From 4da722f3e353ef43acd7ebb825811fdd0225cad8 Mon Sep 17 00:00:00 2001 From: Stypox Date: Wed, 8 Apr 2020 08:10:05 +0200 Subject: [PATCH 1/5] Add newline at end of file To prevent concatenation problems --- docs/scarpet/language/Overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/scarpet/language/Overview.md b/docs/scarpet/language/Overview.md index 0689740f..0ad850f5 100644 --- a/docs/scarpet/language/Overview.md +++ b/docs/scarpet/language/Overview.md @@ -276,4 +276,4 @@ global_foo = floor(rand(10)); check_foo_not_zero(); ... check_foo_not_zero() -> if(global_foo == 0, global_foo = 1) - \ No newline at end of file + From d6d6b69fcb6b940b068c330bc3e2f6a8ab73ddea Mon Sep 17 00:00:00 2001 From: gnembon Date: Sun, 12 Apr 2020 19:42:04 -0300 Subject: [PATCH 2/5] added inhabited_time and player events revolving around damage, death and respawns. --- docs/scarpet/Full.md | 11 +++- docs/scarpet/api/BlocksAndWorldAccess.md | 4 ++ docs/scarpet/api/Events.md | 4 ++ docs/scarpet/resources/editors/idea/2.txt | 1 + docs/scarpet/resources/editors/idea/4.txt | 6 ++- .../scarpet/resources/editors/npp/scarpet.xml | 6 ++- .../DamageTracker_scarpetEventMixin.java | 14 +++++- .../PlayerManager_scarpetEventsMixin.java | 21 ++++++++ .../ServerPlayerEntity_scarpetEventMixin.java | 5 ++ .../java/carpet/script/CarpetEventServer.java | 50 +++++++++++++++++++ .../assets/carpet/scripts/event_test.sc | 35 +++++++++++++ src/main/resources/carpet.mixins.json | 1 + 12 files changed, 154 insertions(+), 4 deletions(-) create mode 100644 src/main/java/carpet/mixins/PlayerManager_scarpetEventsMixin.java diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index 572c8123..baed6c5d 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -276,7 +276,8 @@ global_foo = floor(rand(10)); check_foo_not_zero(); ... check_foo_not_zero() -> if(global_foo == 0, global_foo = 1) -# Variables and Constants + +# Variables and Constants `scarpet` provides a number of constants that can be used literally in scripts @@ -2055,6 +2056,10 @@ Returns generation status as per the ticket system. Can return any value from se can only be stable in a few states: `full`, `features`, `liquid_carvers`, and `structure_starts`. Returns `null` if the chunk is not in memory unless called with optional `true`. +### `inhabited_time(pos)` + +Returns inhabited time for a chunk. + ### `structures(pos), structures(pos, structure_name)` Returns structure information for a given block position. Note that structure information is the same for all the @@ -2872,6 +2877,10 @@ __on_player_interacts_with_block(player, hand, block, face, hitvec) //right cli __on_player_places_block(player, item_tuple, hand, block) // player have just placed the block. __on_player_interacts_with_entity(player, entity, hand) __on_player_attacks_entity(player, entity) +__on_player_takes_damage(player, amount, source, source_entity) +__on_player_deals_damage(player, amount, entity) +__on_player_dies(player) +__on_player_respawns(player) __on_player_rides(player, forward, strafe, jumping, sneaking) __on_player_jumps(player) __on_player_deploys_elytra(player) diff --git a/docs/scarpet/api/BlocksAndWorldAccess.md b/docs/scarpet/api/BlocksAndWorldAccess.md index 7c31b2cd..1ec333d7 100644 --- a/docs/scarpet/api/BlocksAndWorldAccess.md +++ b/docs/scarpet/api/BlocksAndWorldAccess.md @@ -519,6 +519,10 @@ Returns generation status as per the ticket system. Can return any value from se can only be stable in a few states: `full`, `features`, `liquid_carvers`, and `structure_starts`. Returns `null` if the chunk is not in memory unless called with optional `true`. +### `inhabited_time(pos)` + +Returns inhabited time for a chunk. + ### `structures(pos), structures(pos, structure_name)` Returns structure information for a given block position. Note that structure information is the same for all the diff --git a/docs/scarpet/api/Events.md b/docs/scarpet/api/Events.md index aa9f1c98..6408ac94 100644 --- a/docs/scarpet/api/Events.md +++ b/docs/scarpet/api/Events.md @@ -33,6 +33,10 @@ __on_player_interacts_with_block(player, hand, block, face, hitvec) //right cli __on_player_places_block(player, item_tuple, hand, block) // player have just placed the block. __on_player_interacts_with_entity(player, entity, hand) __on_player_attacks_entity(player, entity) +__on_player_takes_damage(player, amount, source, source_entity) +__on_player_deals_damage(player, amount, entity) +__on_player_dies(player) +__on_player_respawns(player) __on_player_rides(player, forward, strafe, jumping, sneaking) __on_player_jumps(player) __on_player_deploys_elytra(player) diff --git a/docs/scarpet/resources/editors/idea/2.txt b/docs/scarpet/resources/editors/idea/2.txt index bbdf2f18..c98522d1 100644 --- a/docs/scarpet/resources/editors/idea/2.txt +++ b/docs/scarpet/resources/editors/idea/2.txt @@ -30,6 +30,7 @@ hardness harvest in_dimension in_slime_chunk +inhabited_time inventory_find inventory_get inventory_remove diff --git a/docs/scarpet/resources/editors/idea/4.txt b/docs/scarpet/resources/editors/idea/4.txt index 6c37a65a..6200e26c 100644 --- a/docs/scarpet/resources/editors/idea/4.txt +++ b/docs/scarpet/resources/editors/idea/4.txt @@ -25,4 +25,8 @@ __on_player_wakes_up __on_statistic __on_tick __on_tick_ender -__on_tick_nether \ No newline at end of file +__on_tick_nether +__on_player_takes_damage +__on_player_deals_damage +__on_player_dies +__on_player_respawns \ No newline at end of file diff --git a/docs/scarpet/resources/editors/npp/scarpet.xml b/docs/scarpet/resources/editors/npp/scarpet.xml index 332d1030..8c06f293 100644 --- a/docs/scarpet/resources/editors/npp/scarpet.xml +++ b/docs/scarpet/resources/editors/npp/scarpet.xml @@ -54,7 +54,7 @@ hardness blast_resistance top loaded suffocates power ticks_randomly update block_tick random_tick in_slime_chunk set without_updates blocks_movement block_sound material map_colour property block_properties block_data poi set_poi - place_item set_biome biome loaded_status generation_status chunk_tickets + place_item set_biome biome loaded_status generation_status inhabited_time chunk_tickets structures structure_references set_structure reset_chunk scoreboard scoreboard_add scoreboard_remove scoreboard_display @@ -104,6 +104,10 @@ __on_tick __on_tick_ender __on_tick_nether + __on_player_takes_damage + __on_player_deals_damage + __on_player_dies + __on_player_respawns $ 00' 01\ 02' 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 diff --git a/src/main/java/carpet/mixins/DamageTracker_scarpetEventMixin.java b/src/main/java/carpet/mixins/DamageTracker_scarpetEventMixin.java index 6f6a7d62..3ac352d9 100644 --- a/src/main/java/carpet/mixins/DamageTracker_scarpetEventMixin.java +++ b/src/main/java/carpet/mixins/DamageTracker_scarpetEventMixin.java @@ -5,6 +5,7 @@ import carpet.script.EntityEventsGroup; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.damage.DamageTracker; +import net.minecraft.server.network.ServerPlayerEntity; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -12,8 +13,11 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import static carpet.script.CarpetEventServer.Event.PLAYER_DEALS_DAMAGE; +import static carpet.script.CarpetEventServer.Event.PLAYER_TAKES_DAMAGE; + @Mixin(DamageTracker.class) -public class DamageTracker_scarpetEventMixin +public abstract class DamageTracker_scarpetEventMixin { @Shadow @Final private LivingEntity entity; @@ -21,5 +25,13 @@ public class DamageTracker_scarpetEventMixin private void onDamageTaken(DamageSource damageSource_1, float float_1, float float_2, CallbackInfo ci) { ((EntityInterface)entity).getEventContainer().onEvent(EntityEventsGroup.EntityEventType.ON_DAMAGE, entity, float_2, damageSource_1); + if (entity instanceof ServerPlayerEntity && PLAYER_TAKES_DAMAGE.isNeeded()) + { + PLAYER_TAKES_DAMAGE.onDamage(entity, float_2, damageSource_1); + } + if (damageSource_1.getAttacker() instanceof ServerPlayerEntity && PLAYER_DEALS_DAMAGE.isNeeded()) + { + PLAYER_DEALS_DAMAGE.onDamage(entity, float_2, damageSource_1); + } } } diff --git a/src/main/java/carpet/mixins/PlayerManager_scarpetEventsMixin.java b/src/main/java/carpet/mixins/PlayerManager_scarpetEventsMixin.java new file mode 100644 index 00000000..9b03218d --- /dev/null +++ b/src/main/java/carpet/mixins/PlayerManager_scarpetEventsMixin.java @@ -0,0 +1,21 @@ +package carpet.mixins; + +import net.minecraft.server.PlayerManager; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.world.dimension.DimensionType; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import static carpet.script.CarpetEventServer.Event.PLAYER_RESPAWNS; + +@Mixin(PlayerManager.class) +public class PlayerManager_scarpetEventsMixin +{ + @Inject(method = "respawnPlayer", at = @At("HEAD")) + private void onRespawn(ServerPlayerEntity player, DimensionType dimension, boolean alive, CallbackInfoReturnable cir) + { + PLAYER_RESPAWNS.onPlayerEvent(player); + } +} diff --git a/src/main/java/carpet/mixins/ServerPlayerEntity_scarpetEventMixin.java b/src/main/java/carpet/mixins/ServerPlayerEntity_scarpetEventMixin.java index c5beb8da..17bbd74d 100644 --- a/src/main/java/carpet/mixins/ServerPlayerEntity_scarpetEventMixin.java +++ b/src/main/java/carpet/mixins/ServerPlayerEntity_scarpetEventMixin.java @@ -17,6 +17,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import static carpet.script.CarpetEventServer.Event.PLAYER_DIES; import static carpet.script.CarpetEventServer.Event.PLAYER_FINISHED_USING_ITEM; import static carpet.script.CarpetEventServer.Event.STATISTICS; @@ -61,6 +62,10 @@ public abstract class ServerPlayerEntity_scarpetEventMixin extends PlayerEntity private void onDeathEvent(DamageSource source, CallbackInfo ci) { ((EntityInterface)this).getEventContainer().onEvent(EntityEventsGroup.EntityEventType.ON_DEATH, this, source.name); + if (PLAYER_DIES.isNeeded()) + { + PLAYER_DIES.onPlayerEvent((ServerPlayerEntity) (Object)this); + } } @Redirect(method = "method_14218", at = @At( diff --git a/src/main/java/carpet/script/CarpetEventServer.java b/src/main/java/carpet/script/CarpetEventServer.java index e6c87413..447396c0 100644 --- a/src/main/java/carpet/script/CarpetEventServer.java +++ b/src/main/java/carpet/script/CarpetEventServer.java @@ -12,6 +12,7 @@ import carpet.script.value.StringValue; import carpet.script.value.Value; import carpet.utils.Messenger; import net.minecraft.block.BlockState; +import net.minecraft.entity.damage.DamageSource; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.entity.Entity; import net.minecraft.server.network.ServerPlayerEntity; @@ -479,6 +480,53 @@ public class CarpetEventServer handler.call( () -> Collections.singletonList(((c, t) -> new EntityValue(player))), player::getCommandSource); } }, + PLAYER_TAKES_DAMAGE("player_takes_damage", 4, false) + { + @Override + public void onDamage(Entity target, float amount, DamageSource source) + { + handler.call( () -> + { + return Arrays.asList( + ((c, t) -> new EntityValue(target)), + ((c, t) -> new NumericValue(amount)), + ((c, t) ->new StringValue(source.getName())), + ((c, t) -> source.getAttacker()==null?Value.NULL:new EntityValue(source.getAttacker())) + ); + }, target::getCommandSource); + } + }, + PLAYER_DEALS_DAMAGE("player_deals_damage", 3, false) + { + @Override + public void onDamage(Entity target, float amount, DamageSource source) + { + handler.call( () -> + { + return Arrays.asList( + ((c, t) -> new EntityValue(source.getAttacker())), + ((c, t) -> new NumericValue(amount)), + ((c, t) -> new EntityValue(target)) + ); + }, () -> source.getAttacker().getCommandSource()); + } + }, + PLAYER_DIES("player_dies", 1, false) + { + @Override + public void onPlayerEvent(ServerPlayerEntity player) + { + handler.call( () -> Collections.singletonList(((c, t) -> new EntityValue(player))), player::getCommandSource); + } + }, + PLAYER_RESPAWNS("player_respawns", 1, false) + { + @Override + public void onPlayerEvent(ServerPlayerEntity player) + { + handler.call( () -> Collections.singletonList(((c, t) -> new EntityValue(player))), player::getCommandSource); + } + }, STATISTICS("statistic", 4, false) { private Identifier getStatId(Stat stat) @@ -551,6 +599,8 @@ public class CarpetEventServer public void onBlockBroken(ServerPlayerEntity player, BlockPos pos, BlockState previousBS) { } public void onBlockPlaced(ServerPlayerEntity player, BlockPos pos, Hand enumhand, ItemStack itemstack) { } public void onEntityAction(ServerPlayerEntity player, Entity entity, Hand enumhand) { } + public void onDamage(Entity target, float amount, DamageSource source) { } + public void onWorldEvent(ServerWorld world, BlockPos pos) { } public void onWorldEventFlag(ServerWorld world, BlockPos pos, int flag) { } } diff --git a/src/main/resources/assets/carpet/scripts/event_test.sc b/src/main/resources/assets/carpet/scripts/event_test.sc index 80e2346e..8e3d937a 100644 --- a/src/main/resources/assets/carpet/scripts/event_test.sc +++ b/src/main/resources/assets/carpet/scripts/event_test.sc @@ -185,3 +185,38 @@ __on_player_places_block(player, item_tuple, hand, block) -> print(' > count: '+count); print(' > nbt: '+nbt); ); + +__on_player_takes_damage(player, amount, source, entity) -> +( + print(''); + print('__on_player_takes_damage(player, amount, source, source_entity)'); + print('player takes damage:'); + print(' - player: '+player); + print(' - amount: '+str('%.2f',amount)); + print(' - source: '+source); + print(' - source_entity: '+entity); +); + +__on_player_deals_damage(player, amount, entity) -> +( + print(''); + print('__on_player_deals_damage(player, amount, target)'); + print('player deals damage:'); + print(' - player: '+player); + print(' - amount: '+str('%.2f',amount)); + print(' - target: '+entity); +); + +__on_player_dies(player) -> +( + print(''); + print('__on_player_dies(player)'); + print('Player '+player+' dies.') +); + +__on_player_respawns(player) -> +( + print(''); + print('__on_player_respawns(player)'); + print('Player '+player+' respawns.') +); diff --git a/src/main/resources/carpet.mixins.json b/src/main/resources/carpet.mixins.json index 25c2356e..1fc02972 100644 --- a/src/main/resources/carpet.mixins.json +++ b/src/main/resources/carpet.mixins.json @@ -140,6 +140,7 @@ "ServerPlayerEntity_scarpetEventMixin", "FallingBlockEntity_scarpetEventsMixin", "BlockItem_scarpetEventMixin", + "PlayerManager_scarpetEventsMixin", "ChunkTicketManager_scarpetMixin", "ServerChunkManager_scarpetMixin", From 66e361167d34d5b8ab7efc3141a7412c3a5d7db8 Mon Sep 17 00:00:00 2001 From: gnembon Date: Sun, 12 Apr 2020 20:26:49 -0300 Subject: [PATCH 3/5] didn't treat appending to containers the same way for variables as well as for container lvalues. Fixes #209 --- src/main/java/carpet/script/Expression.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index cfb3380b..f03e4855 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -657,9 +657,18 @@ public class Expression throw new InternalExpressionException("Failed to resolve left hand side of the += operation"); } Value key = ((LContainerValue) v1).getAddress(); - Value res = cvi.get(key).add(v2); - cvi.put(key, res); - return (cc, tt) -> res; + Value value = cvi.get(key); + if (value instanceof ListValue || value instanceof MapValue) + { + ((AbstractListValue) value).append(v2); + return (cc, tt) -> value; + } + else + { + Value res = value.add(v2); + cvi.put(key, res); + return (cc, tt) -> res; + } } v1.assertAssignable(); String varname = v1.getVariable(); From 19a01bee1be79e9ddc8f9056bc30dd9b9d15c02b Mon Sep 17 00:00:00 2001 From: gnembon Date: Sun, 12 Apr 2020 20:47:39 -0300 Subject: [PATCH 4/5] cannot shadow other players if you are not OP. Fixes #208 --- src/main/java/carpet/commands/PlayerCommand.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/carpet/commands/PlayerCommand.java b/src/main/java/carpet/commands/PlayerCommand.java index 0ceba52d..e6d99c12 100644 --- a/src/main/java/carpet/commands/PlayerCommand.java +++ b/src/main/java/carpet/commands/PlayerCommand.java @@ -296,6 +296,14 @@ public class PlayerCommand Messenger.m(context.getSource(), "r Cannot shadow fake players"); return 0; } + ServerPlayerEntity sendingPlayer = null; + try + { + sendingPlayer = context.getSource().getPlayer(); + } + catch (CommandSyntaxException ignored) { } + + if (sendingPlayer!=player && cantManipulate(context)) return 0; EntityPlayerMPFake.createShadow(player.server, player); return 1; } From 2a1d5542f18ccfe93910724a0363da90401e1d63 Mon Sep 17 00:00:00 2001 From: gnembon Date: Mon, 13 Apr 2020 00:59:55 -0300 Subject: [PATCH 5/5] just to change from disabling spawn chunks to control over its size. Removes disableSpawnChunks, adds spawnChunksSize. Fixes #192 --- src/main/java/carpet/CarpetSettings.java | 80 +++++++------------ .../fakes/ChunkTicketManagerInterface.java | 12 +++ .../fakes/ServerChunkManagerInterface.java | 8 ++ .../ChunkTicketManager_scarpetMixin.java | 16 +++- .../ChunkTicketManager_spawnChunksMixin.java | 60 ++++++++++++++ .../mixins/MinecraftServer_coreMixin.java | 9 +++ .../mixins/ServerChunkManagerMixin.java | 12 ++- .../ServerChunkManager_scarpetMixin.java | 13 --- .../mixins/ServerWorld_spawnChunksMixin.java | 17 ++++ .../java/carpet/script/CarpetExpression.java | 6 +- src/main/java/carpet/utils/SpawnChunks.java | 16 ++++ src/main/resources/carpet.mixins.json | 4 +- 12 files changed, 178 insertions(+), 75 deletions(-) create mode 100644 src/main/java/carpet/fakes/ChunkTicketManagerInterface.java create mode 100644 src/main/java/carpet/fakes/ServerChunkManagerInterface.java create mode 100644 src/main/java/carpet/mixins/ChunkTicketManager_spawnChunksMixin.java delete mode 100644 src/main/java/carpet/mixins/ServerChunkManager_scarpetMixin.java create mode 100644 src/main/java/carpet/mixins/ServerWorld_spawnChunksMixin.java create mode 100644 src/main/java/carpet/utils/SpawnChunks.java diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index e1fb609b..cb9a3598 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -5,13 +5,11 @@ import carpet.settings.Rule; import carpet.settings.SettingsManager; import carpet.settings.Validator; import carpet.utils.Messenger; +import carpet.utils.SpawnChunks; import net.minecraft.server.MinecraftServer; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.dedicated.DedicatedServer; -import net.minecraft.server.world.ChunkTicketType; -import net.minecraft.server.world.ServerChunkManager; import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.Unit; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; import net.minecraft.util.math.ChunkPos; @@ -236,13 +234,6 @@ public class CarpetSettings @Rule( desc = "Pistons can push block entities, like hoppers, chests etc.", category = {EXPERIMENTAL, FEATURE} ) public static boolean movableBlockEntities = false; - /*@Rule( - desc = "Orange stained glass behaves like slime, but doesn't stick to it", - extra = "Only available for 1.14. in 1.15 use honey instead", - category = {EXPERIMENTAL, FEATURE} - ) - public static boolean honeySlime = false;*/ - @Rule( desc = "Saplings turn into dead shrubs in hot climates and no water access", category = FEATURE ) public static boolean desertShrubs = false; @@ -356,9 +347,6 @@ public class CarpetSettings @Rule(desc = "Pistons, Glass and Sponge can be broken faster with their appropriate tools", category = SURVIVAL) public static boolean missingTools = false; - //@Rule(desc = "Alternative, persistent caching strategy for nether portals", category = {SURVIVAL, CREATIVE}) - //public static boolean portalCaching = false; // ineffective in 1.15 - @Rule(desc = "fill/clone/setblock and structure blocks cause block updates", category = CREATIVE) public static boolean fillUpdates = true; @@ -509,13 +497,9 @@ public class CarpetSettings ) public static int viewDistance = 0; - private static class DisableSpawnChunksValidator extends Validator { - @Override public Boolean validate(ServerCommandSource source, ParsedRule currentRule, Boolean newValue, String string) { - if (currentRule.get().booleanValue() == newValue.booleanValue()) - { - //must been some startup thing - return newValue; - } + public static class ChangeSpawnChunksValidator extends Validator { + public static void changeSpawnSize(int size) + { ServerWorld overworld = CarpetServer.minecraft_server.getWorld(DimensionType.OVERWORLD); if (overworld != null) { ChunkPos centerChunk = new ChunkPos(new BlockPos( @@ -523,40 +507,37 @@ public class CarpetSettings overworld.getLevelProperties().getSpawnY(), overworld.getLevelProperties().getSpawnZ() )); - ServerChunkManager chunkManager = (ServerChunkManager) overworld.getChunkManager(); - - chunkManager.removeTicket(ChunkTicketType.START, centerChunk, 11, Unit.INSTANCE); - if (!newValue) - { - chunkManager.addTicket(ChunkTicketType.START, centerChunk, 11, Unit.INSTANCE); - } + SpawnChunks.changeSpawnChunks(overworld.getChunkManager(), centerChunk, size); + } + } + @Override public Integer validate(ServerCommandSource source, ParsedRule currentRule, Integer newValue, String string) { + if (newValue < 0 || newValue > 32) + { + Messenger.m(source, "r spawn chunk size has to be between 0 and 32"); + return null; + } + if (currentRule.get().intValue() == newValue.intValue()) + { + //must been some startup thing + return newValue; + } + ServerWorld currentOverworld = CarpetServer.minecraft_server.getWorld(DimensionType.OVERWORLD); + if (currentOverworld != null) + { + changeSpawnSize(newValue); } return newValue; } } @Rule( - desc = "Allows spawn chunks to unload", + desc = "Changes size of spawn chunks", + extra = {"Defines new radius", "setting it to 0 - disables spawn chunks"}, category = CREATIVE, - validate = DisableSpawnChunksValidator.class - ) - public static boolean disableSpawnChunks = false; - - /*private static class KelpLimit extends Validator - { - @Override public Integer validate(ServerCommandSource source, ParsedRule currentRule, Integer newValue, String string) { - return (newValue>=0 && newValue <=25)?newValue:null; - } - @Override - public String description() { return "You must choose a value from 0 to 25. 25 and all natural kelp can grow 25 blocks, choose 0 to make all generated kelp not to grow";} - } - @Rule( - desc = "limits growth limit of newly naturally generated kelp to this amount of blocks", - options = {"0", "2", "25"}, - category = FEATURE, strict = false, - validate = KelpLimit.class + options = {"0", "11"}, + validate = ChangeSpawnChunksValidator.class ) - public static int kelpGenerationGrowthLimit = 25;*/ + public static int spawnChunksSize = 11; @Rule(desc = "Coral structures will grow with bonemeal from coral plants", category = FEATURE) public static boolean renewableCoral = false; @@ -573,13 +554,6 @@ public class CarpetSettings @Rule(desc = "Spawning requires much less CPU and Memory", category = OPTIMIZATION) public static boolean lagFreeSpawning = false; - - //@Rule( - // desc = "Prevents horses and other mobs to wander into the distance after dismounting", - // extra = "Fixes issues with various Joergens wandering off and disappearing client-side", - // category = BUGFIX - //) - //public static boolean horseWanderingFix = false; @Rule( desc = "Allows structure mobs to spawn in flat worlds", diff --git a/src/main/java/carpet/fakes/ChunkTicketManagerInterface.java b/src/main/java/carpet/fakes/ChunkTicketManagerInterface.java new file mode 100644 index 00000000..37c4ec65 --- /dev/null +++ b/src/main/java/carpet/fakes/ChunkTicketManagerInterface.java @@ -0,0 +1,12 @@ +package carpet.fakes; + +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import net.minecraft.server.world.ChunkTicket; +import net.minecraft.util.SortedArraySet; +import net.minecraft.util.math.ChunkPos; + +public interface ChunkTicketManagerInterface +{ + void changeSpawnChunks(ChunkPos pos, int distance); + Long2ObjectOpenHashMap>> getTicketsByPosition(); +} diff --git a/src/main/java/carpet/fakes/ServerChunkManagerInterface.java b/src/main/java/carpet/fakes/ServerChunkManagerInterface.java new file mode 100644 index 00000000..9f7daddc --- /dev/null +++ b/src/main/java/carpet/fakes/ServerChunkManagerInterface.java @@ -0,0 +1,8 @@ +package carpet.fakes; + +import net.minecraft.server.world.ChunkTicketManager; + +public interface ServerChunkManagerInterface +{ + ChunkTicketManager getTicketManager(); +} diff --git a/src/main/java/carpet/mixins/ChunkTicketManager_scarpetMixin.java b/src/main/java/carpet/mixins/ChunkTicketManager_scarpetMixin.java index 6d52eebd..72621cdd 100644 --- a/src/main/java/carpet/mixins/ChunkTicketManager_scarpetMixin.java +++ b/src/main/java/carpet/mixins/ChunkTicketManager_scarpetMixin.java @@ -1,15 +1,23 @@ package carpet.mixins; +import carpet.fakes.ChunkTicketManagerInterface; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import net.minecraft.server.world.ChunkTicket; import net.minecraft.server.world.ChunkTicketManager; import net.minecraft.util.SortedArraySet; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.Shadow; @Mixin(ChunkTicketManager.class) -public interface ChunkTicketManager_scarpetMixin +public abstract class ChunkTicketManager_scarpetMixin implements ChunkTicketManagerInterface { - @Accessor - Long2ObjectOpenHashMap>> getTicketsByPosition(); + @Shadow @Final private Long2ObjectOpenHashMap>> ticketsByPosition; + + @Override + public Long2ObjectOpenHashMap>> getTicketsByPosition() + { + return ticketsByPosition; + } + } diff --git a/src/main/java/carpet/mixins/ChunkTicketManager_spawnChunksMixin.java b/src/main/java/carpet/mixins/ChunkTicketManager_spawnChunksMixin.java new file mode 100644 index 00000000..53987e95 --- /dev/null +++ b/src/main/java/carpet/mixins/ChunkTicketManager_spawnChunksMixin.java @@ -0,0 +1,60 @@ +package carpet.mixins; + +import carpet.fakes.ChunkTicketManagerInterface; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import net.minecraft.server.world.ChunkTicket; +import net.minecraft.server.world.ChunkTicketManager; +import net.minecraft.server.world.ChunkTicketType; +import net.minecraft.util.SortedArraySet; +import net.minecraft.util.Unit; +import net.minecraft.util.math.ChunkPos; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Iterator; + +@Mixin(ChunkTicketManager.class) +public abstract class ChunkTicketManager_spawnChunksMixin implements ChunkTicketManagerInterface +{ + + @Shadow protected abstract SortedArraySet> getTicketSet(long position); + + @Shadow @Final private Long2ObjectOpenHashMap>> ticketsByPosition; + + @Shadow public abstract void removeTicket(ChunkTicketType type, ChunkPos pos, int radius, T argument); + + @Shadow protected abstract void removeTicket(long pos, ChunkTicket ticket); + + @Shadow public abstract void addTicket(ChunkTicketType type, ChunkPos pos, int radius, T argument); + + @Override + public void changeSpawnChunks(ChunkPos chunkPos, int distance) + { + long pos = chunkPos.toLong(); + SortedArraySet> set = ticketsByPosition.get(pos); + ChunkTicket existingTicket = null; + if (set != null) + { + Iterator> iter = set.iterator(); + while(iter.hasNext()) + { + ChunkTicket ticket = iter.next(); + if (ticket.getType() == ChunkTicketType.START) + { + existingTicket = ticket; + iter.remove(); + } + } + set.add(existingTicket); + } + // the reason we are removing the ticket this way is that there are sideeffects of removal + if (existingTicket != null) + { + removeTicket(pos, existingTicket); + } + // set optionally new spawn ticket + if (distance > 0) + addTicket(ChunkTicketType.START, chunkPos, distance, Unit.INSTANCE); + } +} diff --git a/src/main/java/carpet/mixins/MinecraftServer_coreMixin.java b/src/main/java/carpet/mixins/MinecraftServer_coreMixin.java index 5d5e330e..b11f9d8c 100644 --- a/src/main/java/carpet/mixins/MinecraftServer_coreMixin.java +++ b/src/main/java/carpet/mixins/MinecraftServer_coreMixin.java @@ -1,8 +1,10 @@ package carpet.mixins; import carpet.CarpetServer; +import carpet.CarpetSettings; import com.google.gson.JsonElement; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.WorldGenerationProgressListener; import net.minecraft.world.level.LevelGeneratorType; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -41,4 +43,11 @@ public abstract class MinecraftServer_coreMixin { CarpetServer.onServerClosed((MinecraftServer) (Object) this); } + + @Inject(method = "prepareStartRegion", at = @At("RETURN")) + private void afterSpawnCreated(WorldGenerationProgressListener worldGenerationProgressListener, CallbackInfo ci) + { + if (CarpetSettings.spawnChunksSize != 11) + CarpetSettings.ChangeSpawnChunksValidator.changeSpawnSize(CarpetSettings.spawnChunksSize); + } } diff --git a/src/main/java/carpet/mixins/ServerChunkManagerMixin.java b/src/main/java/carpet/mixins/ServerChunkManagerMixin.java index 109c9bb5..ce4b9132 100644 --- a/src/main/java/carpet/mixins/ServerChunkManagerMixin.java +++ b/src/main/java/carpet/mixins/ServerChunkManagerMixin.java @@ -1,8 +1,10 @@ package carpet.mixins; +import carpet.fakes.ServerChunkManagerInterface; import carpet.utils.SpawnReporter; import it.unimi.dsi.fastutil.objects.Object2IntMap; import net.minecraft.entity.EntityCategory; +import net.minecraft.server.world.ChunkTicketManager; import net.minecraft.server.world.ServerChunkManager; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; @@ -24,12 +26,20 @@ import java.util.HashMap; import java.util.HashSet; @Mixin(ServerChunkManager.class) -public abstract class ServerChunkManagerMixin +public abstract class ServerChunkManagerMixin implements ServerChunkManagerInterface { @Shadow @Final private ServerWorld world; @Shadow @Final private static int CHUNKS_ELIGIBLE_FOR_SPAWNING; + @Shadow @Final private ChunkTicketManager ticketManager; + + @Override // shared between scarpet and spawnChunks setting + public ChunkTicketManager getTicketManager() + { + return ticketManager; + } + @Inject( method = "tickChunks", locals = LocalCapture.CAPTURE_FAILHARD, diff --git a/src/main/java/carpet/mixins/ServerChunkManager_scarpetMixin.java b/src/main/java/carpet/mixins/ServerChunkManager_scarpetMixin.java deleted file mode 100644 index 9cec83e8..00000000 --- a/src/main/java/carpet/mixins/ServerChunkManager_scarpetMixin.java +++ /dev/null @@ -1,13 +0,0 @@ -package carpet.mixins; - -import net.minecraft.server.world.ChunkTicketManager; -import net.minecraft.server.world.ServerChunkManager; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(ServerChunkManager.class) -public interface ServerChunkManager_scarpetMixin -{ - @Accessor - ChunkTicketManager getTicketManager(); -} diff --git a/src/main/java/carpet/mixins/ServerWorld_spawnChunksMixin.java b/src/main/java/carpet/mixins/ServerWorld_spawnChunksMixin.java new file mode 100644 index 00000000..a462a6f6 --- /dev/null +++ b/src/main/java/carpet/mixins/ServerWorld_spawnChunksMixin.java @@ -0,0 +1,17 @@ +package carpet.mixins; + +import carpet.CarpetSettings; +import net.minecraft.server.world.ServerWorld; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.Constant; +import org.spongepowered.asm.mixin.injection.ModifyConstant; + +@Mixin(ServerWorld.class) +public class ServerWorld_spawnChunksMixin +{ + @ModifyConstant(method = "setSpawnPos", constant = @Constant(intValue = 11), expect = 2) + private int pushLimit(int original) + { + return CarpetSettings.spawnChunksSize; + } +} diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 63615671..f246d4fb 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -1,14 +1,14 @@ package carpet.script; import carpet.CarpetServer; +import carpet.fakes.ChunkTicketManagerInterface; import carpet.fakes.MinecraftServerInterface; import carpet.fakes.BiomeArrayInterface; +import carpet.fakes.ServerChunkManagerInterface; import carpet.fakes.StatTypeInterface; import carpet.fakes.ThreadedAnvilChunkStorageInterface; import carpet.helpers.FeatureGenerator; -import carpet.mixins.ChunkTicketManager_scarpetMixin; import carpet.mixins.PointOfInterest_scarpetMixin; -import carpet.mixins.ServerChunkManager_scarpetMixin; import carpet.script.Fluff.TriFunction; import carpet.script.bundled.Module; import carpet.CarpetSettings; @@ -708,7 +708,7 @@ public class CarpetExpression { ServerWorld world = ((CarpetContext) c).s.getWorld(); Long2ObjectOpenHashMap>> levelTickets = ( - (ChunkTicketManager_scarpetMixin) ((ServerChunkManager_scarpetMixin) world.getChunkManager()) + (ChunkTicketManagerInterface) ((ServerChunkManagerInterface) world.getChunkManager()) .getTicketManager() ).getTicketsByPosition(); List res = new ArrayList<>(); diff --git a/src/main/java/carpet/utils/SpawnChunks.java b/src/main/java/carpet/utils/SpawnChunks.java new file mode 100644 index 00000000..e97cb531 --- /dev/null +++ b/src/main/java/carpet/utils/SpawnChunks.java @@ -0,0 +1,16 @@ +package carpet.utils; + +import carpet.fakes.ChunkTicketManagerInterface; +import carpet.fakes.ServerChunkManagerInterface; +import net.minecraft.server.world.ChunkTicketManager; +import net.minecraft.server.world.ServerChunkManager; +import net.minecraft.util.math.ChunkPos; + +public class SpawnChunks +{ + public static void changeSpawnChunks(ServerChunkManager chunkManager, ChunkPos pos, int size) + { + ChunkTicketManager ticketManager = ((ServerChunkManagerInterface)chunkManager).getTicketManager(); + ((ChunkTicketManagerInterface)ticketManager).changeSpawnChunks(pos, size); + } +} diff --git a/src/main/resources/carpet.mixins.json b/src/main/resources/carpet.mixins.json index 1fc02972..ea11cc6d 100644 --- a/src/main/resources/carpet.mixins.json +++ b/src/main/resources/carpet.mixins.json @@ -29,6 +29,9 @@ "ThreadedAnvilChunkStorage_scarpetChunkCreationMixin", "ChunkHolder_scarpetChunkCreationMixin", + "ChunkTicketManager_spawnChunksMixin", + "ServerWorld_spawnChunksMixin", + "MobEntityMixin", "ServerWorld_unloadedEntityMixin", "EntityTrackerEntry_leashFixMixin", @@ -143,7 +146,6 @@ "PlayerManager_scarpetEventsMixin", "ChunkTicketManager_scarpetMixin", - "ServerChunkManager_scarpetMixin", "StatType_scarpetMixin", "PointOfInterest_scarpetMixin", "ServerWorld_scarpetEventMixin",