From cdf7445e205ea573890076063f33b6c972d6af39 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 8 Apr 2020 01:28:43 -0300 Subject: [PATCH 001/198] counter results sorted by rate --- src/main/java/carpet/helpers/HopperCounter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/carpet/helpers/HopperCounter.java b/src/main/java/carpet/helpers/HopperCounter.java index d31876a4..4c7163c5 100644 --- a/src/main/java/carpet/helpers/HopperCounter.java +++ b/src/main/java/carpet/helpers/HopperCounter.java @@ -126,7 +126,7 @@ public class HopperCounter color, ticks*1.0/(20*60), (realTime?" - real time":""), total, total*1.0*(20*60*60)/ticks), "nb [X]", "^g reset", "!/counter "+color+" reset" )); - items.addAll(counter.object2LongEntrySet().stream().map(e -> + items.addAll(counter.object2LongEntrySet().stream().sorted((e, f) -> Long.compare(f.getLongValue(), e.getLongValue())).map(e -> { BaseText itemName = new TranslatableText(e.getKey().getTranslationKey()); long count = e.getLongValue(); From 4da722f3e353ef43acd7ebb825811fdd0225cad8 Mon Sep 17 00:00:00 2001 From: Stypox Date: Wed, 8 Apr 2020 08:10:05 +0200 Subject: [PATCH 002/198] 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 e1948a2fe0f2abcf6060fa6847b309d4a15284fb Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 8 Apr 2020 12:31:08 -0300 Subject: [PATCH 003/198] 1.3.18 --- gradle.properties | 2 +- src/main/java/carpet/CarpetSettings.java | 2 +- src/main/resources/fabric.mod.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 03cd20b9..5dc95d10 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ org.gradle.jvmargs=-Xmx1G loader_version=0.7.8+build.188 # Mod Properties - mod_version = 1.3.17+v200401 + mod_version = 1.3.18+v200408 maven_group = carpet archives_base_name = fabric-carpet diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index 79e32445..e1fb609b 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -35,7 +35,7 @@ import static carpet.settings.RuleCategory.CLIENT; @SuppressWarnings("CanBeFinal") public class CarpetSettings { - public static final String carpetVersion = "1.3.17+v200401"; + public static final String carpetVersion = "1.3.18+v200408"; public static final Logger LOG = LogManager.getLogger(); public static boolean skipGenerationChecks = false; public static boolean impendingFillSkipUpdates = false; diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index e0f72738..fe4203f1 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,7 +1,7 @@ { "schemaVersion": 1, "id": "carpet", - "version": "1.3.17", + "version": "1.3.18", "name": "Carpet Mod in Fabric", "description": "Carpet made out of fabric", From dd4f2aa12d4f4953a4cee7bbbf9e688161f7a445 Mon Sep 17 00:00:00 2001 From: X-Green <35984104+X-Green@users.noreply.github.com> Date: Sun, 12 Apr 2020 10:55:22 +0800 Subject: [PATCH 004/198] More infomation in TNT logging #1 --- .../carpet/logging/logHelpers/TNTLogHelper.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/carpet/logging/logHelpers/TNTLogHelper.java b/src/main/java/carpet/logging/logHelpers/TNTLogHelper.java index 7e51f743..41078113 100644 --- a/src/main/java/carpet/logging/logHelpers/TNTLogHelper.java +++ b/src/main/java/carpet/logging/logHelpers/TNTLogHelper.java @@ -9,6 +9,8 @@ public class TNTLogHelper { public boolean initialized; private double primedX, primedY, primedZ; + private static long lastGametime = 0; + private static int tntCount = 0; private Vec3d primedAngle; /** * Runs when the TNT is primed. Expects the position and motion angle of the TNT. @@ -24,18 +26,30 @@ public class TNTLogHelper /** * Runs when the TNT explodes. Expects the position of the TNT. */ - public void onExploded(double x, double y, double z) + public void onExploded(double x, double y, double z, long gametime) { + if (!(lastGametime == gametime)){ + tntCount = 0; + lastGametime = gametime; + } + tntCount++; LoggerRegistry.getLogger("tnt").log( (option) -> { switch (option) { case "brief": return new BaseText[]{Messenger.c( + "g #" + String.valueOf(tntCount), + "m @" + String.valueOf(gametime), + "g : ", "l P ",Messenger.dblt("l",primedX,primedY,primedZ), "w ",Messenger.dblt("l", primedAngle.x, primedAngle.y, primedAngle.z), "r E ",Messenger.dblt("r",x, y, z))}; case "full": return new BaseText[]{Messenger.c( + "g #" + String.valueOf(tntCount), + "m @" + String.valueOf(gametime), + "g : ", + "g #" + String.valueOf(tntCount) + ": ", "l P ",Messenger.dblf("l",primedX,primedY,primedZ), "w ",Messenger.dblf("l", primedAngle.x, primedAngle.y, primedAngle.z), "r E ",Messenger.dblf("r",x, y, z))}; From ec0aecf6b5c564c38d7b5b9a669b42ec91ef9c78 Mon Sep 17 00:00:00 2001 From: X-Green <35984104+X-Green@users.noreply.github.com> Date: Sun, 12 Apr 2020 10:56:06 +0800 Subject: [PATCH 005/198] More infomation in TNT logging #2 --- src/main/java/carpet/mixins/TntEntityMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/carpet/mixins/TntEntityMixin.java b/src/main/java/carpet/mixins/TntEntityMixin.java index 4a296389..2e67b1e5 100644 --- a/src/main/java/carpet/mixins/TntEntityMixin.java +++ b/src/main/java/carpet/mixins/TntEntityMixin.java @@ -72,7 +72,7 @@ public abstract class TntEntityMixin extends Entity implements TntEntityInterfac private void onExplode(CallbackInfo ci) { if (LoggerRegistry.__tnt && logHelper != null) - logHelper.onExploded(getX(), getY(), getZ()); + logHelper.onExploded(getX(), getY(), getZ(), this.world.getTime()); if (mergedTNT > 1) for (int i = 0; i < mergedTNT - 1; i++) From d6d6b69fcb6b940b068c330bc3e2f6a8ab73ddea Mon Sep 17 00:00:00 2001 From: gnembon Date: Sun, 12 Apr 2020 19:42:04 -0300 Subject: [PATCH 006/198] 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 007/198] 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 008/198] 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 009/198] 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", From 07b3029820a99b41a15b784ffea77040e1464bd6 Mon Sep 17 00:00:00 2001 From: gnembon Date: Mon, 13 Apr 2020 02:04:00 -0300 Subject: [PATCH 010/198] added mixer option and defaulted sounds to master. Fixes #201 --- docs/scarpet/Full.md | 9 ++++++--- docs/scarpet/api/Auxiliary.md | 9 ++++++--- src/main/java/carpet/script/CarpetExpression.java | 12 +++++++++++- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index baed6c5d..3668b28f 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -2932,10 +2932,13 @@ Collection of other methods that control smaller, yet still important aspects of ## Sounds -### `sound(name, pos, volume?, pitch?)` +### `sound(name, pos, volume?, pitch?, mixer?)` -Plays a specific sound `name`, at block or position `pos`, with optional `volume` and modified `pitch`. `pos` can be -either a block, triple of coords, or a list of thee numbers. Uses the same options as a corresponding `playsound` command. +Plays a specific sound `name`, at block or position `pos`, with optional `volume` and modified `pitch`, and under +optional `mixer`. Default values for `volume`, `pitch` and `mixer` are `1.0`, `1.0`, and `master`. +Valid mixer options are `master`, `music`, `record`, `weather`, `block`, `hostile`,`neutral`, `player`, `ambient` +and `voice`. `pos` can be either a block, triple of coords, or a list of thee numbers. Uses the same options as a + corresponding `playsound` command. ## Particles diff --git a/docs/scarpet/api/Auxiliary.md b/docs/scarpet/api/Auxiliary.md index 17b1d003..205656ae 100644 --- a/docs/scarpet/api/Auxiliary.md +++ b/docs/scarpet/api/Auxiliary.md @@ -4,10 +4,13 @@ Collection of other methods that control smaller, yet still important aspects of ## Sounds -### `sound(name, pos, volume?, pitch?)` +### `sound(name, pos, volume?, pitch?, mixer?)` -Plays a specific sound `name`, at block or position `pos`, with optional `volume` and modified `pitch`. `pos` can be -either a block, triple of coords, or a list of thee numbers. Uses the same options as a corresponding `playsound` command. +Plays a specific sound `name`, at block or position `pos`, with optional `volume` and modified `pitch`, and under +optional `mixer`. Default values for `volume`, `pitch` and `mixer` are `1.0`, `1.0`, and `master`. +Valid mixer options are `master`, `music`, `record`, `weather`, `block`, `hostile`,`neutral`, `player`, `ambient` +and `voice`. `pos` can be either a block, triple of coords, or a list of thee numbers. Uses the same options as a + corresponding `playsound` command. ## Particles diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index f246d4fb..d78e178a 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -132,6 +132,7 @@ import java.util.Optional; import java.util.UUID; import java.util.function.BiFunction; import java.util.function.Predicate; +import java.util.stream.Collector; import java.util.stream.Collectors; import static carpet.script.utils.WorldTools.canHasChunk; @@ -2378,6 +2379,8 @@ public class CarpetExpression }); } + private static Map mixerMap = Arrays.stream(SoundCategory.values()).collect(Collectors.toMap(SoundCategory::getName, k -> k)); + private void API_AuxiliaryAspects() { this.expr.addLazyFunction("sound", -1, (c, t, lv) -> { @@ -2388,12 +2391,19 @@ public class CarpetExpression throw new InternalExpressionException("No such sound: "+soundName.getPath()); float volume = 1.0F; float pitch = 1.0F; + SoundCategory mixer = SoundCategory.MASTER; if (lv.size() > 0+locator.offset) { volume = (float) NumericValue.asNumber(lv.get(0+locator.offset).evalValue(c)).getDouble(); if (lv.size() > 1+locator.offset) { pitch = (float) NumericValue.asNumber(lv.get(1+locator.offset).evalValue(c)).getDouble(); + if (lv.size() > 2+locator.offset) + { + String mixerName = lv.get(2+locator.offset).evalValue(c).getString(); + mixer = mixerMap.get(mixerName.toLowerCase(Locale.ROOT)); + if (mixer == null) throw new InternalExpressionException(mixerName +" is not a valid mixer name"); + } } } Vec3d vec = locator.vec; @@ -2402,7 +2412,7 @@ public class CarpetExpression for (ServerPlayerEntity player : cc.s.getWorld().getPlayers( (p) -> p.squaredDistanceTo(vec) < d0)) { count++; - player.networkHandler.sendPacket(new PlaySoundIdS2CPacket(soundName, SoundCategory.PLAYERS, vec, volume, pitch)); + player.networkHandler.sendPacket(new PlaySoundIdS2CPacket(soundName, mixer, vec, volume, pitch)); } int totalPlayed = count; return (_c, _t) -> new NumericValue(totalPlayed); From 3e76adbdaaedd4afe5c13e8fed5fad309227b4d2 Mon Sep 17 00:00:00 2001 From: gnembon Date: Tue, 14 Apr 2020 01:28:00 -0300 Subject: [PATCH 011/198] added deep frozen state where chunk tickets will not be expiring as well, preventing chunks from unloading. Fixes #204 --- .../java/carpet/commands/TickCommand.java | 10 +++++--- src/main/java/carpet/helpers/TickSpeed.java | 1 + .../mixins/ChunkTicketManager_tickMixin.java | 23 +++++++++++++++++++ .../MinecraftServer_tickspeedMixin.java | 2 +- src/main/resources/carpet.mixins.json | 1 + 5 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 src/main/java/carpet/mixins/ChunkTicketManager_tickMixin.java diff --git a/src/main/java/carpet/commands/TickCommand.java b/src/main/java/carpet/commands/TickCommand.java index ac65b7bd..cc7dc38c 100644 --- a/src/main/java/carpet/commands/TickCommand.java +++ b/src/main/java/carpet/commands/TickCommand.java @@ -43,7 +43,8 @@ public class TickCommand c.getSource(), getInteger(c,"ticks"), getString(c, "tail command")))))). - then(literal("freeze").executes( (c)-> toggleFreeze(c.getSource()))). + then(literal("freeze").executes( (c)-> toggleFreeze(c.getSource(), false)). + then(literal("deep").executes( (c)-> toggleFreeze(c.getSource(), true)))). then(literal("step"). executes((c) -> step(1)). then(argument("ticks", integer(1,72000)). @@ -95,15 +96,18 @@ public class TickCommand return 1; } - private static int toggleFreeze(ServerCommandSource source) + private static int toggleFreeze(ServerCommandSource source, boolean isDeep) { TickSpeed.is_paused = !TickSpeed.is_paused; if (TickSpeed.is_paused) { - Messenger.m(source, "gi Game is paused"); + TickSpeed.deepFreeze = isDeep; + Messenger.m(source, "gi Game is "+(isDeep?"deeply ":"")+"frozen"); + } else { + TickSpeed.deepFreeze = false; Messenger.m(source, "gi Game runs normally"); } return 1; diff --git a/src/main/java/carpet/helpers/TickSpeed.java b/src/main/java/carpet/helpers/TickSpeed.java index 79d05576..2daf4fd1 100644 --- a/src/main/java/carpet/helpers/TickSpeed.java +++ b/src/main/java/carpet/helpers/TickSpeed.java @@ -25,6 +25,7 @@ public class TickSpeed public static ServerCommandSource tick_warp_sender = null; public static int player_active_timeout = 0; public static boolean process_entities = true; + public static boolean deepFreeze = false; public static boolean is_paused = false; public static boolean is_superHot = false; diff --git a/src/main/java/carpet/mixins/ChunkTicketManager_tickMixin.java b/src/main/java/carpet/mixins/ChunkTicketManager_tickMixin.java new file mode 100644 index 00000000..9b70b707 --- /dev/null +++ b/src/main/java/carpet/mixins/ChunkTicketManager_tickMixin.java @@ -0,0 +1,23 @@ +package carpet.mixins; + +import carpet.helpers.TickSpeed; +import net.minecraft.server.world.ChunkTicketManager; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ChunkTicketManager.class) +public class ChunkTicketManager_tickMixin +{ + @Shadow private long age; + + @Inject(method = "purge", at = @At("HEAD"), cancellable = true) + private void pauseTicketSystem(CallbackInfo ci) + { + // pausing expiry of tickets + // that will prevent also chunks from unloading, so require a deep frozen state + if (!TickSpeed.process_entities && TickSpeed.deepFreeze) age--; + } +} diff --git a/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java b/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java index ac475142..9b695772 100644 --- a/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java +++ b/src/main/java/carpet/mixins/MinecraftServer_tickspeedMixin.java @@ -120,7 +120,7 @@ public abstract class MinecraftServer_tickspeedMixin extends ReentrantThreadExec this.profiler.startTick(); this.profiler.push("tick"); - this.tick(TickSpeed.time_warp_start_time != 0 ? ()->true : this::shouldKeepTicking); + this.tick(TickSpeed.time_warp_start_time != 0 ? ()->!hasRunningTasks() : this::shouldKeepTicking); this.profiler.swap("nextTickWait"); this.field_19249 = true; this.field_19248 = Math.max(Util.getMeasuringTimeMs() + /*50L*/ msThisTick, this.timeReference); diff --git a/src/main/resources/carpet.mixins.json b/src/main/resources/carpet.mixins.json index ea11cc6d..80faf7b8 100644 --- a/src/main/resources/carpet.mixins.json +++ b/src/main/resources/carpet.mixins.json @@ -25,6 +25,7 @@ "ServerWorld_tickMixin", "ServerChunkManager_tickMixin", "ThreadedAnvilChunkStorage_tickMixin", + "ChunkTicketManager_tickMixin", "ThreadedAnvilChunkStorage_scarpetChunkCreationMixin", "ChunkHolder_scarpetChunkCreationMixin", From 4c5b19767e3a903596a18da756821026447b95e4 Mon Sep 17 00:00:00 2001 From: X-Green <35984104+X-Green@users.noreply.github.com> Date: Tue, 14 Apr 2020 16:19:38 +0800 Subject: [PATCH 012/198] Update TNTLogHelper.java --- src/main/java/carpet/logging/logHelpers/TNTLogHelper.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/carpet/logging/logHelpers/TNTLogHelper.java b/src/main/java/carpet/logging/logHelpers/TNTLogHelper.java index 41078113..b968d0b4 100644 --- a/src/main/java/carpet/logging/logHelpers/TNTLogHelper.java +++ b/src/main/java/carpet/logging/logHelpers/TNTLogHelper.java @@ -38,9 +38,6 @@ public class TNTLogHelper { case "brief": return new BaseText[]{Messenger.c( - "g #" + String.valueOf(tntCount), - "m @" + String.valueOf(gametime), - "g : ", "l P ",Messenger.dblt("l",primedX,primedY,primedZ), "w ",Messenger.dblt("l", primedAngle.x, primedAngle.y, primedAngle.z), "r E ",Messenger.dblt("r",x, y, z))}; From 8dbf269fdeb336cfdc5df49b5072b64b36dfeee8 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 15 Apr 2020 01:58:46 -0300 Subject: [PATCH 013/198] added world_time and day_time. Add ability to store app data in shared space. as well as store in file hierarchies. Fixes #215 --- docs/scarpet/Full.md | 44 ++++++++++++++++--- docs/scarpet/api/Auxiliary.md | 43 +++++++++++++++--- docs/scarpet/resources/editors/idea/2.txt | 4 +- .../scarpet/resources/editors/npp/scarpet.xml | 2 +- .../java/carpet/script/CarpetExpression.java | 44 ++++++++++++++++--- .../java/carpet/script/CarpetScriptHost.java | 18 ++++---- .../carpet/script/bundled/FileModule.java | 5 ++- .../java/carpet/script/bundled/Module.java | 41 ++++++++++------- 8 files changed, 150 insertions(+), 51 deletions(-) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index 3668b28f..5447429a 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -3007,23 +3007,52 @@ run('give @s stone 4') -> 1 // this operation was successful once Performs autosave, saves all chunks, player data, etc. Useful for programs where autosave is disabled due to performance reasons and saves the world only on demand. -### `load_app_data(), load_app_data(file)` +### `load_app_data(), load_app_data(file), load_app_data(file, shared?)` Loads the app data associated with the app from the world /scripts folder. Without argument returns the memory managed and buffered / throttled NBT tag. With a file name - reads explicitly a file with that name from the -scripts folder. +scripts folder that belongs exclusively to the app. if `shared` is true, the file location is not exclusive +to the app anymore, but located in a shared app space. + +File descriptor can contain letters, numbers and folder separator: `'/'`. Any other characters are stripped +from the name before saving/loading. Empty descriptors are invalid. + +Function returns nbt value with the file content, or `null` if the file is missing or there were problems +with retrieving the data. + +The default no-name app, via `/script run` command can only save/load file from the shared data location. + +If the app's name is `'foo'`, the script location would +be `world/scripts/foo.sc`, system-managed default app data storage is in `world/scripts/foo.data.nbt`, app +specific data directory is under `world/scripts/foo.data/bar/../baz.nbt`, and shared data space is under +`world/scripts/shared/bar/../baz.nbt`. You can use app data to save non-vanilla information separately from the world and other scripts. -### `store_app_data(tag), store_app_data(tag, file)` +### `store_app_data(tag), store_app_data(tag, file), store_app_data(tag, file, shared?)` -Stores the app data associated with the app from the world /scripts folder. With the `file` parameter saves -immediately and with every call, without `file` parameter, it may take up to 10 seconds for the output file +Stores the app data associated with the app from the world `/scripts` folder. With the `file` parameter saves +immediately and with every call to a specific file defined by the `file`, either in app space, or in the scripts +shared space if `shared` is true. Without `file` parameter, it may take up to 10 + seconds for the output file to sync preventing flickering in case this tag changes frequently. It will be synced when server closes. +Returns `true` if the file was saved successfully, `false` otherwise. + +Uses the same file structure for exclusive app data, and shared data folder as `load_app_data`. + ### `tick_time()` -Returns game tick counter. Can be used to run certain operations every n-th ticks, or to count in-game time +Returns server tick counter. Can be used to run certain operations every n-th ticks, or to count in-game time. + +### `world_time()` + +Returns dimension-specific tick counter. + +### `day_time(new_time?)` + +Returns current daytime clock value. If `new_time` is specified, sets a new clock +to that value. Daytime clocks are shared between all dimensions. ### `game_tick(mstime?)` @@ -3074,7 +3103,8 @@ For the options of `entry`, consult your statistics page, or give it a guess. The call will return `null` if the statistics options are incorrect, or player didn't get these in their history. If the player encountered the statistic, or game created for him empty one, it will return a number. Scarpet will not affect the entries of the statistics, even if it is just creating empty ones. With `null` response -it could either mean your input is wrong, or statistic has effectively a value of `0`.# `/script run` command +it could either mean your input is wrong, or statistic has effectively a value of `0`. +# `/script run` command Primary way to input commands. The command executes in the context, position, and dimension of the executing player, commandblock, etc... The command receives 4 variables, `x`, `y`, `z` and `p` indicating position and diff --git a/docs/scarpet/api/Auxiliary.md b/docs/scarpet/api/Auxiliary.md index 205656ae..52941068 100644 --- a/docs/scarpet/api/Auxiliary.md +++ b/docs/scarpet/api/Auxiliary.md @@ -79,23 +79,52 @@ run('give @s stone 4') -> 1 // this operation was successful once Performs autosave, saves all chunks, player data, etc. Useful for programs where autosave is disabled due to performance reasons and saves the world only on demand. -### `load_app_data(), load_app_data(file)` +### `load_app_data(), load_app_data(file), load_app_data(file, shared?)` Loads the app data associated with the app from the world /scripts folder. Without argument returns the memory managed and buffered / throttled NBT tag. With a file name - reads explicitly a file with that name from the -scripts folder. +scripts folder that belongs exclusively to the app. if `shared` is true, the file location is not exclusive +to the app anymore, but located in a shared app space. + +File descriptor can contain letters, numbers and folder separator: `'/'`. Any other characters are stripped +from the name before saving/loading. Empty descriptors are invalid. + +Function returns nbt value with the file content, or `null` if the file is missing or there were problems +with retrieving the data. + +The default no-name app, via `/script run` command can only save/load file from the shared data location. + +If the app's name is `'foo'`, the script location would +be `world/scripts/foo.sc`, system-managed default app data storage is in `world/scripts/foo.data.nbt`, app +specific data directory is under `world/scripts/foo.data/bar/../baz.nbt`, and shared data space is under +`world/scripts/shared/bar/../baz.nbt`. You can use app data to save non-vanilla information separately from the world and other scripts. -### `store_app_data(tag), store_app_data(tag, file)` +### `store_app_data(tag), store_app_data(tag, file), store_app_data(tag, file, shared?)` -Stores the app data associated with the app from the world /scripts folder. With the `file` parameter saves -immediately and with every call, without `file` parameter, it may take up to 10 seconds for the output file +Stores the app data associated with the app from the world `/scripts` folder. With the `file` parameter saves +immediately and with every call to a specific file defined by the `file`, either in app space, or in the scripts +shared space if `shared` is true. Without `file` parameter, it may take up to 10 + seconds for the output file to sync preventing flickering in case this tag changes frequently. It will be synced when server closes. +Returns `true` if the file was saved successfully, `false` otherwise. + +Uses the same file structure for exclusive app data, and shared data folder as `load_app_data`. + ### `tick_time()` -Returns game tick counter. Can be used to run certain operations every n-th ticks, or to count in-game time +Returns server tick counter. Can be used to run certain operations every n-th ticks, or to count in-game time. + +### `world_time()` + +Returns dimension-specific tick counter. + +### `day_time(new_time?)` + +Returns current daytime clock value. If `new_time` is specified, sets a new clock +to that value. Daytime clocks are shared between all dimensions. ### `game_tick(mstime?)` @@ -146,4 +175,4 @@ For the options of `entry`, consult your statistics page, or give it a guess. The call will return `null` if the statistics options are incorrect, or player didn't get these in their history. If the player encountered the statistic, or game created for him empty one, it will return a number. Scarpet will not affect the entries of the statistics, even if it is just creating empty ones. With `null` response -it could either mean your input is wrong, or statistic has effectively a value of `0`. \ No newline at end of file +it could either mean your input is wrong, or statistic has effectively a value of `0`. diff --git a/docs/scarpet/resources/editors/idea/2.txt b/docs/scarpet/resources/editors/idea/2.txt index c98522d1..31aa5e6f 100644 --- a/docs/scarpet/resources/editors/idea/2.txt +++ b/docs/scarpet/resources/editors/idea/2.txt @@ -13,6 +13,7 @@ brightness chunk_tickets create_marker current_dimension +day_time destroy diamond drop_item @@ -95,4 +96,5 @@ top transparent update volume -without_updates \ No newline at end of file +without_updates +world_time \ 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 8c06f293..6f5366e0 100644 --- a/docs/scarpet/resources/editors/npp/scarpet.xml +++ b/docs/scarpet/resources/editors/npp/scarpet.xml @@ -67,7 +67,7 @@ logger sound particle particle_line particle_rect - run save tick_time game_tick seed current_dimension in_dimension + run save tick_time world_time day_time game_tick seed current_dimension in_dimension plop harvest destroy schedule nbt create_marker remove_all_markers load_app_data store_app_data escape_nbt statistic diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index d78e178a..d11f126e 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -2669,6 +2669,24 @@ public class CarpetExpression return (cc, tt) -> time; }); + this.expr.addLazyFunction("world_time", 0, (c, t, lv) -> + { + Value time = new NumericValue(((CarpetContext) c).s.getWorld().getTime()); + return (cc, tt) -> time; + }); + + this.expr.addLazyFunction("day_time", -1, (c, t, lv) -> + { + Value time = new NumericValue(((CarpetContext) c).s.getWorld().getTimeOfDay()); + if (lv.size() > 0) + { + long newTime = NumericValue.asNumber(lv.get(0).evalValue(c)).getLong(); + if (newTime < 0) newTime = 0; + ((CarpetContext) c).s.getWorld().setTimeOfDay(newTime); + } + return (cc, tt) -> time; + }); + this.expr.addLazyFunction("game_tick", -1, (c, t, lv) -> { ServerCommandSource s = ((CarpetContext)c).s; if (!s.getMinecraftServer().isOnThread()) throw new InternalExpressionException("Unable to run ticks from threads"); @@ -2805,16 +2823,22 @@ public class CarpetExpression this.expr.addLazyFunction("load_app_data", -1, (c, t, lv) -> { String file = null; + boolean shared = false; if (lv.size()>0) { String origfile = lv.get(0).evalValue(c).getString(); - file = origfile.toLowerCase(Locale.ROOT).replaceAll("[^A-Za-z0-9]", ""); + file = origfile.toLowerCase(Locale.ROOT).replaceAll("[^A-Za-z0-9/]", ""); + file = Arrays.stream(file.split("/+")).filter(s -> !s.isEmpty()).collect(Collectors.joining("/")); if (file.isEmpty()) { - throw new InternalExpressionException("Cannot use "+file+" as resource name - must have some letters and numbers"); + throw new InternalExpressionException("Cannot use "+origfile+" as resource name - must have at least some letters and numbers"); + } + if (lv.size() > 1) + { + shared = lv.get(1).evalValue(c).getBoolean(); } } - Tag state = ((CarpetScriptHost)((CarpetContext)c).host).getGlobalState(file); + Tag state = ((CarpetScriptHost)((CarpetContext)c).host).getGlobalState(file, shared); if (state == null) return (cc, tt) -> Value.NULL; Value retVal = new NBTSerializableValue(state); @@ -2827,21 +2851,27 @@ public class CarpetExpression throw new InternalExpressionException("'store_app_data' needs NBT tag and an optional file"); Value val = lv.get(0).evalValue(c); String file = null; + boolean shared = false; if (lv.size()>1) { String origfile = lv.get(1).evalValue(c).getString(); - file = origfile.toLowerCase(Locale.ROOT).replaceAll("[^A-Za-z0-9]", ""); + file = origfile.toLowerCase(Locale.ROOT).replaceAll("[^A-Za-z0-9/]", ""); + file = Arrays.stream(file.split("/+")).filter(s -> !s.isEmpty()).collect(Collectors.joining("/")); if (file.isEmpty()) { - throw new InternalExpressionException("Cannot use "+file+" as resource name - must have some letters and numbers"); + throw new InternalExpressionException("Cannot use "+origfile+" as resource name - must have some letters and numbers"); + } + if (lv.size() > 2) + { + shared = lv.get(2).evalValue(c).getBoolean(); } } NBTSerializableValue tagValue = (val instanceof NBTSerializableValue) ? (NBTSerializableValue) val : new NBTSerializableValue(val.getString()); Tag tag = tagValue.getTag(); - ((CarpetScriptHost)((CarpetContext)c).host).setGlobalState(tag, file); - return (cc, tt) -> Value.NULL; + boolean success = ((CarpetScriptHost)((CarpetContext)c).host).setGlobalState(tag, file, shared); + return success?LazyValue.TRUE:LazyValue.FALSE; }); this.expr.addLazyFunction("statistic", 3, (c, t, lv) -> diff --git a/src/main/java/carpet/script/CarpetScriptHost.java b/src/main/java/carpet/script/CarpetScriptHost.java index 0b1a5eb7..c6a8afa8 100644 --- a/src/main/java/carpet/script/CarpetScriptHost.java +++ b/src/main/java/carpet/script/CarpetScriptHost.java @@ -361,32 +361,31 @@ public class CarpetScriptHost extends ScriptHost private void dumpState() { - main.saveData(null, globalState); + Module.saveData(main, null, globalState, false); } private Tag loadState() { - return main.getData(null); + return Module.getData(main, null, false); } - public Tag getGlobalState(String file) + public Tag getGlobalState(String file, boolean isShared) { - if (getName() == null ) return null; + if (getName() == null && !isShared) return null; if (file != null) - return main.getData(file); + return Module.getData(main, file, isShared); if (parent == null) return globalState; return ((CarpetScriptHost)parent).globalState; } - public void setGlobalState(Tag tag, String file) + public boolean setGlobalState(Tag tag, String file, boolean isShared) { - if (getName() == null ) return; + if (getName() == null && !isShared) return false; // if belongs to an app, cannot be default host. if (file!= null) { - main.saveData(file, tag); - return; + return Module.saveData(main, file, tag, isShared); } CarpetScriptHost responsibleHost = (parent != null)?(CarpetScriptHost) parent:this; @@ -396,6 +395,7 @@ public class CarpetScriptHost extends ScriptHost responsibleHost.dumpState(); responsibleHost.saveTimeout = 200; } + return true; } public void tick() diff --git a/src/main/java/carpet/script/bundled/FileModule.java b/src/main/java/carpet/script/bundled/FileModule.java index c9ff21e1..ef44a292 100644 --- a/src/main/java/carpet/script/bundled/FileModule.java +++ b/src/main/java/carpet/script/bundled/FileModule.java @@ -74,7 +74,7 @@ public class FileModule extends Module } //copied private method from net.minecraft.nbt.NbtIo.write() and client method safe_write - public static void write(Tag tag_1, File file) + public static boolean write(Tag tag_1, File file) { File file_2 = new File(file.getAbsolutePath() + "_tmp"); if (file_2.exists()) file_2.delete(); @@ -90,9 +90,10 @@ public class FileModule extends Module } catch (IOException e) { - return; + return false; } if (file.exists()) file.delete(); if (!file.exists()) file_2.renameTo(file); + return true; } } diff --git a/src/main/java/carpet/script/bundled/Module.java b/src/main/java/carpet/script/bundled/Module.java index 1cc804f1..c15cebd4 100644 --- a/src/main/java/carpet/script/bundled/Module.java +++ b/src/main/java/carpet/script/bundled/Module.java @@ -4,7 +4,6 @@ import carpet.CarpetServer; import net.minecraft.nbt.Tag; import java.io.File; -import java.io.IOException; import java.nio.file.Files; import static carpet.script.bundled.FileModule.read; @@ -16,30 +15,38 @@ public abstract class Module public abstract String getCode(); public abstract boolean isLibrary(); - public Tag getData(String file) + private static String getDescriptor(Module module, String file, boolean isShared) { + if (isShared) + { + return "shared/"+file; + } + else if (module != null && module.getName() != null) // appdata + { + return module.getName()+".data"+(file==null?"":"/"+file); + } + else + { + throw new RuntimeException("Invalid file descriptor: "+file); + } + } + + public static Tag getData(Module module, String file, boolean isShared) + { + if (!isShared && (module == null || module.getName() == null)) return null; File dataFile = CarpetServer.minecraft_server.getLevelStorage().resolveFile( - CarpetServer.minecraft_server.getLevelName(), "scripts/"+getName()+".data"+(file==null?"":"."+file)+".nbt"); + CarpetServer.minecraft_server.getLevelName(), "scripts/"+getDescriptor(module, file, isShared)+".nbt"); if (!Files.exists(dataFile.toPath()) || !(dataFile.isFile())) return null; return read(dataFile); } - public void saveData(String file, Tag globalState) + public static boolean saveData(Module module, String file, Tag globalState, boolean isShared) { + if (!isShared && (module == null || module.getName() == null)) return false; File dataFile =CarpetServer.minecraft_server.getLevelStorage().resolveFile( - CarpetServer.minecraft_server.getLevelName(), "scripts/"+getName()+".data"+(file==null?"":"."+file)+".nbt"); - if (!Files.exists(dataFile.toPath().getParent())) - { - try - { - Files.createDirectory(dataFile.toPath().getParent()); - } - catch (IOException ignored) - { - } - } - write(globalState, dataFile); - + CarpetServer.minecraft_server.getLevelName(), "scripts/"+getDescriptor(module, file, isShared)+".nbt"); + if (!Files.exists(dataFile.toPath().getParent()) && !dataFile.getParentFile().mkdirs()) return false; + return write(globalState, dataFile); } @Override From 6932e5b6820bd9c4ca17b64a65aa41469b743be4 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 15 Apr 2020 11:01:26 -0300 Subject: [PATCH 014/198] added 'last_tick_times' --- docs/scarpet/api/Auxiliary.md | 9 +++++++++ docs/scarpet/resources/editors/idea/2.txt | 1 + docs/scarpet/resources/editors/npp/scarpet.xml | 2 +- .../java/carpet/script/CarpetExpression.java | 16 ++++++++++++++++ 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/docs/scarpet/api/Auxiliary.md b/docs/scarpet/api/Auxiliary.md index 52941068..db5cba2e 100644 --- a/docs/scarpet/api/Auxiliary.md +++ b/docs/scarpet/api/Auxiliary.md @@ -126,6 +126,15 @@ Returns dimension-specific tick counter. Returns current daytime clock value. If `new_time` is specified, sets a new clock to that value. Daytime clocks are shared between all dimensions. +### `last_tick_times()` + +Returns a 100-long array of recent tick times, in milliseconds. First item on the list is the most recent tick +If called outside of the main tick (either throgh scheduled tasks, or async execution), then the first item on the +list may refer to the previous tick performance. In this case the last entry (tick 100) would refer to the most current +tick. For all intent and purpose, `last_tick_times():0` should be used as last tick execution time, but +individual tick times may vary greatly, and these need to be taken with the little grain of +averaging. + ### `game_tick(mstime?)` Causes game to run for one tick. By default runs it and returns control to the program, but can optionally diff --git a/docs/scarpet/resources/editors/idea/2.txt b/docs/scarpet/resources/editors/idea/2.txt index 31aa5e6f..edcf56fb 100644 --- a/docs/scarpet/resources/editors/idea/2.txt +++ b/docs/scarpet/resources/editors/idea/2.txt @@ -38,6 +38,7 @@ inventory_remove inventory_set inventory_size item_category +last_tick_times light liquid load_app_data diff --git a/docs/scarpet/resources/editors/npp/scarpet.xml b/docs/scarpet/resources/editors/npp/scarpet.xml index 6f5366e0..8ad6f2ea 100644 --- a/docs/scarpet/resources/editors/npp/scarpet.xml +++ b/docs/scarpet/resources/editors/npp/scarpet.xml @@ -67,7 +67,7 @@ logger sound particle particle_line particle_rect - run save tick_time world_time day_time game_tick seed current_dimension in_dimension + run save tick_time world_time day_time last_tick_times game_tick seed current_dimension in_dimension plop harvest destroy schedule nbt create_marker remove_all_markers load_app_data store_app_data escape_nbt statistic diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index d11f126e..3bb7ffd5 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -2687,6 +2687,22 @@ public class CarpetExpression return (cc, tt) -> time; }); + this.expr.addLazyFunction("last_tick_times", -1, (c, t, lv) -> + { + //assuming we are in the tick world section + // might be off one tick when run in the off tasks or asynchronously. + int currentReportedTick = ((CarpetContext) c).s.getMinecraftServer().getTicks()-1; + List ticks = new ArrayList<>(100); + final long[] tickArray = ((CarpetContext) c).s.getMinecraftServer().lastTickLengths; + for (int i=currentReportedTick+100; i > currentReportedTick; i--) + { + ticks.add(new NumericValue(((double)tickArray[i % 100])/1000000.0)); + } + Value ret = ListValue.wrap(ticks); + return (cc, tt) -> ret; + }); + + this.expr.addLazyFunction("game_tick", -1, (c, t, lv) -> { ServerCommandSource s = ((CarpetContext)c).s; if (!s.getMinecraftServer().isOnThread()) throw new InternalExpressionException("Unable to run ticks from threads"); From 3fe2d5174bbb3f1b86c88360cf811a221fdcfa1b Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 15 Apr 2020 11:02:46 -0300 Subject: [PATCH 015/198] added 'last_tick_times' --- docs/scarpet/Full.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index 5447429a..b212f553 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -3054,6 +3054,15 @@ Returns dimension-specific tick counter. Returns current daytime clock value. If `new_time` is specified, sets a new clock to that value. Daytime clocks are shared between all dimensions. +### `last_tick_times()` + +Returns a 100-long array of recent tick times, in milliseconds. First item on the list is the most recent tick +If called outside of the main tick (either throgh scheduled tasks, or async execution), then the first item on the +list may refer to the previous tick performance. In this case the last entry (tick 100) would refer to the most current +tick. For all intent and purpose, `last_tick_times():0` should be used as last tick execution time, but +individual tick times may vary greatly, and these need to be taken with the little grain of +averaging. + ### `game_tick(mstime?)` Causes game to run for one tick. By default runs it and returns control to the program, but can optionally From 7ddf8658c8f0f20d4cc3c73c645625d92b064c12 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 15 Apr 2020 11:51:46 -0300 Subject: [PATCH 016/198] refine tnt messaging --- src/main/java/carpet/logging/logHelpers/TNTLogHelper.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/carpet/logging/logHelpers/TNTLogHelper.java b/src/main/java/carpet/logging/logHelpers/TNTLogHelper.java index b968d0b4..6b7b35fa 100644 --- a/src/main/java/carpet/logging/logHelpers/TNTLogHelper.java +++ b/src/main/java/carpet/logging/logHelpers/TNTLogHelper.java @@ -43,10 +43,9 @@ public class TNTLogHelper "r E ",Messenger.dblt("r",x, y, z))}; case "full": return new BaseText[]{Messenger.c( - "g #" + String.valueOf(tntCount), - "m @" + String.valueOf(gametime), - "g : ", - "g #" + String.valueOf(tntCount) + ": ", + "r #" + String.valueOf(tntCount), + "m @" + String.valueOf(gametime), + "g : ", "l P ",Messenger.dblf("l",primedX,primedY,primedZ), "w ",Messenger.dblf("l", primedAngle.x, primedAngle.y, primedAngle.z), "r E ",Messenger.dblf("r",x, y, z))}; From 4bb283a851258f0c2c0cb4c2165039ecd1ff262b Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 15 Apr 2020 12:39:36 -0300 Subject: [PATCH 017/198] 1.3.19 --- gradle.properties | 2 +- src/main/java/carpet/CarpetSettings.java | 2 +- src/main/resources/fabric.mod.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 5dc95d10..4a2d7082 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ org.gradle.jvmargs=-Xmx1G loader_version=0.7.8+build.188 # Mod Properties - mod_version = 1.3.18+v200408 + mod_version = 1.3.19+v200415 maven_group = carpet archives_base_name = fabric-carpet diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index cb9a3598..963b2eb3 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -33,7 +33,7 @@ import static carpet.settings.RuleCategory.CLIENT; @SuppressWarnings("CanBeFinal") public class CarpetSettings { - public static final String carpetVersion = "1.3.18+v200408"; + public static final String carpetVersion = "1.3.19+v200415"; public static final Logger LOG = LogManager.getLogger(); public static boolean skipGenerationChecks = false; public static boolean impendingFillSkipUpdates = false; diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index fe4203f1..758e0adf 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,7 +1,7 @@ { "schemaVersion": 1, "id": "carpet", - "version": "1.3.18", + "version": "1.3.19", "name": "Carpet Mod in Fabric", "description": "Carpet made out of fabric", From a229c2084c850c041f7a8bea772da8d9f961dfc4 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 15 Apr 2020 22:46:58 -0300 Subject: [PATCH 018/198] added new structure info --- docs/scarpet/Full.md | 15 +++++++++++++++ docs/scarpet/api/BlocksAndWorldAccess.md | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index b212f553..56398e7d 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -2127,6 +2127,13 @@ Structure list: * `village_savanna`: Savanna, acacia village. * `village_taiga`: Taiga, spruce village. * `village_snowy`: Resolute, Canada. +* `nether_fossil`: Pile of bones (1.16) +* `ruined_portal`: Ruined portal, random variant. +* `bastion_remnant`: Piglin bastion, random variant for the chunk (1.16) +* `bastion_remnant_housing`: Housing units version of a piglin bastion (1.16) +* `bastion_remnant_stable`: Hoglin stables version of q piglin bastion (1.16) +* `bastion_remnant_treasure`: Treasure room version of a piglin bastion (1.16) +* `bastion_remnant_bridge` : Bridge version of a piglin bastion (1.16) Feature list: @@ -2183,6 +2190,14 @@ Feature list: * `coral`: random coral structure. Require water to spawn. * `sea_pickle` * `boulder`: A rocky, mossy formation from a giant taiga biome. Doesn't update client properly, needs relogging. +* `crimson_fungus` (1.16) +* `warped_fungus` (1.16) +* `nether_sprouts` (1.16) +* `crimson_roots` (1.16) +* `warped_roots` (1.16) +* `weeping_vines` (1.16) +* `twisting_vines` (1.16) +* `basalt_pillar` (1.16) ### `reset_chunk(pos)`, `reset_chunk(from_pos, to_pos)`, `reset_chunk(l(pos, ...))` Removes and resets the chunk, all chunks in the specified area or all chunks in a list at once, removing all previous diff --git a/docs/scarpet/api/BlocksAndWorldAccess.md b/docs/scarpet/api/BlocksAndWorldAccess.md index 1ec333d7..0847bbbf 100644 --- a/docs/scarpet/api/BlocksAndWorldAccess.md +++ b/docs/scarpet/api/BlocksAndWorldAccess.md @@ -590,6 +590,13 @@ Structure list: * `village_savanna`: Savanna, acacia village. * `village_taiga`: Taiga, spruce village. * `village_snowy`: Resolute, Canada. +* `nether_fossil`: Pile of bones (1.16) +* `ruined_portal`: Ruined portal, random variant. +* `bastion_remnant`: Piglin bastion, random variant for the chunk (1.16) +* `bastion_remnant_housing`: Housing units version of a piglin bastion (1.16) +* `bastion_remnant_stable`: Hoglin stables version of q piglin bastion (1.16) +* `bastion_remnant_treasure`: Treasure room version of a piglin bastion (1.16) +* `bastion_remnant_bridge` : Bridge version of a piglin bastion (1.16) Feature list: @@ -646,6 +653,14 @@ Feature list: * `coral`: random coral structure. Require water to spawn. * `sea_pickle` * `boulder`: A rocky, mossy formation from a giant taiga biome. Doesn't update client properly, needs relogging. +* `crimson_fungus` (1.16) +* `warped_fungus` (1.16) +* `nether_sprouts` (1.16) +* `crimson_roots` (1.16) +* `warped_roots` (1.16) +* `weeping_vines` (1.16) +* `twisting_vines` (1.16) +* `basalt_pillar` (1.16) ### `reset_chunk(pos)`, `reset_chunk(from_pos, to_pos)`, `reset_chunk(l(pos, ...))` Removes and resets the chunk, all chunks in the specified area or all chunks in a list at once, removing all previous From 9a588cf19a565f8da33b838b2b62fd98640a12f3 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 15 Apr 2020 23:58:59 -0300 Subject: [PATCH 019/198] fixes #225 --- src/main/java/carpet/script/value/EntityValue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index 3cd5726e..ce033fa1 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -118,7 +118,7 @@ public class EntityValue extends Value @Override public String getString() { - return entity.getDisplayName().getString(); + return entity.getName().getString(); } @Override From 022addf4e171a537ed1ea5566761599acf9d499a Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 16 Apr 2020 00:24:02 -0300 Subject: [PATCH 020/198] fixed #225 yet again, added display_name, command_name and team option for entities. --- docs/scarpet/Full.md | 18 ++++++++++++++++-- docs/scarpet/api/Entities.md | 18 ++++++++++++++++-- .../java/carpet/script/value/EntityValue.java | 6 +++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index 56398e7d..45d8eb9e 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -2370,15 +2370,25 @@ Triple of entity motion vector, `l(motion_x, motion_y, motion_z)` Respective component of the motion vector -### `query(e,'name'), query(e,'custom_name'), query(e,'type')` +### `query(e,'name'), query(e,'display_name'), query(e,'custom_name'), query(e,'type')` String of entity name -
query(e,'name')  => Leatherworker
+
+query(e,'name')  => Leatherworker
 query(e,'custom_name')  => null
 query(e,'type')  => villager
 
+## `query(e, 'command_name')` + +Returns a valid string to be used in commands to address an entity. Its UUID for all entities except +player, where its their name. + +
+run('/kill ' + e~'command_name');
+
+ ### `query(e,'is_riding')` Boolean. True if riding another entity. @@ -2522,6 +2532,10 @@ Returns `null` if the argument is not a player, otherwise: * `shadow`: any carpet-shadowed real player * `realms`: ? +### `query(e, 'team')` + +Team name for entity, or `null` if no team is assigned. + ### `query(e,'ping')` Player's ping in milliseconds, or `null` if its not a player. diff --git a/docs/scarpet/api/Entities.md b/docs/scarpet/api/Entities.md index 5fec0d0b..3bd7634f 100644 --- a/docs/scarpet/api/Entities.md +++ b/docs/scarpet/api/Entities.md @@ -113,15 +113,25 @@ Triple of entity motion vector, `l(motion_x, motion_y, motion_z)` Respective component of the motion vector -### `query(e,'name'), query(e,'custom_name'), query(e,'type')` +### `query(e,'name'), query(e,'display_name'), query(e,'custom_name'), query(e,'type')` String of entity name -
query(e,'name')  => Leatherworker
+
+query(e,'name')  => Leatherworker
 query(e,'custom_name')  => null
 query(e,'type')  => villager
 
+## `query(e, 'command_name')` + +Returns a valid string to be used in commands to address an entity. Its UUID for all entities except +player, where its their name. + +
+run('/kill ' + e~'command_name');
+
+ ### `query(e,'is_riding')` Boolean. True if riding another entity. @@ -265,6 +275,10 @@ Returns `null` if the argument is not a player, otherwise: * `shadow`: any carpet-shadowed real player * `realms`: ? +### `query(e, 'team')` + +Team name for entity, or `null` if no team is assigned. + ### `query(e,'ping')` Player's ping in milliseconds, or `null` if its not a player. diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index ce033fa1..88c9f14a 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -220,7 +220,9 @@ public class EntityValue extends Value put("motion_x", (e, a) -> new NumericValue(e.getVelocity().x)); put("motion_y", (e, a) -> new NumericValue(e.getVelocity().y)); put("motion_z", (e, a) -> new NumericValue(e.getVelocity().z)); - put("name", (e, a) -> new StringValue(e.getDisplayName().getString())); + put("name", (e, a) -> new StringValue(e.getName().getString())); + put("display_name", (e, a) -> new StringValue(e.getDisplayName().getString())); + put("command_name", (e, a) -> new StringValue(e.getEntityName())); put("custom_name", (e, a) -> e.hasCustomName()?new StringValue(e.getCustomName().getString()):Value.NULL); put("type", (e, a) -> new StringValue(nameFromRegistryId(Registry.ENTITY_TYPE.getId(e.getType())))); put("is_riding", (e, a) -> new NumericValue(e.hasVehicle())); @@ -331,6 +333,8 @@ public class EntityValue extends Value return Value.NULL; }); + put("team", (e, a) -> e.getScoreboardTeam()==null?Value.NULL:new StringValue(e.getScoreboardTeam().getName())); + put("ping", (e, a) -> { if (e instanceof ServerPlayerEntity) { From fb1a03b3f7b596ca0d0e6a5c949e678f75a4dfa0 Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 16 Apr 2020 17:47:06 -0300 Subject: [PATCH 021/198] refactor argument parsers --- .../java/carpet/script/CarpetExpression.java | 121 +++++----- .../java/carpet/script/CarpetScriptHost.java | 5 + .../java/carpet/script/utils/ArgParser.java | 17 ++ .../carpet/script/utils/CarpetArgParser.java | 215 ++++++++++++++++++ .../java/carpet/script/value/BlockValue.java | 201 ---------------- .../java/carpet/script/value/MapValue.java | 10 + 6 files changed, 317 insertions(+), 252 deletions(-) create mode 100644 src/main/java/carpet/script/utils/ArgParser.java create mode 100644 src/main/java/carpet/script/utils/CarpetArgParser.java diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 3bb7ffd5..ed9419fd 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -18,6 +18,7 @@ import carpet.script.exception.ContinueStatement; import carpet.script.exception.ExitStatement; import carpet.script.exception.ExpressionException; import carpet.script.exception.InternalExpressionException; +import carpet.script.utils.CarpetArgParser; import carpet.script.value.BlockValue; import carpet.script.value.EntityValue; import carpet.script.value.FunctionValue; @@ -132,7 +133,6 @@ import java.util.Optional; import java.util.UUID; import java.util.function.BiFunction; import java.util.function.Predicate; -import java.util.stream.Collector; import java.util.stream.Collectors; import static carpet.script.utils.WorldTools.canHasChunk; @@ -175,7 +175,7 @@ public class CarpetExpression Value retval = test.apply(((BlockValue) v0).getBlockState(), ((BlockValue) v0).getPos()) ? Value.TRUE : Value.FALSE; return (c_, t_) -> retval; } - BlockValue block = BlockValue.fromParams(cc, params, 0).block; + BlockValue block = CarpetArgParser.locateBlock(cc, params, 0).block; Value retval = test.apply(block.getBlockState(), block.getPos()) ? Value.TRUE : Value.FALSE; return (c_, t_) -> retval; } @@ -200,7 +200,7 @@ public class CarpetExpression Value retval = strVal != null ? new StringValue(strVal) : Value.NULL; return (c_, t_) -> retval; } - BlockValue block = BlockValue.fromParams(cc, params, 0).block; + BlockValue block = CarpetArgParser.locateBlock(cc, params, 0).block; String strVal = test.apply(block.getBlockState(), block.getPos()); Value retval = strVal != null ? new StringValue(strVal) : Value.NULL; return (c_, t_) -> retval; @@ -231,7 +231,7 @@ public class CarpetExpression throw new InternalExpressionException("'" + name + "' function requires a block that is positioned in the world"); } } - BlockValue block = BlockValue.fromParams(cc, params, 0).block; + BlockValue block = CarpetArgParser.locateBlock(cc, params, 0).block; Value retval = test.apply(block.getBlockState(), block.getPos(), cc.s.getWorld()); return (c_, t_) -> retval; } @@ -400,7 +400,7 @@ public class CarpetExpression { throw new InternalExpressionException("Block requires at least one parameter"); } - BlockValue retval = BlockValue.fromParams(cc, lv, 0, true).block; + BlockValue retval = CarpetArgParser.locateBlock(cc, lv, 0, true).block; // fixing block state and data retval.getBlockState(); retval.getData(); @@ -414,7 +414,7 @@ public class CarpetExpression { throw new InternalExpressionException("Block requires at least one parameter"); } - CompoundTag tag = BlockValue.fromParams(cc, lv, 0, true).block.getData(); + CompoundTag tag = CarpetArgParser.locateBlock(cc, lv, 0, true).block.getData(); if (tag == null) return (c_, t_) -> Value.NULL; Value retval = new NBTSerializableValue(tag); @@ -426,7 +426,7 @@ public class CarpetExpression { CarpetContext cc = (CarpetContext) c; if (lv.size() == 0) throw new InternalExpressionException("'poi' requires at least one parameter"); - BlockValue.LocatorResult locator = BlockValue.fromParams(cc, lv, 0, false); + CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock(cc, lv, 0, false); BlockPos pos = locator.block.getPos(); PointOfInterestStorage store = cc.s.getWorld().getPointOfInterestStorage(); if (lv.size() == locator.offset) @@ -492,7 +492,7 @@ public class CarpetExpression { CarpetContext cc = (CarpetContext) c; if (lv.size() == 0) throw new InternalExpressionException("'set_poi' requires at least one parameter"); - BlockValue.LocatorResult locator = BlockValue.fromParams(cc, lv, 0, false); + CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock(cc, lv, 0, false); BlockPos pos = locator.block.getPos(); if (lv.size() < locator.offset) throw new InternalExpressionException("'set_poi' requires the new poi type or null, after position argument"); Value poi = lv.get(locator.offset+0).evalValue(c); @@ -559,7 +559,7 @@ public class CarpetExpression this.expr.addLazyFunction("pos_offset", -1, (c, t, lv) -> { - BlockValue.LocatorResult locator = BlockValue.fromParams((CarpetContext)c, lv, 0); + CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock((CarpetContext)c, lv, 0); BlockPos pos = locator.block.getPos(); if (lv.size() <= locator.offset) throw new InternalExpressionException("'pos_offset' needs at least position, and direction"); @@ -622,7 +622,7 @@ public class CarpetExpression this.expr.addLazyFunction("in_slime_chunk", -1, (c, t, lv) -> { - BlockPos pos = BlockValue.fromParams((CarpetContext)c, lv, 0).block.getPos(); + BlockPos pos = CarpetArgParser.locateBlock((CarpetContext)c, lv, 0).block.getPos(); ChunkPos chunkPos = new ChunkPos(pos); Value ret = new NumericValue(ChunkRandom.create( chunkPos.x, chunkPos.z, @@ -646,7 +646,7 @@ public class CarpetExpression case "surface": htype = Heightmap.Type.WORLD_SURFACE; break; default: throw new InternalExpressionException("Unknown heightmap type: "+type); } - BlockValue.LocatorResult locator = BlockValue.fromParams((CarpetContext)c, lv, 1); + CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock((CarpetContext)c, lv, 1); BlockPos pos = locator.block.getPos(); int x = pos.getX(); int z = pos.getZ(); @@ -658,21 +658,21 @@ public class CarpetExpression this.expr.addLazyFunction("loaded", -1, (c, t, lv) -> { - Value retval = ((CarpetContext) c).s.getWorld().isChunkLoaded(BlockValue.fromParams((CarpetContext) c, lv, 0).block.getPos()) ? Value.TRUE : Value.FALSE; + Value retval = ((CarpetContext) c).s.getWorld().isChunkLoaded(CarpetArgParser.locateBlock((CarpetContext) c, lv, 0).block.getPos()) ? Value.TRUE : Value.FALSE; return (c_, t_) -> retval; }); // Deprecated, use loaded_status as more indicative this.expr.addLazyFunction("loaded_ep", -1, (c, t, lv) -> { - BlockPos pos = BlockValue.fromParams((CarpetContext)c, lv, 0).block.getPos(); + BlockPos pos = CarpetArgParser.locateBlock((CarpetContext)c, lv, 0).block.getPos(); Value retval = ((CarpetContext)c).s.getWorld().getChunkManager().shouldTickChunk(new ChunkPos(pos))?Value.TRUE : Value.FALSE; return (c_, t_) -> retval; }); this.expr.addLazyFunction("loaded_status", -1, (c, t, lv) -> { - BlockPos pos = BlockValue.fromParams((CarpetContext)c, lv, 0).block.getPos(); + BlockPos pos = CarpetArgParser.locateBlock((CarpetContext)c, lv, 0).block.getPos(); WorldChunk chunk = ((CarpetContext)c).s.getWorld().getChunkManager().getWorldChunk(pos.getX()>>4, pos.getZ()>>4, false); if (chunk == null) return LazyValue.ZERO; @@ -682,7 +682,7 @@ public class CarpetExpression this.expr.addLazyFunction("is_chunk_generated", -1, (c, t, lv) -> { - BlockValue.LocatorResult locator = BlockValue.fromParams((CarpetContext)c, lv, 0); + CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock((CarpetContext)c, lv, 0); BlockPos pos = locator.block.getPos(); boolean force = false; if (lv.size() > locator.offset) @@ -693,11 +693,11 @@ public class CarpetExpression this.expr.addLazyFunction("generation_status", -1, (c, t, lv) -> { - BlockValue.LocatorResult locatorResult = BlockValue.fromParams((CarpetContext)c, lv, 0); - BlockPos pos = locatorResult.block.getPos(); + CarpetArgParser.BlockArgument blockArgument = CarpetArgParser.locateBlock((CarpetContext)c, lv, 0); + BlockPos pos = blockArgument.block.getPos(); boolean forceLoad = false; - if (lv.size() > locatorResult.offset) - forceLoad = lv.get(locatorResult.offset).evalValue(c, Context.BOOLEAN).getBoolean(); + if (lv.size() > blockArgument.offset) + forceLoad = lv.get(blockArgument.offset).evalValue(c, Context.BOOLEAN).getBoolean(); Chunk chunk = ((CarpetContext)c).s.getWorld().getChunk(pos.getX()>>4, pos.getZ()>>4, ChunkStatus.EMPTY, forceLoad); if (chunk == null) return LazyValue.NULL; @@ -731,8 +731,8 @@ public class CarpetExpression } else { - BlockValue.LocatorResult locatorResult = BlockValue.fromParams((CarpetContext) c, lv, 0); - BlockPos pos = locatorResult.block.getPos(); + CarpetArgParser.BlockArgument blockArgument = CarpetArgParser.locateBlock((CarpetContext) c, lv, 0); + BlockPos pos = blockArgument.block.getPos(); SortedArraySet> tickets = levelTickets.get(new ChunkPos(pos).toLong()); if (tickets != null) { @@ -804,8 +804,8 @@ public class CarpetExpression ServerWorld world = cc.s.getWorld(); if (lv.size() < 2 || lv.size() % 2 == 1) throw new InternalExpressionException("'set' should have at least 2 params and odd attributes"); - BlockValue.LocatorResult targetLocator = BlockValue.fromParams(cc, lv, 0); - BlockValue.LocatorResult sourceLocator = BlockValue.fromParams(cc, lv, targetLocator.offset, true); + CarpetArgParser.BlockArgument targetLocator = CarpetArgParser.locateBlock(cc, lv, 0); + CarpetArgParser.BlockArgument sourceLocator = CarpetArgParser.locateBlock(cc, lv, targetLocator.offset, true); BlockState sourceBlockState = sourceLocator.block.getBlockState(); BlockState targetBlockState = world.getBlockState(targetLocator.block.getPos()); if (sourceLocator.offset < lv.size()) @@ -854,7 +854,7 @@ public class CarpetExpression { CarpetContext cc = (CarpetContext)c; ServerWorld world = cc.s.getWorld(); - BlockValue.LocatorResult locator = BlockValue.fromParams(cc, lv, 0); + CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock(cc, lv, 0); BlockState state = locator.block.getBlockState(); if (state.isAir()) return (c_, t_) -> Value.FALSE; @@ -964,7 +964,7 @@ public class CarpetExpression if (!(e instanceof ServerPlayerEntity)) return (c_, t_) -> Value.FALSE; ServerPlayerEntity player = (ServerPlayerEntity)e; - BlockValue.LocatorResult locator = BlockValue.fromParams(cc, lv, 1); + CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock(cc, lv, 1); BlockPos where = locator.block.getPos(); BlockState state = locator.block.getBlockState(); Block block = state.getBlock(); @@ -982,7 +982,7 @@ public class CarpetExpression throw new InternalExpressionException("'place_item' takes at least 2 parameters: item and block, or position, to place onto"); CarpetContext cc = (CarpetContext) c; String itemString = lv.get(0).evalValue(c).getString(); - BlockValue.VectorLocator locator = BlockValue.locateVec(cc, lv, 1); + CarpetArgParser.Vector3Argument locator = CarpetArgParser.locateVector(cc, lv, 1); ItemStackArgument stackArg = NBTSerializableValue.parseItem(itemString); BlockPos where = new BlockPos(locator.vec); String facing = "up"; @@ -1038,7 +1038,7 @@ public class CarpetExpression this.expr.addLazyFunction("property", -1, (c, t, lv) -> { - BlockValue.LocatorResult locator = BlockValue.fromParams((CarpetContext) c, lv, 0); + CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock((CarpetContext) c, lv, 0); BlockState state = locator.block.getBlockState(); if (lv.size() <= locator.offset) throw new InternalExpressionException("'property' requires to specify a property to query"); @@ -1053,7 +1053,7 @@ public class CarpetExpression this.expr.addLazyFunction("block_properties", -1, (c, t, lv) -> { - BlockValue.LocatorResult locator = BlockValue.fromParams((CarpetContext) c, lv, 0); + CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock((CarpetContext) c, lv, 0); BlockState state = locator.block.getBlockState(); StateManager states = state.getBlock().getStateManager(); Value res = ListValue.wrap(states.getProperties().stream().map( @@ -1064,7 +1064,7 @@ public class CarpetExpression this.expr.addLazyFunction("biome", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; - BlockValue.LocatorResult locator = BlockValue.fromParams(cc, lv, 0); + CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock(cc, lv, 0); ServerWorld world = cc.s.getWorld(); BlockPos pos = locator.block.getPos(); Biome biome = world.getBiome(pos); @@ -1075,7 +1075,7 @@ public class CarpetExpression this.expr.addLazyFunction("set_biome", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; - BlockValue.LocatorResult locator = BlockValue.fromParams(cc, lv, 0); + CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock(cc, lv, 0); if (lv.size() == locator.offset) throw new InternalExpressionException("'set_biome' needs a biome name as an argument"); String biomeName = lv.get(locator.offset+0).evalValue(c).getString(); @@ -1092,7 +1092,7 @@ public class CarpetExpression this.expr.addLazyFunction("structure_references", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; - BlockValue.LocatorResult locator = BlockValue.fromParams(cc, lv, 0); + CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock(cc, lv, 0); ServerWorld world = cc.s.getWorld(); BlockPos pos = locator.block.getPos(); Map references = world.getChunk(pos).getStructureReferences(); @@ -1117,7 +1117,7 @@ public class CarpetExpression this.expr.addLazyFunction("structures", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; - BlockValue.LocatorResult locator = BlockValue.fromParams(cc, lv, 0); + CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock(cc, lv, 0); ServerWorld world = cc.s.getWorld(); BlockPos pos = locator.block.getPos(); @@ -1159,7 +1159,7 @@ public class CarpetExpression this.expr.addLazyFunction("set_structure", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; - BlockValue.LocatorResult locator = BlockValue.fromParams(cc, lv, 0); + CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock(cc, lv, 0); ServerWorld world = cc.s.getWorld(); BlockPos pos = locator.block.getPos(); @@ -1223,27 +1223,27 @@ public class CarpetExpression { List listVal = ((ListValue) first).getItems(); int offset = 0; - BlockValue.LocatorResult locator = BlockValue.fromParamValues(cc, listVal, 0, false, false); + CarpetArgParser.BlockArgument locator = CarpetArgParser.fromParamValues(cc, listVal, 0, false, false); requestedChunks.add(new ChunkPos(locator.block.getPos())); while (listVal.size() > locator.offset) { - locator = BlockValue.fromParamValues(cc, listVal, locator.offset, false, false); + locator = CarpetArgParser.fromParamValues(cc, listVal, locator.offset, false, false); requestedChunks.add(new ChunkPos(locator.block.getPos())); } } else { - BlockValue.LocatorResult locator = BlockValue.fromParamValues(cc, Collections.singletonList(first), 0, false, false); + CarpetArgParser.BlockArgument locator = CarpetArgParser.fromParamValues(cc, Collections.singletonList(first), 0, false, false); requestedChunks.add(new ChunkPos(locator.block.getPos())); } } else { - BlockValue.LocatorResult locator = BlockValue.fromParams(cc, lv, 0); + CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock(cc, lv, 0); ChunkPos from = new ChunkPos(locator.block.getPos()); if (lv.size() > locator.offset) { - locator = BlockValue.fromParams(cc, lv, locator.offset); + locator = CarpetArgParser.locateBlock(cc, lv, locator.offset); ChunkPos to = new ChunkPos(locator.block.getPos()); int xmax = Math.max(from.x, to.x); int zmax = Math.max(from.z, to.z); @@ -1285,7 +1285,7 @@ public class CarpetExpression this.expr.addLazyFunction("inhabited_time", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; - BlockValue.LocatorResult locator = BlockValue.fromParams(cc, lv, 0); + CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock(cc, lv, 0); BlockPos pos = locator.block.getPos(); Value ret = new NumericValue(cc.s.getWorld().getChunk(pos).getInhabitedTime()); return (_c, _t) -> ret; @@ -1765,7 +1765,7 @@ public class CarpetExpression return LazyValue.NULL; } - BlockValue.VectorLocator position = BlockValue.locateVec(cc, lv, 1); + CarpetArgParser.Vector3Argument position = CarpetArgParser.locateVector(cc, lv, 1); if (position.fromBlock) position.vec = position.vec.subtract(0, 0.5, 0); CompoundTag tag = new CompoundTag(); @@ -2087,7 +2087,7 @@ public class CarpetExpression this.expr.addLazyFunction("neighbours", -1, (c, t, lv)-> { - BlockPos center = BlockValue.fromParams((CarpetContext) c, lv,0).block.getPos(); + BlockPos center = CarpetArgParser.locateBlock((CarpetContext) c, lv,0).block.getPos(); ServerWorld world = ((CarpetContext) c).s.getWorld(); List neighbours = new ArrayList<>(); @@ -2381,12 +2381,30 @@ public class CarpetExpression private static Map mixerMap = Arrays.stream(SoundCategory.values()).collect(Collectors.toMap(SoundCategory::getName, k -> k)); + private void API_Interapperability() + { + //todo doc and test all + this.expr.addLazyFunction("loaded_apps", 0, (c, t, lv) -> + { + // return a set of all loaded apps + Value ret = new MapValue(((CarpetScriptHost) c.host).getScriptServer().modules.keySet().stream().map(StringValue::new).collect(Collectors.toSet())); + return (cc, tt) -> ret; + }); + + this.expr.addLazyFunction("is_app_loaded", 1, (c, t, lv) -> + { + Value ret = new NumericValue(((CarpetScriptHost) c.host).getScriptServer().modules.containsKey(lv.get(0).evalValue(c).getString())); + return (cc, tt) -> ret; + }); + + } + private void API_AuxiliaryAspects() { this.expr.addLazyFunction("sound", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; Identifier soundName = new Identifier(lv.get(0).evalValue(c).getString()); - BlockValue.VectorLocator locator = BlockValue.locateVec(cc, lv, 1); + CarpetArgParser.Vector3Argument locator = CarpetArgParser.locateVector(cc, lv, 1); if (Registry.SOUND_EVENT.get(soundName) == null) throw new InternalExpressionException("No such sound: "+soundName.getPath()); float volume = 1.0F; @@ -2423,7 +2441,7 @@ public class CarpetExpression CarpetContext cc = (CarpetContext)c; MinecraftServer ms = cc.s.getMinecraftServer(); ServerWorld world = cc.s.getWorld(); - BlockValue.VectorLocator locator = BlockValue.locateVec(cc, lv, 1); + CarpetArgParser.Vector3Argument locator = CarpetArgParser.locateVector(cc, lv, 1); String particleName = lv.get(0).evalValue(c).getString(); int count = 10; double speed = 0; @@ -2471,8 +2489,8 @@ public class CarpetExpression ServerWorld world = cc.s.getWorld(); String particleName = lv.get(0).evalValue(c).getString(); ParticleEffect particle = getParticleData(particleName); - BlockValue.VectorLocator pos1 = BlockValue.locateVec(cc, lv, 1); - BlockValue.VectorLocator pos2 = BlockValue.locateVec(cc, lv, pos1.offset); + CarpetArgParser.Vector3Argument pos1 = CarpetArgParser.locateVector(cc, lv, 1); + CarpetArgParser.Vector3Argument pos2 = CarpetArgParser.locateVector(cc, lv, pos1.offset); int offset = pos2.offset; double density = (lv.size() > offset)? NumericValue.asNumber(lv.get(offset).evalValue(c)).getDouble():1.0; if (density <= 0) @@ -2489,8 +2507,8 @@ public class CarpetExpression ServerWorld world = cc.s.getWorld(); String particleName = lv.get(0).evalValue(c).getString(); ParticleEffect particle = getParticleData(particleName); - BlockValue.VectorLocator pos1 = BlockValue.locateVec(cc, lv, 1); - BlockValue.VectorLocator pos2 = BlockValue.locateVec(cc, lv, pos1.offset); + CarpetArgParser.Vector3Argument pos1 = CarpetArgParser.locateVector(cc, lv, 1); + CarpetArgParser.Vector3Argument pos2 = CarpetArgParser.locateVector(cc, lv, pos1.offset); int offset = pos2.offset; double density = 1.0; if (lv.size() > offset) @@ -2531,17 +2549,17 @@ public class CarpetExpression this.expr.addLazyFunction("create_marker", -1, (c, t, lv) ->{ CarpetContext cc = (CarpetContext)c; BlockState targetBlock = null; - BlockValue.VectorLocator pointLocator; + CarpetArgParser.Vector3Argument pointLocator; boolean interactable = true; String name; try { Value nameValue = lv.get(0).evalValue(c); name = nameValue instanceof NullValue ? "" : nameValue.getString(); - pointLocator = BlockValue.locateVec(cc, lv, 1, true); + pointLocator = CarpetArgParser.locateVector(cc, lv, 1, true); if (lv.size()>pointLocator.offset) { - BlockValue.LocatorResult blockLocator = BlockValue.fromParams(cc, lv, pointLocator.offset, true, true); + CarpetArgParser.BlockArgument blockLocator = CarpetArgParser.locateBlock(cc, lv, pointLocator.offset, true, true); if (blockLocator.block != null) targetBlock = blockLocator.block.getBlockState(); if (lv.size() > blockLocator.offset) { @@ -2790,7 +2808,7 @@ public class CarpetExpression }); this.expr.addLazyFunction("plop", 4, (c, t, lv) ->{ - BlockValue.LocatorResult locator = BlockValue.fromParams((CarpetContext)c, lv, 0); + CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock((CarpetContext)c, lv, 0); if (lv.size() <= locator.offset) throw new InternalExpressionException("'plop' needs extra argument indicating what to plop"); String what = lv.get(locator.offset).evalValue(c).getString(); @@ -2946,6 +2964,7 @@ public class CarpetExpression API_IteratingOverAreasOfBlocks(); API_AuxiliaryAspects(); API_Scoreboard(); + API_Interapperability(); } public boolean fillAndScanCommand(ScriptHost host, int x, int y, int z) diff --git a/src/main/java/carpet/script/CarpetScriptHost.java b/src/main/java/carpet/script/CarpetScriptHost.java index c6a8afa8..bd2b669e 100644 --- a/src/main/java/carpet/script/CarpetScriptHost.java +++ b/src/main/java/carpet/script/CarpetScriptHost.java @@ -491,4 +491,9 @@ public class CarpetScriptHost extends ScriptHost { handleErrorWithStack(message, new CarpetExpressionException(exc.getMessage(), exc.stack)); } + + public CarpetScriptServer getScriptServer() + { + return scriptServer; + } } diff --git a/src/main/java/carpet/script/utils/ArgParser.java b/src/main/java/carpet/script/utils/ArgParser.java new file mode 100644 index 00000000..1d9ee519 --- /dev/null +++ b/src/main/java/carpet/script/utils/ArgParser.java @@ -0,0 +1,17 @@ +package carpet.script.utils; + +import carpet.script.value.FunctionValue; + +public class ArgParser +{ + public static class FunctionArgument + { + public final FunctionValue function; + public final int offset; + FunctionArgument(FunctionValue f, int o) + { + function = f; + offset = o; + } + } +} diff --git a/src/main/java/carpet/script/utils/CarpetArgParser.java b/src/main/java/carpet/script/utils/CarpetArgParser.java new file mode 100644 index 00000000..eeafe256 --- /dev/null +++ b/src/main/java/carpet/script/utils/CarpetArgParser.java @@ -0,0 +1,215 @@ +package carpet.script.utils; + +import carpet.script.CarpetContext; +import carpet.script.LazyValue; +import carpet.script.exception.InternalExpressionException; +import carpet.script.value.*; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; + +import java.util.List; + +public class CarpetArgParser +{ + public static Vector3Argument locateVector(CarpetContext c, List params, int offset) + { + return locateVector(c,params, offset, false); + } + + public static Vector3Argument locateVector(CarpetContext c, List params, int offset, boolean optionalDirection) + { + try + { + Value v1 = params.get(0 + offset).evalValue(c); + if (v1 instanceof BlockValue) + { + return (new Vector3Argument(new Vec3d(((BlockValue) v1).getPos()).add(0.5,0.5,0.5), 1+offset)).fromBlock(); + } + if (v1 instanceof ListValue) + { + List args = ((ListValue) v1).getItems(); + Vec3d pos = new Vec3d( + NumericValue.asNumber(args.get(0)).getDouble(), + NumericValue.asNumber(args.get(1)).getDouble(), + NumericValue.asNumber(args.get(2)).getDouble()); + double yaw = 0.0D; + double pitch = 0.0D; + if (args.size()>3 && optionalDirection) + { + yaw = NumericValue.asNumber(args.get(3)).getDouble(); + pitch = NumericValue.asNumber(args.get(4)).getDouble(); + } + return new Vector3Argument(pos,offset+1, yaw, pitch); + } + Vec3d pos = new Vec3d( + NumericValue.asNumber(v1).getDouble(), + NumericValue.asNumber(params.get(1 + offset).evalValue(c)).getDouble(), + NumericValue.asNumber(params.get(2 + offset).evalValue(c)).getDouble()); + double yaw = 0.0D; + double pitch = 0.0D; + int eatenLength = 3; + if (params.size()>3+offset && optionalDirection) + { + yaw = NumericValue.asNumber(params.get(3 + offset).evalValue(c)).getDouble(); + pitch = NumericValue.asNumber(params.get(4 + offset).evalValue(c)).getDouble(); + eatenLength = 5; + } + + return new Vector3Argument(pos,offset+eatenLength, yaw, pitch); + } + catch (IndexOutOfBoundsException e) + { + throw new InternalExpressionException("Position should be defined either by three coordinates, or a block value"); + } + } + + public static BlockArgument locateBlock(CarpetContext c, List params, int offset) + { + return locateBlock(c, params,offset, false, false); + } + + public static BlockArgument locateBlock(CarpetContext c, List params, int offset, boolean acceptString) + { + return locateBlock(c, params,offset, acceptString, false); + } + + public static BlockArgument locateBlock(CarpetContext c, List params, int offset, boolean acceptString, boolean optional) + { + try + { + Value v1 = params.get(0 + offset).evalValue(c); + //add conditional from string name + if (optional && v1 instanceof NullValue) + { + return new BlockArgument(null, 1+offset); + } + if (acceptString && v1 instanceof StringValue) + { + return new BlockArgument(BlockValue.fromString(v1.getString()), 1+offset); + } + if (v1 instanceof BlockValue) + { + return new BlockArgument(((BlockValue) v1), 1+offset); + } + if (v1 instanceof ListValue) + { + List args = ((ListValue) v1).getItems(); + int xpos = (int) NumericValue.asNumber(args.get(0)).getLong(); + int ypos = (int) NumericValue.asNumber(args.get(1)).getLong(); + int zpos = (int) NumericValue.asNumber(args.get(2)).getLong(); + return new BlockArgument( + new BlockValue( + null, + c.s.getWorld(), + new BlockPos(c.origin.getX() + xpos, c.origin.getY() + ypos, c.origin.getZ() + zpos) + ), + 1+offset); + } + int xpos = (int) NumericValue.asNumber(v1).getLong(); + int ypos = (int) NumericValue.asNumber( params.get(1 + offset).evalValue(c)).getLong(); + int zpos = (int) NumericValue.asNumber( params.get(2 + offset).evalValue(c)).getLong(); + return new BlockArgument( + new BlockValue( + null, + c.s.getWorld(), + new BlockPos(c.origin.getX() + xpos, c.origin.getY() + ypos, c.origin.getZ() + zpos) + ), + 3+offset + ); + } + catch (IndexOutOfBoundsException e) + { + throw new InternalExpressionException("Block should be defined either by three coordinates, a block value, or a proper string"); + } + } + + public static BlockArgument fromParamValues(CarpetContext c, List params, int offset, boolean acceptString, boolean optional) + { + try + { + Value v1 = params.get(0 + offset); + //add conditional from string name + if (optional && v1 instanceof NullValue) + { + return new BlockArgument(null, 1+offset); + } + if (acceptString && v1 instanceof StringValue) + { + return new BlockArgument(BlockValue.fromString(v1.getString()), 1+offset); + } + if (v1 instanceof BlockValue) + { + return new BlockArgument(((BlockValue) v1), 1+offset); + } + if (v1 instanceof ListValue) + { + List args = ((ListValue) v1).getItems(); + int xpos = (int) NumericValue.asNumber(args.get(0)).getLong(); + int ypos = (int) NumericValue.asNumber(args.get(1)).getLong(); + int zpos = (int) NumericValue.asNumber(args.get(2)).getLong(); + return new BlockArgument( + new BlockValue( + null, + c.s.getWorld(), + new BlockPos(c.origin.getX() + xpos, c.origin.getY() + ypos, c.origin.getZ() + zpos) + ), + 1+offset); + } + int xpos = (int) NumericValue.asNumber(v1).getLong(); + int ypos = (int) NumericValue.asNumber( params.get(1 + offset)).getLong(); + int zpos = (int) NumericValue.asNumber( params.get(2 + offset)).getLong(); + return new BlockArgument( + new BlockValue( + null, + c.s.getWorld(), + new BlockPos(c.origin.getX() + xpos, c.origin.getY() + ypos, c.origin.getZ() + zpos) + ), + 3+offset + ); + } + catch (IndexOutOfBoundsException e) + { + throw new InternalExpressionException("Block should be defined either by three coordinates, a block value, or a proper string"); + } + } + + public static class BlockArgument + { + public final BlockValue block; + public final int offset; + BlockArgument(BlockValue b, int o) + { + block = b; + offset = o; + } + } + + public static class Vector3Argument + { + public Vec3d vec; + public final int offset; + public final double yaw; + public final double pitch; + public boolean fromBlock; + Vector3Argument(Vec3d v, int o) + { + vec = v; + offset = o; + yaw = 0.0D; + pitch = 0.0D; + } + Vector3Argument(Vec3d v, int o, double y, double p) + { + vec = v; + offset = o; + yaw = y; + pitch = p; + } + + public Vector3Argument fromBlock() + { + fromBlock = true; + return this; + } + } +} diff --git a/src/main/java/carpet/script/value/BlockValue.java b/src/main/java/carpet/script/value/BlockValue.java index 860b5c24..0f921b01 100644 --- a/src/main/java/carpet/script/value/BlockValue.java +++ b/src/main/java/carpet/script/value/BlockValue.java @@ -72,172 +72,11 @@ public class BlockValue extends Value throw new InternalExpressionException("Cannot parse block: "+str); } - public static VectorLocator locateVec(CarpetContext c, List params, int offset) - { - return locateVec(c,params, offset, false); - } - public static VectorLocator locateVec(CarpetContext c, List params, int offset, boolean optionalDirection) - { - try - { - Value v1 = params.get(0 + offset).evalValue(c); - if (v1 instanceof BlockValue) - { - return (new VectorLocator(new Vec3d(((BlockValue) v1).getPos()).add(0.5,0.5,0.5), 1+offset)).fromBlock(); - } - if (v1 instanceof ListValue) - { - List args = ((ListValue) v1).getItems(); - Vec3d pos = new Vec3d( - NumericValue.asNumber(args.get(0)).getDouble(), - NumericValue.asNumber(args.get(1)).getDouble(), - NumericValue.asNumber(args.get(2)).getDouble()); - double yaw = 0.0D; - double pitch = 0.0D; - if (args.size()>3 && optionalDirection) - { - yaw = NumericValue.asNumber(args.get(3)).getDouble(); - pitch = NumericValue.asNumber(args.get(4)).getDouble(); - } - return new VectorLocator(pos,offset+1, yaw, pitch); - } - Vec3d pos = new Vec3d( - NumericValue.asNumber(v1).getDouble(), - NumericValue.asNumber(params.get(1 + offset).evalValue(c)).getDouble(), - NumericValue.asNumber(params.get(2 + offset).evalValue(c)).getDouble()); - double yaw = 0.0D; - double pitch = 0.0D; - int eatenLength = 3; - if (params.size()>3+offset && optionalDirection) - { - yaw = NumericValue.asNumber(params.get(3 + offset).evalValue(c)).getDouble(); - pitch = NumericValue.asNumber(params.get(4 + offset).evalValue(c)).getDouble(); - eatenLength = 5; - } - - return new VectorLocator(pos,offset+eatenLength, yaw, pitch); - } - catch (IndexOutOfBoundsException e) - { - throw new InternalExpressionException("Position should be defined either by three coordinates, or a block value"); - } - } - public static BlockPos locateBlockPos(CarpetContext c, int xpos, int ypos, int zpos) { return new BlockPos(c.origin.getX() + xpos, c.origin.getY() + ypos, c.origin.getZ() + zpos); } - public static LocatorResult fromParams(CarpetContext c, List params, int offset) - { - return fromParams(c, params,offset, false, false); - } - - public static LocatorResult fromParams(CarpetContext c, List params, int offset, boolean acceptString) - { - return fromParams(c, params,offset, acceptString, false); - } - - public static LocatorResult fromParams(CarpetContext c, List params, int offset, boolean acceptString, boolean optional) - { - try - { - Value v1 = params.get(0 + offset).evalValue(c); - //add conditional from string name - if (optional && v1 instanceof NullValue) - { - return new LocatorResult(null, 1+offset); - } - if (acceptString && v1 instanceof StringValue) - { - return new LocatorResult(fromString(v1.getString()), 1+offset); - } - if (v1 instanceof BlockValue) - { - return new LocatorResult(((BlockValue) v1), 1+offset); - } - if (v1 instanceof ListValue) - { - List args = ((ListValue) v1).getItems(); - int xpos = (int) NumericValue.asNumber(args.get(0)).getLong(); - int ypos = (int) NumericValue.asNumber(args.get(1)).getLong(); - int zpos = (int) NumericValue.asNumber(args.get(2)).getLong(); - return new LocatorResult( - new BlockValue( - null, - c.s.getWorld(), - new BlockPos(c.origin.getX() + xpos, c.origin.getY() + ypos, c.origin.getZ() + zpos) - ), - 1+offset); - } - int xpos = (int) NumericValue.asNumber(v1).getLong(); - int ypos = (int) NumericValue.asNumber( params.get(1 + offset).evalValue(c)).getLong(); - int zpos = (int) NumericValue.asNumber( params.get(2 + offset).evalValue(c)).getLong(); - return new LocatorResult( - new BlockValue( - null, - c.s.getWorld(), - new BlockPos(c.origin.getX() + xpos, c.origin.getY() + ypos, c.origin.getZ() + zpos) - ), - 3+offset - ); - } - catch (IndexOutOfBoundsException e) - { - throw new InternalExpressionException("Block should be defined either by three coordinates, a block value, or a proper string"); - } - } - - public static LocatorResult fromParamValues(CarpetContext c, List params, int offset, boolean acceptString, boolean optional) - { - try - { - Value v1 = params.get(0 + offset); - //add conditional from string name - if (optional && v1 instanceof NullValue) - { - return new LocatorResult(null, 1+offset); - } - if (acceptString && v1 instanceof StringValue) - { - return new LocatorResult(fromString(v1.getString()), 1+offset); - } - if (v1 instanceof BlockValue) - { - return new LocatorResult(((BlockValue) v1), 1+offset); - } - if (v1 instanceof ListValue) - { - List args = ((ListValue) v1).getItems(); - int xpos = (int) NumericValue.asNumber(args.get(0)).getLong(); - int ypos = (int) NumericValue.asNumber(args.get(1)).getLong(); - int zpos = (int) NumericValue.asNumber(args.get(2)).getLong(); - return new LocatorResult( - new BlockValue( - null, - c.s.getWorld(), - new BlockPos(c.origin.getX() + xpos, c.origin.getY() + ypos, c.origin.getZ() + zpos) - ), - 1+offset); - } - int xpos = (int) NumericValue.asNumber(v1).getLong(); - int ypos = (int) NumericValue.asNumber( params.get(1 + offset)).getLong(); - int zpos = (int) NumericValue.asNumber( params.get(2 + offset)).getLong(); - return new LocatorResult( - new BlockValue( - null, - c.s.getWorld(), - new BlockPos(c.origin.getX() + xpos, c.origin.getY() + ypos, c.origin.getZ() + zpos) - ), - 3+offset - ); - } - catch (IndexOutOfBoundsException e) - { - throw new InternalExpressionException("Block should be defined either by three coordinates, a block value, or a proper string"); - } - } - public BlockState getBlockState() { if (blockState != null) @@ -342,46 +181,6 @@ public class BlockValue extends Value public ServerWorld getWorld() { return world;} - public static class LocatorResult - { - public final BlockValue block; - public final int offset; - LocatorResult(BlockValue b, int o) - { - block = b; - offset = o; - } - } - - public static class VectorLocator - { - public Vec3d vec; - public final int offset; - public final double yaw; - public final double pitch; - public boolean fromBlock; - VectorLocator(Vec3d v, int o) - { - vec = v; - offset = o; - yaw = 0.0D; - pitch = 0.0D; - } - VectorLocator(Vec3d v, int o, double y, double p) - { - vec = v; - offset = o; - yaw = y; - pitch = p; - } - - public VectorLocator fromBlock() - { - fromBlock = true; - return this; - } - } - public enum SpecificDirection { UP("up",0.5, 0.0, 0.5, Direction.UP), diff --git a/src/main/java/carpet/script/value/MapValue.java b/src/main/java/carpet/script/value/MapValue.java index 8e22001c..61965e4e 100644 --- a/src/main/java/carpet/script/value/MapValue.java +++ b/src/main/java/carpet/script/value/MapValue.java @@ -7,6 +7,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; public class MapValue extends AbstractListValue implements ContainerValueInterface @@ -27,6 +28,15 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa } } + public MapValue(Set keySet) + { + this(); + for (Value v : keySet) + { + map.put(v, Value.NULL); + } + } + @Override public Iterator iterator() { From 17b15b48933c803696abdcb162d37d315aa7edbe Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 16 Apr 2020 23:30:05 -0300 Subject: [PATCH 022/198] refactor arg parsers --- .../java/carpet/script/CarpetExpression.java | 107 +++++---- src/main/java/carpet/script/Expression.java | 17 +- .../java/carpet/script/argument/Argument.java | 10 + .../carpet/script/argument/BlockArgument.java | 133 +++++++++++ .../script/argument/FunctionArgument.java | 56 +++++ .../script/argument/Vector3Argument.java | 93 ++++++++ .../java/carpet/script/utils/ArgParser.java | 17 -- .../carpet/script/utils/CarpetArgParser.java | 209 ------------------ 8 files changed, 369 insertions(+), 273 deletions(-) create mode 100644 src/main/java/carpet/script/argument/Argument.java create mode 100644 src/main/java/carpet/script/argument/BlockArgument.java create mode 100644 src/main/java/carpet/script/argument/FunctionArgument.java create mode 100644 src/main/java/carpet/script/argument/Vector3Argument.java delete mode 100644 src/main/java/carpet/script/utils/ArgParser.java diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index ed9419fd..c75a156b 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -10,6 +10,9 @@ import carpet.fakes.ThreadedAnvilChunkStorageInterface; import carpet.helpers.FeatureGenerator; import carpet.mixins.PointOfInterest_scarpetMixin; import carpet.script.Fluff.TriFunction; +import carpet.script.argument.BlockArgument; +import carpet.script.argument.FunctionArgument; +import carpet.script.argument.Vector3Argument; import carpet.script.bundled.Module; import carpet.CarpetSettings; import carpet.script.exception.BreakStatement; @@ -175,7 +178,7 @@ public class CarpetExpression Value retval = test.apply(((BlockValue) v0).getBlockState(), ((BlockValue) v0).getPos()) ? Value.TRUE : Value.FALSE; return (c_, t_) -> retval; } - BlockValue block = CarpetArgParser.locateBlock(cc, params, 0).block; + BlockValue block = BlockArgument.findIn(cc, params, 0).block; Value retval = test.apply(block.getBlockState(), block.getPos()) ? Value.TRUE : Value.FALSE; return (c_, t_) -> retval; } @@ -200,7 +203,7 @@ public class CarpetExpression Value retval = strVal != null ? new StringValue(strVal) : Value.NULL; return (c_, t_) -> retval; } - BlockValue block = CarpetArgParser.locateBlock(cc, params, 0).block; + BlockValue block = BlockArgument.findIn(cc, params, 0).block; String strVal = test.apply(block.getBlockState(), block.getPos()); Value retval = strVal != null ? new StringValue(strVal) : Value.NULL; return (c_, t_) -> retval; @@ -231,7 +234,7 @@ public class CarpetExpression throw new InternalExpressionException("'" + name + "' function requires a block that is positioned in the world"); } } - BlockValue block = CarpetArgParser.locateBlock(cc, params, 0).block; + BlockValue block = BlockArgument.findIn(cc, params, 0).block; Value retval = test.apply(block.getBlockState(), block.getPos(), cc.s.getWorld()); return (c_, t_) -> retval; } @@ -400,7 +403,7 @@ public class CarpetExpression { throw new InternalExpressionException("Block requires at least one parameter"); } - BlockValue retval = CarpetArgParser.locateBlock(cc, lv, 0, true).block; + BlockValue retval = BlockArgument.findIn(cc, lv, 0, true).block; // fixing block state and data retval.getBlockState(); retval.getData(); @@ -414,7 +417,7 @@ public class CarpetExpression { throw new InternalExpressionException("Block requires at least one parameter"); } - CompoundTag tag = CarpetArgParser.locateBlock(cc, lv, 0, true).block.getData(); + CompoundTag tag = BlockArgument.findIn(cc, lv, 0, true).block.getData(); if (tag == null) return (c_, t_) -> Value.NULL; Value retval = new NBTSerializableValue(tag); @@ -426,7 +429,7 @@ public class CarpetExpression { CarpetContext cc = (CarpetContext) c; if (lv.size() == 0) throw new InternalExpressionException("'poi' requires at least one parameter"); - CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock(cc, lv, 0, false); + BlockArgument locator = BlockArgument.findIn(cc, lv, 0, false); BlockPos pos = locator.block.getPos(); PointOfInterestStorage store = cc.s.getWorld().getPointOfInterestStorage(); if (lv.size() == locator.offset) @@ -492,7 +495,7 @@ public class CarpetExpression { CarpetContext cc = (CarpetContext) c; if (lv.size() == 0) throw new InternalExpressionException("'set_poi' requires at least one parameter"); - CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock(cc, lv, 0, false); + BlockArgument locator = BlockArgument.findIn(cc, lv, 0, false); BlockPos pos = locator.block.getPos(); if (lv.size() < locator.offset) throw new InternalExpressionException("'set_poi' requires the new poi type or null, after position argument"); Value poi = lv.get(locator.offset+0).evalValue(c); @@ -559,7 +562,7 @@ public class CarpetExpression this.expr.addLazyFunction("pos_offset", -1, (c, t, lv) -> { - CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock((CarpetContext)c, lv, 0); + BlockArgument locator = BlockArgument.findIn((CarpetContext)c, lv, 0); BlockPos pos = locator.block.getPos(); if (lv.size() <= locator.offset) throw new InternalExpressionException("'pos_offset' needs at least position, and direction"); @@ -622,7 +625,7 @@ public class CarpetExpression this.expr.addLazyFunction("in_slime_chunk", -1, (c, t, lv) -> { - BlockPos pos = CarpetArgParser.locateBlock((CarpetContext)c, lv, 0).block.getPos(); + BlockPos pos = BlockArgument.findIn((CarpetContext)c, lv, 0).block.getPos(); ChunkPos chunkPos = new ChunkPos(pos); Value ret = new NumericValue(ChunkRandom.create( chunkPos.x, chunkPos.z, @@ -646,7 +649,7 @@ public class CarpetExpression case "surface": htype = Heightmap.Type.WORLD_SURFACE; break; default: throw new InternalExpressionException("Unknown heightmap type: "+type); } - CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock((CarpetContext)c, lv, 1); + BlockArgument locator = BlockArgument.findIn((CarpetContext)c, lv, 1); BlockPos pos = locator.block.getPos(); int x = pos.getX(); int z = pos.getZ(); @@ -658,21 +661,21 @@ public class CarpetExpression this.expr.addLazyFunction("loaded", -1, (c, t, lv) -> { - Value retval = ((CarpetContext) c).s.getWorld().isChunkLoaded(CarpetArgParser.locateBlock((CarpetContext) c, lv, 0).block.getPos()) ? Value.TRUE : Value.FALSE; + Value retval = ((CarpetContext) c).s.getWorld().isChunkLoaded(BlockArgument.findIn((CarpetContext) c, lv, 0).block.getPos()) ? Value.TRUE : Value.FALSE; return (c_, t_) -> retval; }); // Deprecated, use loaded_status as more indicative this.expr.addLazyFunction("loaded_ep", -1, (c, t, lv) -> { - BlockPos pos = CarpetArgParser.locateBlock((CarpetContext)c, lv, 0).block.getPos(); + BlockPos pos = BlockArgument.findIn((CarpetContext)c, lv, 0).block.getPos(); Value retval = ((CarpetContext)c).s.getWorld().getChunkManager().shouldTickChunk(new ChunkPos(pos))?Value.TRUE : Value.FALSE; return (c_, t_) -> retval; }); this.expr.addLazyFunction("loaded_status", -1, (c, t, lv) -> { - BlockPos pos = CarpetArgParser.locateBlock((CarpetContext)c, lv, 0).block.getPos(); + BlockPos pos = BlockArgument.findIn((CarpetContext)c, lv, 0).block.getPos(); WorldChunk chunk = ((CarpetContext)c).s.getWorld().getChunkManager().getWorldChunk(pos.getX()>>4, pos.getZ()>>4, false); if (chunk == null) return LazyValue.ZERO; @@ -682,7 +685,7 @@ public class CarpetExpression this.expr.addLazyFunction("is_chunk_generated", -1, (c, t, lv) -> { - CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock((CarpetContext)c, lv, 0); + BlockArgument locator = BlockArgument.findIn((CarpetContext)c, lv, 0); BlockPos pos = locator.block.getPos(); boolean force = false; if (lv.size() > locator.offset) @@ -693,7 +696,7 @@ public class CarpetExpression this.expr.addLazyFunction("generation_status", -1, (c, t, lv) -> { - CarpetArgParser.BlockArgument blockArgument = CarpetArgParser.locateBlock((CarpetContext)c, lv, 0); + BlockArgument blockArgument = BlockArgument.findIn((CarpetContext)c, lv, 0); BlockPos pos = blockArgument.block.getPos(); boolean forceLoad = false; if (lv.size() > blockArgument.offset) @@ -731,7 +734,7 @@ public class CarpetExpression } else { - CarpetArgParser.BlockArgument blockArgument = CarpetArgParser.locateBlock((CarpetContext) c, lv, 0); + BlockArgument blockArgument = BlockArgument.findIn((CarpetContext) c, lv, 0); BlockPos pos = blockArgument.block.getPos(); SortedArraySet> tickets = levelTickets.get(new ChunkPos(pos).toLong()); if (tickets != null) @@ -804,8 +807,8 @@ public class CarpetExpression ServerWorld world = cc.s.getWorld(); if (lv.size() < 2 || lv.size() % 2 == 1) throw new InternalExpressionException("'set' should have at least 2 params and odd attributes"); - CarpetArgParser.BlockArgument targetLocator = CarpetArgParser.locateBlock(cc, lv, 0); - CarpetArgParser.BlockArgument sourceLocator = CarpetArgParser.locateBlock(cc, lv, targetLocator.offset, true); + BlockArgument targetLocator = BlockArgument.findIn(cc, lv, 0); + BlockArgument sourceLocator = BlockArgument.findIn(cc, lv, targetLocator.offset, true); BlockState sourceBlockState = sourceLocator.block.getBlockState(); BlockState targetBlockState = world.getBlockState(targetLocator.block.getPos()); if (sourceLocator.offset < lv.size()) @@ -854,7 +857,7 @@ public class CarpetExpression { CarpetContext cc = (CarpetContext)c; ServerWorld world = cc.s.getWorld(); - CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock(cc, lv, 0); + BlockArgument locator = BlockArgument.findIn(cc, lv, 0); BlockState state = locator.block.getBlockState(); if (state.isAir()) return (c_, t_) -> Value.FALSE; @@ -964,7 +967,7 @@ public class CarpetExpression if (!(e instanceof ServerPlayerEntity)) return (c_, t_) -> Value.FALSE; ServerPlayerEntity player = (ServerPlayerEntity)e; - CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock(cc, lv, 1); + BlockArgument locator = BlockArgument.findIn(cc, lv, 1); BlockPos where = locator.block.getPos(); BlockState state = locator.block.getBlockState(); Block block = state.getBlock(); @@ -982,7 +985,7 @@ public class CarpetExpression throw new InternalExpressionException("'place_item' takes at least 2 parameters: item and block, or position, to place onto"); CarpetContext cc = (CarpetContext) c; String itemString = lv.get(0).evalValue(c).getString(); - CarpetArgParser.Vector3Argument locator = CarpetArgParser.locateVector(cc, lv, 1); + Vector3Argument locator = Vector3Argument.findIn(cc, lv, 1); ItemStackArgument stackArg = NBTSerializableValue.parseItem(itemString); BlockPos where = new BlockPos(locator.vec); String facing = "up"; @@ -1038,7 +1041,7 @@ public class CarpetExpression this.expr.addLazyFunction("property", -1, (c, t, lv) -> { - CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock((CarpetContext) c, lv, 0); + BlockArgument locator = BlockArgument.findIn((CarpetContext) c, lv, 0); BlockState state = locator.block.getBlockState(); if (lv.size() <= locator.offset) throw new InternalExpressionException("'property' requires to specify a property to query"); @@ -1053,7 +1056,7 @@ public class CarpetExpression this.expr.addLazyFunction("block_properties", -1, (c, t, lv) -> { - CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock((CarpetContext) c, lv, 0); + BlockArgument locator = BlockArgument.findIn((CarpetContext) c, lv, 0); BlockState state = locator.block.getBlockState(); StateManager states = state.getBlock().getStateManager(); Value res = ListValue.wrap(states.getProperties().stream().map( @@ -1064,7 +1067,7 @@ public class CarpetExpression this.expr.addLazyFunction("biome", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; - CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock(cc, lv, 0); + BlockArgument locator = BlockArgument.findIn(cc, lv, 0); ServerWorld world = cc.s.getWorld(); BlockPos pos = locator.block.getPos(); Biome biome = world.getBiome(pos); @@ -1075,7 +1078,7 @@ public class CarpetExpression this.expr.addLazyFunction("set_biome", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; - CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock(cc, lv, 0); + BlockArgument locator = BlockArgument.findIn(cc, lv, 0); if (lv.size() == locator.offset) throw new InternalExpressionException("'set_biome' needs a biome name as an argument"); String biomeName = lv.get(locator.offset+0).evalValue(c).getString(); @@ -1092,7 +1095,7 @@ public class CarpetExpression this.expr.addLazyFunction("structure_references", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; - CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock(cc, lv, 0); + BlockArgument locator = BlockArgument.findIn(cc, lv, 0); ServerWorld world = cc.s.getWorld(); BlockPos pos = locator.block.getPos(); Map references = world.getChunk(pos).getStructureReferences(); @@ -1117,7 +1120,7 @@ public class CarpetExpression this.expr.addLazyFunction("structures", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; - CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock(cc, lv, 0); + BlockArgument locator = BlockArgument.findIn(cc, lv, 0); ServerWorld world = cc.s.getWorld(); BlockPos pos = locator.block.getPos(); @@ -1159,7 +1162,7 @@ public class CarpetExpression this.expr.addLazyFunction("set_structure", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; - CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock(cc, lv, 0); + BlockArgument locator = BlockArgument.findIn(cc, lv, 0); ServerWorld world = cc.s.getWorld(); BlockPos pos = locator.block.getPos(); @@ -1223,27 +1226,27 @@ public class CarpetExpression { List listVal = ((ListValue) first).getItems(); int offset = 0; - CarpetArgParser.BlockArgument locator = CarpetArgParser.fromParamValues(cc, listVal, 0, false, false); + BlockArgument locator = BlockArgument.findInValues(cc, listVal, 0, false, false); requestedChunks.add(new ChunkPos(locator.block.getPos())); while (listVal.size() > locator.offset) { - locator = CarpetArgParser.fromParamValues(cc, listVal, locator.offset, false, false); + locator = BlockArgument.findInValues(cc, listVal, locator.offset, false, false); requestedChunks.add(new ChunkPos(locator.block.getPos())); } } else { - CarpetArgParser.BlockArgument locator = CarpetArgParser.fromParamValues(cc, Collections.singletonList(first), 0, false, false); + BlockArgument locator = BlockArgument.findInValues(cc, Collections.singletonList(first), 0, false, false); requestedChunks.add(new ChunkPos(locator.block.getPos())); } } else { - CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock(cc, lv, 0); + BlockArgument locator = BlockArgument.findIn(cc, lv, 0); ChunkPos from = new ChunkPos(locator.block.getPos()); if (lv.size() > locator.offset) { - locator = CarpetArgParser.locateBlock(cc, lv, locator.offset); + locator = BlockArgument.findIn(cc, lv, locator.offset); ChunkPos to = new ChunkPos(locator.block.getPos()); int xmax = Math.max(from.x, to.x); int zmax = Math.max(from.z, to.z); @@ -1285,7 +1288,7 @@ public class CarpetExpression this.expr.addLazyFunction("inhabited_time", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; - CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock(cc, lv, 0); + BlockArgument locator = BlockArgument.findIn(cc, lv, 0); BlockPos pos = locator.block.getPos(); Value ret = new NumericValue(cc.s.getWorld().getChunk(pos).getInhabitedTime()); return (_c, _t) -> ret; @@ -1765,7 +1768,7 @@ public class CarpetExpression return LazyValue.NULL; } - CarpetArgParser.Vector3Argument position = CarpetArgParser.locateVector(cc, lv, 1); + Vector3Argument position = Vector3Argument.findIn(cc, lv, 1); if (position.fromBlock) position.vec = position.vec.subtract(0, 0.5, 0); CompoundTag tag = new CompoundTag(); @@ -2087,7 +2090,7 @@ public class CarpetExpression this.expr.addLazyFunction("neighbours", -1, (c, t, lv)-> { - BlockPos center = CarpetArgParser.locateBlock((CarpetContext) c, lv,0).block.getPos(); + BlockPos center = BlockArgument.findIn((CarpetContext) c, lv,0).block.getPos(); ServerWorld world = ((CarpetContext) c).s.getWorld(); List neighbours = new ArrayList<>(); @@ -2404,7 +2407,7 @@ public class CarpetExpression this.expr.addLazyFunction("sound", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; Identifier soundName = new Identifier(lv.get(0).evalValue(c).getString()); - CarpetArgParser.Vector3Argument locator = CarpetArgParser.locateVector(cc, lv, 1); + Vector3Argument locator = Vector3Argument.findIn(cc, lv, 1); if (Registry.SOUND_EVENT.get(soundName) == null) throw new InternalExpressionException("No such sound: "+soundName.getPath()); float volume = 1.0F; @@ -2441,7 +2444,7 @@ public class CarpetExpression CarpetContext cc = (CarpetContext)c; MinecraftServer ms = cc.s.getMinecraftServer(); ServerWorld world = cc.s.getWorld(); - CarpetArgParser.Vector3Argument locator = CarpetArgParser.locateVector(cc, lv, 1); + Vector3Argument locator = Vector3Argument.findIn(cc, lv, 1); String particleName = lv.get(0).evalValue(c).getString(); int count = 10; double speed = 0; @@ -2489,8 +2492,8 @@ public class CarpetExpression ServerWorld world = cc.s.getWorld(); String particleName = lv.get(0).evalValue(c).getString(); ParticleEffect particle = getParticleData(particleName); - CarpetArgParser.Vector3Argument pos1 = CarpetArgParser.locateVector(cc, lv, 1); - CarpetArgParser.Vector3Argument pos2 = CarpetArgParser.locateVector(cc, lv, pos1.offset); + Vector3Argument pos1 = Vector3Argument.findIn(cc, lv, 1); + Vector3Argument pos2 = Vector3Argument.findIn(cc, lv, pos1.offset); int offset = pos2.offset; double density = (lv.size() > offset)? NumericValue.asNumber(lv.get(offset).evalValue(c)).getDouble():1.0; if (density <= 0) @@ -2507,8 +2510,8 @@ public class CarpetExpression ServerWorld world = cc.s.getWorld(); String particleName = lv.get(0).evalValue(c).getString(); ParticleEffect particle = getParticleData(particleName); - CarpetArgParser.Vector3Argument pos1 = CarpetArgParser.locateVector(cc, lv, 1); - CarpetArgParser.Vector3Argument pos2 = CarpetArgParser.locateVector(cc, lv, pos1.offset); + Vector3Argument pos1 = Vector3Argument.findIn(cc, lv, 1); + Vector3Argument pos2 = Vector3Argument.findIn(cc, lv, pos1.offset); int offset = pos2.offset; double density = 1.0; if (lv.size() > offset) @@ -2549,17 +2552,17 @@ public class CarpetExpression this.expr.addLazyFunction("create_marker", -1, (c, t, lv) ->{ CarpetContext cc = (CarpetContext)c; BlockState targetBlock = null; - CarpetArgParser.Vector3Argument pointLocator; + Vector3Argument pointLocator; boolean interactable = true; String name; try { Value nameValue = lv.get(0).evalValue(c); name = nameValue instanceof NullValue ? "" : nameValue.getString(); - pointLocator = CarpetArgParser.locateVector(cc, lv, 1, true); + pointLocator = Vector3Argument.findIn(cc, lv, 1, true); if (lv.size()>pointLocator.offset) { - CarpetArgParser.BlockArgument blockLocator = CarpetArgParser.locateBlock(cc, lv, pointLocator.offset, true, true); + BlockArgument blockLocator = BlockArgument.findIn(cc, lv, pointLocator.offset, true, true); if (blockLocator.block != null) targetBlock = blockLocator.block.getBlockState(); if (lv.size() > blockLocator.offset) { @@ -2808,7 +2811,7 @@ public class CarpetExpression }); this.expr.addLazyFunction("plop", 4, (c, t, lv) ->{ - CarpetArgParser.BlockArgument locator = CarpetArgParser.locateBlock((CarpetContext)c, lv, 0); + BlockArgument locator = BlockArgument.findIn((CarpetContext)c, lv, 0); if (lv.size() <= locator.offset) throw new InternalExpressionException("'plop' needs extra argument indicating what to plop"); String what = lv.get(locator.offset).evalValue(c).getString(); @@ -2832,6 +2835,16 @@ public class CarpetExpression throw new InternalExpressionException("'schedule' should have at least 2 arguments, delay and call name"); long delay = NumericValue.asNumber(lv.get(0).evalValue(c)).getLong(); + FunctionArgument functionArgument = FunctionArgument.findIn(c, this.expr.module, lv, 1, true); + + CarpetServer.scriptServer.events.scheduleCall( + (CarpetContext) c, + functionArgument.function, + functionArgument.resolveArgs(c, Context.NONE), + delay + ); + return (c_, t_) -> Value.TRUE; + /* Value functionValue = lv.get(1).evalValue(c); if (!(functionValue instanceof FunctionValue)) { @@ -2852,6 +2865,8 @@ public class CarpetExpression function.getArguments().size()+" arguments, "+args.size()+" provided."); CarpetServer.scriptServer.events.scheduleCall(cc, function, args, delay); return (c_, t_) -> Value.TRUE; + */ + }); this.expr.addLazyFunction("load_app_data", -1, (c, t, lv) -> diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index f03e4855..b441ec71 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -11,6 +11,7 @@ import carpet.script.Fluff.QuadFunction; import carpet.script.Fluff.QuinnFunction; import carpet.script.Fluff.SexFunction; import carpet.script.Fluff.TriFunction; +import carpet.script.argument.FunctionArgument; import carpet.script.bundled.Module; import carpet.script.exception.BreakStatement; import carpet.script.exception.ContinueStatement; @@ -439,6 +440,12 @@ public class Expression //lv.remove(lv.size()-1); // aint gonna cut it // maybe it will because of the eager eval changes if (t != Context.SIGNATURE) // just call the function { + FunctionArgument functionArgument = FunctionArgument.findIn(c, module, lv, 0, true); + FunctionValue fun = functionArgument.function; + Value retval = fun.callInContext(expr, c, t, fun.getExpression(), fun.getToken(), functionArgument.args).evalValue(c); + return (cc, tt) -> retval; ///!!!! dono might need to store expr and token in statics? (e? t?) + + /* Value functionValue = lv.get(0).evalValue(c); if (!(functionValue instanceof FunctionValue)) { @@ -453,6 +460,7 @@ public class Expression FunctionValue fun = (FunctionValue)functionValue; Value retval = fun.callInContext(expr, c, t, fun.getExpression(), fun.getToken(), lvargs).evalValue(c); return (cc, tt) -> retval; ///!!!! dono might need to store expr and token in statics? (e? t?) + */ } // gimme signature String name = lv.get(0).evalValue(c).getString(); @@ -1870,6 +1878,13 @@ public class Expression addLazyFunctionWithDelegation("task", -1, (c, t, expr, tok, lv) -> { if (lv.size() == 0) throw new InternalExpressionException("'task' requires at least function to call as a parameter"); + FunctionArgument functionArgument = FunctionArgument.findIn(c, module, lv, 0); + Value queue = Value.NULL; + if (lv.size() > functionArgument.offset) queue = lv.get(functionArgument.offset).evalValue(c); + ThreadValue thread = new ThreadValue(queue, functionArgument.function, expr, tok, c, functionArgument.args); + Thread.yield(); + return (cc, tt) -> thread; + /* Value funcDesc = lv.get(0).evalValue(c); if (!(funcDesc instanceof FunctionValue)) { @@ -1891,7 +1906,7 @@ public class Expression if (extraargs == 2) queue = lv.get(lv.size()-1).evalValue(c); ThreadValue thread = new ThreadValue(queue, fun, expr, tok, c, lvargs); Thread.yield(); - return (cc, tt) -> thread; + return (cc, tt) -> thread;*/ }); addFunction("task_count", (lv) -> diff --git a/src/main/java/carpet/script/argument/Argument.java b/src/main/java/carpet/script/argument/Argument.java new file mode 100644 index 00000000..1a9dbd41 --- /dev/null +++ b/src/main/java/carpet/script/argument/Argument.java @@ -0,0 +1,10 @@ +package carpet.script.argument; + +public abstract class Argument +{ + public int offset; + protected Argument(int offset) + { + this.offset = offset; + } +} diff --git a/src/main/java/carpet/script/argument/BlockArgument.java b/src/main/java/carpet/script/argument/BlockArgument.java new file mode 100644 index 00000000..0e492f64 --- /dev/null +++ b/src/main/java/carpet/script/argument/BlockArgument.java @@ -0,0 +1,133 @@ +package carpet.script.argument; + +import carpet.script.CarpetContext; +import carpet.script.LazyValue; +import carpet.script.exception.InternalExpressionException; +import carpet.script.value.BlockValue; +import carpet.script.value.ListValue; +import carpet.script.value.NullValue; +import carpet.script.value.NumericValue; +import carpet.script.value.StringValue; +import carpet.script.value.Value; +import net.minecraft.util.math.BlockPos; + +import java.util.List; + +public class BlockArgument extends Argument +{ + public final BlockValue block; + private BlockArgument(BlockValue b, int o) + { + super(o); + block = b; + } + public static BlockArgument findIn(CarpetContext c, List params, int offset) + { + return findIn(c, params,offset, false, false); + } + + public static BlockArgument findIn(CarpetContext c, List params, int offset, boolean acceptString) + { + return findIn(c, params,offset, acceptString, false); + } + + public static BlockArgument findIn(CarpetContext c, List params, int offset, boolean acceptString, boolean optional) + { + try + { + Value v1 = params.get(0 + offset).evalValue(c); + //add conditional from string name + if (optional && v1 instanceof NullValue) + { + return new BlockArgument(null, 1+offset); + } + if (acceptString && v1 instanceof StringValue) + { + return new BlockArgument(BlockValue.fromString(v1.getString()), 1+offset); + } + if (v1 instanceof BlockValue) + { + return new BlockArgument(((BlockValue) v1), 1+offset); + } + if (v1 instanceof ListValue) + { + List args = ((ListValue) v1).getItems(); + int xpos = (int) NumericValue.asNumber(args.get(0)).getLong(); + int ypos = (int) NumericValue.asNumber(args.get(1)).getLong(); + int zpos = (int) NumericValue.asNumber(args.get(2)).getLong(); + return new BlockArgument( + new BlockValue( + null, + c.s.getWorld(), + new BlockPos(c.origin.getX() + xpos, c.origin.getY() + ypos, c.origin.getZ() + zpos) + ), + 1+offset); + } + int xpos = (int) NumericValue.asNumber(v1).getLong(); + int ypos = (int) NumericValue.asNumber( params.get(1 + offset).evalValue(c)).getLong(); + int zpos = (int) NumericValue.asNumber( params.get(2 + offset).evalValue(c)).getLong(); + return new BlockArgument( + new BlockValue( + null, + c.s.getWorld(), + new BlockPos(c.origin.getX() + xpos, c.origin.getY() + ypos, c.origin.getZ() + zpos) + ), + 3+offset + ); + } + catch (IndexOutOfBoundsException e) + { + throw new InternalExpressionException("Block should be defined either by three coordinates, a block value, or a proper string"); + } + } + + public static BlockArgument findInValues(CarpetContext c, List params, int offset, boolean acceptString, boolean optional) + { + try + { + Value v1 = params.get(0 + offset); + //add conditional from string name + if (optional && v1 instanceof NullValue) + { + return new BlockArgument(null, 1+offset); + } + if (acceptString && v1 instanceof StringValue) + { + return new BlockArgument(BlockValue.fromString(v1.getString()), 1+offset); + } + if (v1 instanceof BlockValue) + { + return new BlockArgument(((BlockValue) v1), 1+offset); + } + if (v1 instanceof ListValue) + { + List args = ((ListValue) v1).getItems(); + int xpos = (int) NumericValue.asNumber(args.get(0)).getLong(); + int ypos = (int) NumericValue.asNumber(args.get(1)).getLong(); + int zpos = (int) NumericValue.asNumber(args.get(2)).getLong(); + return new BlockArgument( + new BlockValue( + null, + c.s.getWorld(), + new BlockPos(c.origin.getX() + xpos, c.origin.getY() + ypos, c.origin.getZ() + zpos) + ), + 1+offset); + } + int xpos = (int) NumericValue.asNumber(v1).getLong(); + int ypos = (int) NumericValue.asNumber( params.get(1 + offset)).getLong(); + int zpos = (int) NumericValue.asNumber( params.get(2 + offset)).getLong(); + return new BlockArgument( + new BlockValue( + null, + c.s.getWorld(), + new BlockPos(c.origin.getX() + xpos, c.origin.getY() + ypos, c.origin.getZ() + zpos) + ), + 3+offset + ); + } + catch (IndexOutOfBoundsException e) + { + throw new InternalExpressionException("Block should be defined either by three coordinates, a block value, or a proper string"); + } + } +} diff --git a/src/main/java/carpet/script/argument/FunctionArgument.java b/src/main/java/carpet/script/argument/FunctionArgument.java new file mode 100644 index 00000000..4f3ba735 --- /dev/null +++ b/src/main/java/carpet/script/argument/FunctionArgument.java @@ -0,0 +1,56 @@ +package carpet.script.argument; + +import carpet.script.CarpetContext; +import carpet.script.Context; +import carpet.script.LazyValue; +import carpet.script.bundled.Module; +import carpet.script.exception.InternalExpressionException; +import carpet.script.value.FunctionValue; +import carpet.script.value.Value; + +import java.util.ArrayList; +import java.util.List; + +public class FunctionArgument extends Argument +{ + public FunctionValue function; + public List args; + + private FunctionArgument(FunctionValue function, int offset, List args) + { + super(offset); + this.function = function; + this.args = args; + } + public static FunctionArgument findIn(Context c, Module module, List params, int offset) + { + return findIn(c, module, params, offset, false); + } + public static FunctionArgument findIn(Context c, Module module, List params, int offset, boolean strict) + { + Value functionValue = params.get(offset).evalValue(c); + if (!(functionValue instanceof FunctionValue)) + { + String name = functionValue.getString(); + functionValue = c.host.getAssertFunction(module, name); + } + FunctionValue fun = (FunctionValue)functionValue; + int argsize = fun.getArguments().size(); + int extraargs = params.size() - argsize - offset - 1; + if (extraargs < 0 || (extraargs > 0 && strict)) + throw new InternalExpressionException("Function "+fun.getPrettyString()+" requires "+fun.getArguments().size()+" arguments"); + List lvargs = new ArrayList<>(); + for (int i=0; i< argsize; i++) + { + lvargs.add(params.get(offset+1+i)); + } + return new FunctionArgument(fun, offset+1+argsize, lvargs); + } + + public List resolveArgs(Context context, Integer type) + { + List res = new ArrayList<>(args.size()); + for (LazyValue arg : args) res.add(arg.evalValue(context, type)); + return res; + } +} diff --git a/src/main/java/carpet/script/argument/Vector3Argument.java b/src/main/java/carpet/script/argument/Vector3Argument.java new file mode 100644 index 00000000..beb2a827 --- /dev/null +++ b/src/main/java/carpet/script/argument/Vector3Argument.java @@ -0,0 +1,93 @@ +package carpet.script.argument; + +import carpet.script.CarpetContext; +import carpet.script.LazyValue; +import carpet.script.exception.InternalExpressionException; +import carpet.script.value.BlockValue; +import carpet.script.value.ListValue; +import carpet.script.value.NumericValue; +import carpet.script.value.Value; +import net.minecraft.util.math.Vec3d; + +import java.util.List; + +public class Vector3Argument extends Argument +{ + public Vec3d vec; + public final double yaw; + public final double pitch; + public boolean fromBlock; + private Vector3Argument(Vec3d v, int o) + { + super(o); + this.vec = v; + this.yaw = 0.0D; + this.pitch = 0.0D; + } + private Vector3Argument(Vec3d v, int o, double y, double p) + { + super(o); + this.vec = v; + this.yaw = y; + this.pitch = p; + } + + private Vector3Argument fromBlock() + { + fromBlock = true; + return this; + } + + + public static Vector3Argument findIn(CarpetContext c, List params, int offset) + { + return findIn(c,params, offset, false); + } + + public static Vector3Argument findIn(CarpetContext c, List params, int offset, boolean optionalDirection) + { + try + { + Value v1 = params.get(0 + offset).evalValue(c); + if (v1 instanceof BlockValue) + { + return (new Vector3Argument(new Vec3d(((BlockValue) v1).getPos()).add(0.5,0.5,0.5), 1+offset)).fromBlock(); + } + if (v1 instanceof ListValue) + { + List args = ((ListValue) v1).getItems(); + Vec3d pos = new Vec3d( + NumericValue.asNumber(args.get(0)).getDouble(), + NumericValue.asNumber(args.get(1)).getDouble(), + NumericValue.asNumber(args.get(2)).getDouble()); + double yaw = 0.0D; + double pitch = 0.0D; + if (args.size()>3 && optionalDirection) + { + yaw = NumericValue.asNumber(args.get(3)).getDouble(); + pitch = NumericValue.asNumber(args.get(4)).getDouble(); + } + return new Vector3Argument(pos,offset+1, yaw, pitch); + } + Vec3d pos = new Vec3d( + NumericValue.asNumber(v1).getDouble(), + NumericValue.asNumber(params.get(1 + offset).evalValue(c)).getDouble(), + NumericValue.asNumber(params.get(2 + offset).evalValue(c)).getDouble()); + double yaw = 0.0D; + double pitch = 0.0D; + int eatenLength = 3; + if (params.size()>3+offset && optionalDirection) + { + yaw = NumericValue.asNumber(params.get(3 + offset).evalValue(c)).getDouble(); + pitch = NumericValue.asNumber(params.get(4 + offset).evalValue(c)).getDouble(); + eatenLength = 5; + } + + return new Vector3Argument(pos,offset+eatenLength, yaw, pitch); + } + catch (IndexOutOfBoundsException e) + { + throw new InternalExpressionException("Position should be defined either by three coordinates, or a block value"); + } + } +} diff --git a/src/main/java/carpet/script/utils/ArgParser.java b/src/main/java/carpet/script/utils/ArgParser.java deleted file mode 100644 index 1d9ee519..00000000 --- a/src/main/java/carpet/script/utils/ArgParser.java +++ /dev/null @@ -1,17 +0,0 @@ -package carpet.script.utils; - -import carpet.script.value.FunctionValue; - -public class ArgParser -{ - public static class FunctionArgument - { - public final FunctionValue function; - public final int offset; - FunctionArgument(FunctionValue f, int o) - { - function = f; - offset = o; - } - } -} diff --git a/src/main/java/carpet/script/utils/CarpetArgParser.java b/src/main/java/carpet/script/utils/CarpetArgParser.java index eeafe256..7fff1c5b 100644 --- a/src/main/java/carpet/script/utils/CarpetArgParser.java +++ b/src/main/java/carpet/script/utils/CarpetArgParser.java @@ -1,215 +1,6 @@ package carpet.script.utils; -import carpet.script.CarpetContext; -import carpet.script.LazyValue; -import carpet.script.exception.InternalExpressionException; -import carpet.script.value.*; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3d; - -import java.util.List; public class CarpetArgParser { - public static Vector3Argument locateVector(CarpetContext c, List params, int offset) - { - return locateVector(c,params, offset, false); - } - - public static Vector3Argument locateVector(CarpetContext c, List params, int offset, boolean optionalDirection) - { - try - { - Value v1 = params.get(0 + offset).evalValue(c); - if (v1 instanceof BlockValue) - { - return (new Vector3Argument(new Vec3d(((BlockValue) v1).getPos()).add(0.5,0.5,0.5), 1+offset)).fromBlock(); - } - if (v1 instanceof ListValue) - { - List args = ((ListValue) v1).getItems(); - Vec3d pos = new Vec3d( - NumericValue.asNumber(args.get(0)).getDouble(), - NumericValue.asNumber(args.get(1)).getDouble(), - NumericValue.asNumber(args.get(2)).getDouble()); - double yaw = 0.0D; - double pitch = 0.0D; - if (args.size()>3 && optionalDirection) - { - yaw = NumericValue.asNumber(args.get(3)).getDouble(); - pitch = NumericValue.asNumber(args.get(4)).getDouble(); - } - return new Vector3Argument(pos,offset+1, yaw, pitch); - } - Vec3d pos = new Vec3d( - NumericValue.asNumber(v1).getDouble(), - NumericValue.asNumber(params.get(1 + offset).evalValue(c)).getDouble(), - NumericValue.asNumber(params.get(2 + offset).evalValue(c)).getDouble()); - double yaw = 0.0D; - double pitch = 0.0D; - int eatenLength = 3; - if (params.size()>3+offset && optionalDirection) - { - yaw = NumericValue.asNumber(params.get(3 + offset).evalValue(c)).getDouble(); - pitch = NumericValue.asNumber(params.get(4 + offset).evalValue(c)).getDouble(); - eatenLength = 5; - } - - return new Vector3Argument(pos,offset+eatenLength, yaw, pitch); - } - catch (IndexOutOfBoundsException e) - { - throw new InternalExpressionException("Position should be defined either by three coordinates, or a block value"); - } - } - - public static BlockArgument locateBlock(CarpetContext c, List params, int offset) - { - return locateBlock(c, params,offset, false, false); - } - - public static BlockArgument locateBlock(CarpetContext c, List params, int offset, boolean acceptString) - { - return locateBlock(c, params,offset, acceptString, false); - } - - public static BlockArgument locateBlock(CarpetContext c, List params, int offset, boolean acceptString, boolean optional) - { - try - { - Value v1 = params.get(0 + offset).evalValue(c); - //add conditional from string name - if (optional && v1 instanceof NullValue) - { - return new BlockArgument(null, 1+offset); - } - if (acceptString && v1 instanceof StringValue) - { - return new BlockArgument(BlockValue.fromString(v1.getString()), 1+offset); - } - if (v1 instanceof BlockValue) - { - return new BlockArgument(((BlockValue) v1), 1+offset); - } - if (v1 instanceof ListValue) - { - List args = ((ListValue) v1).getItems(); - int xpos = (int) NumericValue.asNumber(args.get(0)).getLong(); - int ypos = (int) NumericValue.asNumber(args.get(1)).getLong(); - int zpos = (int) NumericValue.asNumber(args.get(2)).getLong(); - return new BlockArgument( - new BlockValue( - null, - c.s.getWorld(), - new BlockPos(c.origin.getX() + xpos, c.origin.getY() + ypos, c.origin.getZ() + zpos) - ), - 1+offset); - } - int xpos = (int) NumericValue.asNumber(v1).getLong(); - int ypos = (int) NumericValue.asNumber( params.get(1 + offset).evalValue(c)).getLong(); - int zpos = (int) NumericValue.asNumber( params.get(2 + offset).evalValue(c)).getLong(); - return new BlockArgument( - new BlockValue( - null, - c.s.getWorld(), - new BlockPos(c.origin.getX() + xpos, c.origin.getY() + ypos, c.origin.getZ() + zpos) - ), - 3+offset - ); - } - catch (IndexOutOfBoundsException e) - { - throw new InternalExpressionException("Block should be defined either by three coordinates, a block value, or a proper string"); - } - } - - public static BlockArgument fromParamValues(CarpetContext c, List params, int offset, boolean acceptString, boolean optional) - { - try - { - Value v1 = params.get(0 + offset); - //add conditional from string name - if (optional && v1 instanceof NullValue) - { - return new BlockArgument(null, 1+offset); - } - if (acceptString && v1 instanceof StringValue) - { - return new BlockArgument(BlockValue.fromString(v1.getString()), 1+offset); - } - if (v1 instanceof BlockValue) - { - return new BlockArgument(((BlockValue) v1), 1+offset); - } - if (v1 instanceof ListValue) - { - List args = ((ListValue) v1).getItems(); - int xpos = (int) NumericValue.asNumber(args.get(0)).getLong(); - int ypos = (int) NumericValue.asNumber(args.get(1)).getLong(); - int zpos = (int) NumericValue.asNumber(args.get(2)).getLong(); - return new BlockArgument( - new BlockValue( - null, - c.s.getWorld(), - new BlockPos(c.origin.getX() + xpos, c.origin.getY() + ypos, c.origin.getZ() + zpos) - ), - 1+offset); - } - int xpos = (int) NumericValue.asNumber(v1).getLong(); - int ypos = (int) NumericValue.asNumber( params.get(1 + offset)).getLong(); - int zpos = (int) NumericValue.asNumber( params.get(2 + offset)).getLong(); - return new BlockArgument( - new BlockValue( - null, - c.s.getWorld(), - new BlockPos(c.origin.getX() + xpos, c.origin.getY() + ypos, c.origin.getZ() + zpos) - ), - 3+offset - ); - } - catch (IndexOutOfBoundsException e) - { - throw new InternalExpressionException("Block should be defined either by three coordinates, a block value, or a proper string"); - } - } - - public static class BlockArgument - { - public final BlockValue block; - public final int offset; - BlockArgument(BlockValue b, int o) - { - block = b; - offset = o; - } - } - - public static class Vector3Argument - { - public Vec3d vec; - public final int offset; - public final double yaw; - public final double pitch; - public boolean fromBlock; - Vector3Argument(Vec3d v, int o) - { - vec = v; - offset = o; - yaw = 0.0D; - pitch = 0.0D; - } - Vector3Argument(Vec3d v, int o, double y, double p) - { - vec = v; - offset = o; - yaw = y; - pitch = p; - } - - public Vector3Argument fromBlock() - { - fromBlock = true; - return this; - } - } } From 56749f731afc9e8d61c7cd707d630c35ebc4d0ef Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 16 Apr 2020 22:33:53 -0300 Subject: [PATCH 023/198] refactored `scan` to also take pos arguments. --- docs/scarpet/api/BlockIterations.md | 12 ++-- .../java/carpet/script/CarpetExpression.java | 68 +++++++++++++------ .../carpet/script/argument/BlockArgument.java | 15 +++- .../script/argument/Vector3Argument.java | 2 +- .../carpet/script/utils/CarpetArgParser.java | 6 -- 5 files changed, 70 insertions(+), 33 deletions(-) delete mode 100644 src/main/java/carpet/script/utils/CarpetArgParser.java diff --git a/docs/scarpet/api/BlockIterations.md b/docs/scarpet/api/BlockIterations.md index 4f2085ff..6aebfbc8 100644 --- a/docs/scarpet/api/BlockIterations.md +++ b/docs/scarpet/api/BlockIterations.md @@ -2,11 +2,15 @@ These functions help scan larger areas of blocks without using generic loop functions, like nested `loop`. -### `scan(cx, cy, cz, dx, dy, dz, px?, py?, pz?, expr)` +### `scan(cx, cy, cz, dx, dy, dz, px?, py?, pz?, expr)`, `scan(center, range, lower_range?, expr)` -Evaluates expression over area of blocks defined by its center (`cx, cy, cz`), expanded in all directions -by `dx, dy, dz` blocks, or optionally in negative with `d` coords, and `p` coords in positive values. `expr` -receives `_x, _y, _z` as coords of current analyzed block and `_`, which represents the block itself. +Evaluates expression over area of blocks defined by its center `center = (cx, cy, cz)`, expanded in all directions +by `range = (dx, dy, dz)` blocks, or optionally in negative with `range` coords, and `upper_range` coords in +positive values. +`center` can be defined either as a three coordinates, list of three coords, or block value. +`range` and `lower_range` can have the same representations, just if its a block, it computes the distance to the center +as range instead of taking the values as is. +`expr` receives `_x, _y, _z` as coords of current analyzed block and `_`, which represents the block itself. Returns number of successful evaluations of `expr` (with `true` boolean result) unless called in void context, which would cause the expression not be evaluated for their boolean value. diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index c75a156b..5692dbe7 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -21,7 +21,6 @@ import carpet.script.exception.ContinueStatement; import carpet.script.exception.ExitStatement; import carpet.script.exception.ExpressionException; import carpet.script.exception.InternalExpressionException; -import carpet.script.utils.CarpetArgParser; import carpet.script.value.BlockValue; import carpet.script.value.EntityValue; import carpet.script.value.FunctionValue; @@ -109,6 +108,7 @@ import net.minecraft.util.math.Direction; import net.minecraft.util.math.EulerAngle; import net.minecraft.util.math.BlockBox; import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.Vec3i; import net.minecraft.util.registry.Registry; import net.minecraft.world.poi.PointOfInterest; import net.minecraft.world.poi.PointOfInterestStorage; @@ -1947,30 +1947,58 @@ public class CarpetExpression { this.expr.addLazyFunction("scan", -1, (c, t, lv) -> { - int lvsise = lv.size(); - if (lvsise != 7 && lvsise != 10) - throw new InternalExpressionException("'scan' takes 2, or 3 triples of coords, and the expression"); - int cx = (int) NumericValue.asNumber(lv.get(0).evalValue(c)).getLong(); - int cy = (int) NumericValue.asNumber(lv.get(1).evalValue(c)).getLong(); - int cz = (int) NumericValue.asNumber(lv.get(2).evalValue(c)).getLong(); - int xrange = (int) NumericValue.asNumber(lv.get(3).evalValue(c)).getLong(); - int yrange = (int) NumericValue.asNumber(lv.get(4).evalValue(c)).getLong(); - int zrange = (int) NumericValue.asNumber(lv.get(5).evalValue(c)).getLong(); - int xprange = xrange; - int yprange = yrange; - int zprange = zrange; - LazyValue expr; - if (lvsise == 7) + CarpetContext cc = (CarpetContext)c; + BlockArgument centerLocator = BlockArgument.findIn(cc, lv, 0); + Vector3Argument rangeLocator = Vector3Argument.findIn(cc, lv, centerLocator.offset); + BlockPos center = centerLocator.block.getPos(); + Vec3i range; + + if (rangeLocator.fromBlock) { - expr = lv.get(6); + range = new Vec3i( + abs(rangeLocator.vec.x - center.getX()), + abs(rangeLocator.vec.y - center.getY()), + abs(rangeLocator.vec.z - center.getZ()) + ); + //if (lv.size() > rangeLocator.offset+1) throw new InternalExpressionException("'scan' takes two block positions, and the expression") } else { - xprange = (int) NumericValue.asNumber(lv.get(6).evalValue(c)).getLong(); - yprange = (int) NumericValue.asNumber(lv.get(7).evalValue(c)).getLong(); - zprange = (int) NumericValue.asNumber(lv.get(8).evalValue(c)).getLong(); - expr = lv.get(9); + range = new Vec3i(abs(rangeLocator.vec.x), abs(rangeLocator.vec.y), abs(rangeLocator.vec.z)); } + Vec3i upperRange = range; + if (lv.size() > rangeLocator.offset+1) // +1 cause we still need the expression + { + rangeLocator = Vector3Argument.findIn(cc, lv, rangeLocator.offset); + if (rangeLocator.fromBlock) + { + upperRange = new Vec3i( + abs(rangeLocator.vec.x - center.getX()), + abs(rangeLocator.vec.y - center.getY()), + abs(rangeLocator.vec.z - center.getZ()) + ); + //if (lv.size() > rangeLocator.offset+1) throw new InternalExpressionException("'scan' takes two block positions, and the expression") + } + else + { + upperRange = new Vec3i(abs(rangeLocator.vec.x), abs(rangeLocator.vec.y), abs(rangeLocator.vec.z)); + } + } + if (lv.size() != rangeLocator.offset+1) + { + throw new InternalExpressionException("'scan' takes two, or three block positions, and an expression: "+lv.size()+" "+rangeLocator.offset); + } + LazyValue expr = lv.get(rangeLocator.offset); + + int cx = center.getX(); + int cy = center.getY(); + int cz = center.getZ(); + int xrange = range.getX(); + int yrange = range.getY(); + int zrange = range.getZ(); + int xprange = upperRange.getX(); + int yprange = upperRange.getY(); + int zprange = upperRange.getZ(); //saving outer scope LazyValue _x = c.getVariable("_x"); diff --git a/src/main/java/carpet/script/argument/BlockArgument.java b/src/main/java/carpet/script/argument/BlockArgument.java index 0e492f64..59c0d96c 100644 --- a/src/main/java/carpet/script/argument/BlockArgument.java +++ b/src/main/java/carpet/script/argument/BlockArgument.java @@ -77,7 +77,7 @@ public class BlockArgument extends Argument } catch (IndexOutOfBoundsException e) { - throw new InternalExpressionException("Block should be defined either by three coordinates, a block value, or a proper string"); + throw handleError(optional, acceptString); } } @@ -127,7 +127,18 @@ public class BlockArgument extends Argument } catch (IndexOutOfBoundsException e) { - throw new InternalExpressionException("Block should be defined either by three coordinates, a block value, or a proper string"); + throw handleError(optional, acceptString); } } + + private static InternalExpressionException handleError(boolean optional, boolean acceptString) + { + String message = "Block-type argument should be defined either by three coordinates (a triple or by three arguments), or a block value"; + if (acceptString) + message+=", or a string with block description"; + if (optional) + message+=", or null"; + return new InternalExpressionException(message); + } + } diff --git a/src/main/java/carpet/script/argument/Vector3Argument.java b/src/main/java/carpet/script/argument/Vector3Argument.java index beb2a827..54dc21c6 100644 --- a/src/main/java/carpet/script/argument/Vector3Argument.java +++ b/src/main/java/carpet/script/argument/Vector3Argument.java @@ -87,7 +87,7 @@ public class Vector3Argument extends Argument } catch (IndexOutOfBoundsException e) { - throw new InternalExpressionException("Position should be defined either by three coordinates, or a block value"); + throw new InternalExpressionException("Position argument should be defined either by three coordinates (a triple or by three arguments), or a positioned block value"); } } } diff --git a/src/main/java/carpet/script/utils/CarpetArgParser.java b/src/main/java/carpet/script/utils/CarpetArgParser.java deleted file mode 100644 index 7fff1c5b..00000000 --- a/src/main/java/carpet/script/utils/CarpetArgParser.java +++ /dev/null @@ -1,6 +0,0 @@ -package carpet.script.utils; - - -public class CarpetArgParser -{ -} From 67e3ed3229b2fab7047e588b776dd73e5bc81e21 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Sat, 18 Apr 2020 13:49:07 +0200 Subject: [PATCH 024/198] Added draw command --- .../java/carpet/commands/DrawCommand.java | 90 ++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index 41fbcda6..c1d3c510 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -21,6 +21,7 @@ import net.minecraft.server.world.ServerWorld; import java.util.List; import java.util.function.Predicate; +import java.lang.Math.abs; import static net.minecraft.server.command.CommandManager.argument; import static net.minecraft.server.command.CommandManager.literal; @@ -52,7 +53,35 @@ public class DrawCommand BlockStateArgumentType.getBlockState(c,"block"), BlockPredicateArgumentType.getBlockPredicate(c, "filter") - )))))))); + )))))))). + then(literal("diamond"). + then(argument("centre",BlockPosArgumentType.blockPos()). + then(argument("radius",IntegerArgumentType.integer(1)). + then(argument("block",BlockStateArgumentType.blockState()). + executes((c)->drawDiamond( + c.getSource(), + BlockPosArgumentType.getBlockPos(c,"centre"), + IntegerArgumentType.getInteger(c,"radius"), + BlockStateArgumentType.getBlockState(c,"block"), + null + ). + then(literal("replace"). + then(argument("filter",BlockPredicateArgumentType.blockPredicate()). + executes((c)->drawDiamond( + c.getSource(), + BlockPosArgumentType.getBlockPos(c, "centre"), + IntegerArgumentType.getInteger(c, "radius"), + BlockStateArgumentType.getBlockState(c,"block"), + BlockPredicateArgumentType.getBlockPredicate(c,"filter") + ) + ) + ) + ) + ) + ) + ) + ) + ); dispatcher.register(command); } @@ -161,4 +190,63 @@ public class DrawCommand { return (x * x) + (y * y) + (z * z); } + + private static int manhattan(int x1, int y1, int z1, int x2, int y2, int z2){ + return abs(x1-x2)+abs(y1-y2)+abs(z1-z2) + } + + private static int drawDiamond(ServerCommandSource source, BlockPos pos, int radius, BlockStateArgument block, + Predicate replacement){ + int affected =0; + + BlockPos.Mutable mbpos = new BlockPos.Mutable(pos); + + List list = Lists.newArrayList(); + + ServerWorld world=source.getWorld(); + + CarpetSettings.impendingFillSkipUpdates = !CarpetSettings.fillUpdates; + + for(int x=-radius; x<=radius;++x){ + + for(int y=-radius; y<=radius; ++y){ + + for(int z=-radius; z<=radius; ++z){ + + if(manhattan(0,0,0,x,y,z)!=radius){continue}; + + mbpos.set(pos.getX()+x, pos.getY()+y, pos.getZ()+z); + + if (replacement == null || replacement.test(new CachedBlockPosition( world, mbpos, true))){ + BlockEntity tileentity = world.getBlockEntity(mbpos); + + if (tileentity instanceof Inventory){ + ((Inventory)tileentity).clear(); + } + + if (block.setBlockState(world, mbpos,2)){ + list.add(mbpos.toImmutable()); + ++affected; + } + } + } + } + } + + CarpetSettings.impendingFillSkipUpdates = false; + + if (CarpetSettings.fillUpdates) + { + + for (BlockPos blockpos1 : list) + { + Block blokc = world.getBlockState(blockpos1).getBlock(); + world.updateNeighbors(blockpos1, blokc); + } + } + + Messenger.m(source, "gi Filled "+affected+" blocks"); + + return 1; + } } From dab41bb0cef214624ff0f54891dd64f40c17e741 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Sat, 18 Apr 2020 14:07:24 +0200 Subject: [PATCH 025/198] FIxed some stuff Still borken asf, but im not sure how to fix --- .../java/carpet/commands/DrawCommand.java | 181 ++++++++---------- 1 file changed, 75 insertions(+), 106 deletions(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index c1d3c510..f576967e 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -21,79 +21,55 @@ import net.minecraft.server.world.ServerWorld; import java.util.List; import java.util.function.Predicate; -import java.lang.Math.abs; +import java.lang.Math; import static net.minecraft.server.command.CommandManager.argument; import static net.minecraft.server.command.CommandManager.literal; -public class DrawCommand -{ - public static void register(CommandDispatcher dispatcher) - { - LiteralArgumentBuilder command = literal("draw"). - requires((player) -> SettingsManager.canUseCommand(player, CarpetSettings.commandDraw)). - then(literal("sphere"). - then(argument("center",BlockPosArgumentType.blockPos()). - then(argument("radius",IntegerArgumentType.integer(1)). - then(argument("block",BlockStateArgumentType.blockState()). - executes((c)-> drawCircle( - c.getSource(), - BlockPosArgumentType.getBlockPos(c, "center"), - IntegerArgumentType.getInteger(c, "radius"), - BlockStateArgumentType.getBlockState (c,"block"), - null - ) - ). - then(literal("replace"). - then(argument("filter",BlockPredicateArgumentType.blockPredicate()) - .executes((c)-> drawCircle( - c.getSource(), - BlockPosArgumentType.getBlockPos(c, "center"), +public class DrawCommand { + public static void register(CommandDispatcher dispatcher) { + LiteralArgumentBuilder command = literal("draw") + .requires((player) -> SettingsManager.canUseCommand(player, CarpetSettings.commandDraw)) + .then(literal("sphere").then(argument("center", BlockPosArgumentType.blockPos()) + .then(argument("radius", IntegerArgumentType.integer(1)) + .then(argument("block", BlockStateArgumentType.blockState()) + .executes((c) -> drawCircle(c.getSource(), + BlockPosArgumentType.getBlockPos(c, "center"), + IntegerArgumentType.getInteger(c, "radius"), + BlockStateArgumentType.getBlockState(c, "block"), null)) + .then(literal("replace") + .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) + .executes((c) -> drawCircle(c.getSource(), + BlockPosArgumentType.getBlockPos(c, "center"), + IntegerArgumentType.getInteger(c, "radius"), + BlockStateArgumentType.getBlockState(c, "block"), + BlockPredicateArgumentType.getBlockPredicate(c, + "filter"))))))))) + .then(literal("diamond").then(argument("centre", BlockPosArgumentType.blockPos()) + .then(argument("radius", IntegerArgumentType.integer(1)).then( + argument("block", BlockStateArgumentType.blockState()).executes((c) -> drawDiamond( + c.getSource(), BlockPosArgumentType.getBlockPos(c, "centre"), + IntegerArgumentType.getInteger(c, "radius"), + BlockStateArgumentType.getBlockState(c, "block"), null) + .then(literal("replace").then( + argument("filter", BlockPredicateArgumentType.blockPredicate()) + .executes((c) -> drawDiamond(c.getSource(), + BlockPosArgumentType.getBlockPos(c, "centre"), IntegerArgumentType.getInteger(c, "radius"), - BlockStateArgumentType.getBlockState(c,"block"), + BlockStateArgumentType.getBlockState(c, + "block"), BlockPredicateArgumentType.getBlockPredicate(c, - "filter") - )))))))). - then(literal("diamond"). - then(argument("centre",BlockPosArgumentType.blockPos()). - then(argument("radius",IntegerArgumentType.integer(1)). - then(argument("block",BlockStateArgumentType.blockState()). - executes((c)->drawDiamond( - c.getSource(), - BlockPosArgumentType.getBlockPos(c,"centre"), - IntegerArgumentType.getInteger(c,"radius"), - BlockStateArgumentType.getBlockState(c,"block"), - null - ). - then(literal("replace"). - then(argument("filter",BlockPredicateArgumentType.blockPredicate()). - executes((c)->drawDiamond( - c.getSource(), - BlockPosArgumentType.getBlockPos(c, "centre"), - IntegerArgumentType.getInteger(c, "radius"), - BlockStateArgumentType.getBlockState(c,"block"), - BlockPredicateArgumentType.getBlockPredicate(c,"filter") - ) - ) - ) - ) - ) - ) - ) - ) - ); + "filter")))))))))); dispatcher.register(command); } - private static int drawCircle(ServerCommandSource source, BlockPos pos, int radius, BlockStateArgument block, - Predicate replacement) - { - return drawCircle(source, pos, (double)radius, (double)radius, (double)radius, block, replacement, false); + Predicate replacement) { + return drawCircle(source, pos, (double) radius, (double) radius, (double) radius, block, replacement, false); } - private static int drawCircle(ServerCommandSource source, BlockPos pos, double radiusX, double radiusY, double radiusZ, - BlockStateArgument block, Predicate replacement, boolean solid) - { + + private static int drawCircle(ServerCommandSource source, BlockPos pos, double radiusX, double radiusY, + double radiusZ, BlockStateArgument block, Predicate replacement, boolean solid) { int affected = 0; ServerWorld world = source.getWorld(); @@ -138,30 +114,25 @@ public class DrawCommand } if (!solid) { - if (lengthSq(nextXn, yn, zn) <= 1 && lengthSq(xn, nextYn, zn) <= 1 && lengthSq(xn, yn, nextZn) <= 1) { + if (lengthSq(nextXn, yn, zn) <= 1 && lengthSq(xn, nextYn, zn) <= 1 + && lengthSq(xn, yn, nextZn) <= 1) { continue; } } CarpetSettings.impendingFillSkipUpdates = !CarpetSettings.fillUpdates; - for (int xmod = -1; xmod < 2; xmod+= 2) - { - for (int ymod = -1; ymod < 2; ymod += 2) - { - for (int zmod = -1; zmod < 2; zmod += 2) - { - mbpos.set(pos.getX()+xmod*x, pos.getY()+ymod*y, pos.getZ()+zmod*z); - if (replacement == null || replacement.test( - new CachedBlockPosition( world, mbpos, true))) - { + for (int xmod = -1; xmod < 2; xmod += 2) { + for (int ymod = -1; ymod < 2; ymod += 2) { + for (int zmod = -1; zmod < 2; zmod += 2) { + mbpos.set(pos.getX() + xmod * x, pos.getY() + ymod * y, pos.getZ() + zmod * z); + if (replacement == null + || replacement.test(new CachedBlockPosition(world, mbpos, true))) { BlockEntity tileentity = world.getBlockEntity(mbpos); - if (tileentity instanceof Inventory) - { - ((Inventory)tileentity).clear(); + if (tileentity instanceof Inventory) { + ((Inventory) tileentity).clear(); } - if (block.setBlockState(world, mbpos,2)) - { + if (block.setBlockState(world, mbpos, 2)) { list.add(mbpos.toImmutable()); ++affected; } @@ -173,58 +144,58 @@ public class DrawCommand } } } - if (CarpetSettings.fillUpdates) - { + if (CarpetSettings.fillUpdates) { - for (BlockPos blockpos1 : list) - { + for (BlockPos blockpos1 : list) { Block blokc = world.getBlockState(blockpos1).getBlock(); world.updateNeighbors(blockpos1, blokc); // or always version???? } } - Messenger.m(source, "gi Filled "+affected+" blocks"); + Messenger.m(source, "gi Filled " + affected + " blocks"); return 1; } - private static double lengthSq(double x, double y, double z) - { + + private static double lengthSq(double x, double y, double z) { return (x * x) + (y * y) + (z * z); } - private static int manhattan(int x1, int y1, int z1, int x2, int y2, int z2){ - return abs(x1-x2)+abs(y1-y2)+abs(z1-z2) + private static int manhattan(int x1, int y1, int z1, int x2, int y2, int z2) { + return Math.abs(x1 - x2) + Math.abs(y1 - y2) + Math.abs(z1 - z2); } - private static int drawDiamond(ServerCommandSource source, BlockPos pos, int radius, BlockStateArgument block, - Predicate replacement){ - int affected =0; + private static int drawDiamond(ServerCommandSource source, BlockPos pos, int radius, BlockStateArgument block, + Predicate replacement) { + int affected = 0; BlockPos.Mutable mbpos = new BlockPos.Mutable(pos); List list = Lists.newArrayList(); - ServerWorld world=source.getWorld(); + ServerWorld world = source.getWorld(); CarpetSettings.impendingFillSkipUpdates = !CarpetSettings.fillUpdates; - for(int x=-radius; x<=radius;++x){ + for (int x = -radius; x <= radius; ++x) { - for(int y=-radius; y<=radius; ++y){ + for (int y = -radius; y <= radius; ++y) { - for(int z=-radius; z<=radius; ++z){ + for (int z = -radius; z <= radius; ++z) { - if(manhattan(0,0,0,x,y,z)!=radius){continue}; + if (manhattan(0, 0, 0, x, y, z) != radius) { + continue; + } - mbpos.set(pos.getX()+x, pos.getY()+y, pos.getZ()+z); + mbpos.set(pos.getX() + x, pos.getY() + y, pos.getZ() + z); - if (replacement == null || replacement.test(new CachedBlockPosition( world, mbpos, true))){ + if (replacement == null || replacement.test(new CachedBlockPosition(world, mbpos, true))) { BlockEntity tileentity = world.getBlockEntity(mbpos); - if (tileentity instanceof Inventory){ - ((Inventory)tileentity).clear(); + if (tileentity instanceof Inventory) { + ((Inventory) tileentity).clear(); } - - if (block.setBlockState(world, mbpos,2)){ + + if (block.setBlockState(world, mbpos, 2)) { list.add(mbpos.toImmutable()); ++affected; } @@ -235,17 +206,15 @@ public class DrawCommand CarpetSettings.impendingFillSkipUpdates = false; - if (CarpetSettings.fillUpdates) - { + if (CarpetSettings.fillUpdates) { - for (BlockPos blockpos1 : list) - { + for (BlockPos blockpos1 : list) { Block blokc = world.getBlockState(blockpos1).getBlock(); world.updateNeighbors(blockpos1, blokc); } } - Messenger.m(source, "gi Filled "+affected+" blocks"); + Messenger.m(source, "gi Filled " + affected + " blocks"); return 1; } From 08e42523ba6ad46f9c58c4407fccd88d82d78b22 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Sat, 18 Apr 2020 14:12:26 +0200 Subject: [PATCH 026/198] I thinks this helped? --- src/main/java/carpet/commands/DrawCommand.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index f576967e..6d726477 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -165,7 +165,13 @@ public class DrawCommand { } private static int drawDiamond(ServerCommandSource source, BlockPos pos, int radius, BlockStateArgument block, - Predicate replacement) { + Predicate replacement) { + return (int) drawDiamond(source, pos, radius, block, replacement, false); + } + + private static double drawDiamond(ServerCommandSource source, BlockPos pos, int radius, + BlockStateArgument block, + Predicate replacement, boolean solid) { int affected = 0; BlockPos.Mutable mbpos = new BlockPos.Mutable(pos); From fe9ad4b29789d094cb691292b9022a6a4cd2d1af Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Sat, 18 Apr 2020 18:31:18 +0200 Subject: [PATCH 027/198] I hope this works I copy pasted above code and edited a bit to see if it works (Btw, that is basically how I did #224) --- .../java/carpet/commands/DrawCommand.java | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index 6d726477..d1a561e8 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -45,21 +45,28 @@ public class DrawCommand { BlockStateArgumentType.getBlockState(c, "block"), BlockPredicateArgumentType.getBlockPredicate(c, "filter"))))))))) - .then(literal("diamond").then(argument("centre", BlockPosArgumentType.blockPos()) - .then(argument("radius", IntegerArgumentType.integer(1)).then( - argument("block", BlockStateArgumentType.blockState()).executes((c) -> drawDiamond( - c.getSource(), BlockPosArgumentType.getBlockPos(c, "centre"), - IntegerArgumentType.getInteger(c, "radius"), - BlockStateArgumentType.getBlockState(c, "block"), null) - .then(literal("replace").then( - argument("filter", BlockPredicateArgumentType.blockPredicate()) - .executes((c) -> drawDiamond(c.getSource(), - BlockPosArgumentType.getBlockPos(c, "centre"), - IntegerArgumentType.getInteger(c, "radius"), - BlockStateArgumentType.getBlockState(c, - "block"), - BlockPredicateArgumentType.getBlockPredicate(c, - "filter")))))))))); + .then(literal("diamond").then(argument("center", BlockPosArgumentType.blockPos()) + .then(argument("radius", IntegerArgumentType.integer(1)) + .then(argument("block", BlockStateArgumentType.blockState()) + .executes((c) -> drawDiamond(c.getSource(), + BlockPosArgumentType.getBlockPos(c, "center"), + IntegerArgumentType.getInteger(c, "radius"), + BlockStateArgumentType.getBlockState(c, "block"), null)) + .then(literal("replace") + .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) + .executes((c) -> drawDiamond(c.getSource(), + BlockPosArgumentType.getBlockPos(c, "center"), + IntegerArgumentType.getInteger(c, "radius"), + BlockStateArgumentType.getBlockState(c, "block"), + BlockPredicateArgumentType.getBlockPredicate(c,"filter") + ) + ) + ) + ) + ) + ) + ) + ); dispatcher.register(command); } @@ -169,8 +176,7 @@ public class DrawCommand { return (int) drawDiamond(source, pos, radius, block, replacement, false); } - private static double drawDiamond(ServerCommandSource source, BlockPos pos, int radius, - BlockStateArgument block, + private static int drawDiamond(ServerCommandSource source, BlockPos pos, int radius,BlockStateArgument block, Predicate replacement, boolean solid) { int affected = 0; From 11f1ce61b795fc8aba45d12a533ef6808541de9f Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Sat, 18 Apr 2020 22:23:34 +0200 Subject: [PATCH 028/198] Added cone y not --- .../java/carpet/commands/DrawCommand.java | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index d1a561e8..6fba527e 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -6,6 +6,7 @@ import carpet.utils.Messenger; import com.google.common.collect.Lists; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.arguments.BoolArgumentType; import com.mojang.brigadier.arguments.IntegerArgumentType; import net.minecraft.block.Block; import net.minecraft.block.pattern.CachedBlockPosition; @@ -66,6 +67,38 @@ public class DrawCommand { ) ) ) + ) + .then(literal("cone") + .then(argument("center", BlockPosArgumentType.blockPos()) + .then(argument("radius", IntegerArgumentType.integer(1)) + .then(argument("height",IntegerArgumentType.integer(1)) + .then(argument("pointing up?",BoolArgumentType.bool()) + .then(argument("block", BlockStateArgumentType.blockState()) + .executes((c) -> drawCone(c.getSource(), + BlockPosArgumentType.getBlockPos(c, "center"), + IntegerArgumentType.getInteger(c, "radius"), + IntegerArgumentType.getInteger(c, "height"), + BoolArgumentType.getBool(c, "pointing up?"), + BlockStateArgumentType.getBlockState(c, "block"), null) + ) + .then(literal("replace") + .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) + .executes((c) -> drawCone(c.getSource(), + BlockPosArgumentType.getBlockPos(c, "center"), + IntegerArgumentType.getInteger(c, "radius"), + IntegerArgumentType.getInteger(c, "height"), + BoolArgumentType.getBool(c, "pointing up?"), + BlockStateArgumentType.getBlockState(c, "block"), + BlockPredicateArgumentType.getBlockPredicate(c,"filter") + ) + ) + ) + ) + ) + ) + ) + ) + ) ); dispatcher.register(command); } @@ -230,4 +263,67 @@ public class DrawCommand { return 1; } + + private static int drawCone(ServerCommandSource source, BlockPos pos, int radius, int height, boolean pointup, BlockStateArgument block, + Predicate replacement) { + return (int) drawCone(source, pos, radius, height, block, replacement, pointup, false); + } + + private static int drawCone(ServerCommandSource source, BlockPos pos, int radius, int height,BlockStateArgument block, + Predicate replacement, boolean pointup, boolean solid) { + int affected = 0; + int offset = 0; + if(pointup){ + offset=height; + } + BlockPos.Mutable mbpos = new BlockPos.Mutable(pos); + + List list = Lists.newArrayList(); + + ServerWorld world = source.getWorld(); + + CarpetSettings.impendingFillSkipUpdates = !CarpetSettings.fillUpdates; + + for (int x = -radius; x <= radius; ++x) { + + for (int y = -offset; y <= height+1-offset; ++y) { + + for (int z = -radius; z <= radius; ++z) { + + if (x*x+z*z>(radius/height*y)*(radius/height*y)) { + continue; + } + + mbpos.set(pos.getX() + x, pos.getY() + y + offset, pos.getZ() + z); + + if (replacement == null || replacement.test(new CachedBlockPosition(world, mbpos, true))) { + BlockEntity tileentity = world.getBlockEntity(mbpos); + + if (tileentity instanceof Inventory) { + ((Inventory) tileentity).clear(); + } + + if (block.setBlockState(world, mbpos, 2)) { + list.add(mbpos.toImmutable()); + ++affected; + } + } + } + } + } + + CarpetSettings.impendingFillSkipUpdates = false; + + if (CarpetSettings.fillUpdates) { + + for (BlockPos blockpos1 : list) { + Block blokc = world.getBlockState(blockpos1).getBlock(); + world.updateNeighbors(blockpos1, blokc); + } + } + + Messenger.m(source, "gi Filled " + affected + " blocks"); + + return 1; + } } From 776eec05b2d6bf885c4d3ce0f62edff7aa3bea44 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Sun, 19 Apr 2020 09:10:32 +0200 Subject: [PATCH 029/198] I think that fixed it But now its conctantly crashing --- src/main/java/carpet/commands/DrawCommand.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index 6fba527e..5ba454d7 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -274,7 +274,7 @@ public class DrawCommand { int affected = 0; int offset = 0; if(pointup){ - offset=height; + offset=height+1; } BlockPos.Mutable mbpos = new BlockPos.Mutable(pos); @@ -286,16 +286,15 @@ public class DrawCommand { for (int x = -radius; x <= radius; ++x) { - for (int y = -offset; y <= height+1-offset; ++y) { + for (int y = 2-offset; y <= height-offset+1; ++y) { for (int z = -radius; z <= radius; ++z) { - if (x*x+z*z>(radius/height*y)*(radius/height*y)) { + if (!(x*x+z*z<=(radius/height*y)*(radius/height*y))) { continue; } mbpos.set(pos.getX() + x, pos.getY() + y + offset, pos.getZ() + z); - if (replacement == null || replacement.test(new CachedBlockPosition(world, mbpos, true))) { BlockEntity tileentity = world.getBlockEntity(mbpos); From 432c2a8394426c3f03c3cd8c4ad7beb0717ebc1b Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Sun, 19 Apr 2020 09:23:47 +0200 Subject: [PATCH 030/198] Now it works But if it is pointing up, it has a flat top --- src/main/java/carpet/commands/DrawCommand.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index 5ba454d7..d49f8cb7 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -274,7 +274,7 @@ public class DrawCommand { int affected = 0; int offset = 0; if(pointup){ - offset=height+1; + offset=height; } BlockPos.Mutable mbpos = new BlockPos.Mutable(pos); @@ -286,7 +286,7 @@ public class DrawCommand { for (int x = -radius; x <= radius; ++x) { - for (int y = 2-offset; y <= height-offset+1; ++y) { + for (int y = -offset; y <= height-offset-1; ++y) { for (int z = -radius; z <= radius; ++z) { From 6d5c7ed3bd427098827b7dd3586b0aa46dde2d3d Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Sun, 19 Apr 2020 09:29:41 +0200 Subject: [PATCH 031/198] Ok, NOW it works! --- src/main/java/carpet/commands/DrawCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index d49f8cb7..c6c9edcd 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -274,7 +274,7 @@ public class DrawCommand { int affected = 0; int offset = 0; if(pointup){ - offset=height; + offset=height-1; } BlockPos.Mutable mbpos = new BlockPos.Mutable(pos); From 25e8543a116078a46ae633fa8befc4755606d86b Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Sun, 19 Apr 2020 09:32:41 +0200 Subject: [PATCH 032/198] changing name to drawConey So later I can add drawConex and draw Conez methods --- src/main/java/carpet/commands/DrawCommand.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index c6c9edcd..a17123d3 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -74,7 +74,7 @@ public class DrawCommand { .then(argument("height",IntegerArgumentType.integer(1)) .then(argument("pointing up?",BoolArgumentType.bool()) .then(argument("block", BlockStateArgumentType.blockState()) - .executes((c) -> drawCone(c.getSource(), + .executes((c) -> drawConey(c.getSource(), BlockPosArgumentType.getBlockPos(c, "center"), IntegerArgumentType.getInteger(c, "radius"), IntegerArgumentType.getInteger(c, "height"), @@ -83,7 +83,7 @@ public class DrawCommand { ) .then(literal("replace") .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) - .executes((c) -> drawCone(c.getSource(), + .executes((c) -> drawConey(c.getSource(), BlockPosArgumentType.getBlockPos(c, "center"), IntegerArgumentType.getInteger(c, "radius"), IntegerArgumentType.getInteger(c, "height"), @@ -264,12 +264,12 @@ public class DrawCommand { return 1; } - private static int drawCone(ServerCommandSource source, BlockPos pos, int radius, int height, boolean pointup, BlockStateArgument block, + private static int drawConey(ServerCommandSource source, BlockPos pos, int radius, int height, boolean pointup, BlockStateArgument block, Predicate replacement) { - return (int) drawCone(source, pos, radius, height, block, replacement, pointup, false); + return (int) drawConey(source, pos, radius, height, block, replacement, pointup, false); } - private static int drawCone(ServerCommandSource source, BlockPos pos, int radius, int height,BlockStateArgument block, + private static int drawConey(ServerCommandSource source, BlockPos pos, int radius, int height,BlockStateArgument block, Predicate replacement, boolean pointup, boolean solid) { int affected = 0; int offset = 0; From 5aea313479b75a34574369a9731bff916d8a9352 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Sun, 19 Apr 2020 09:36:15 +0200 Subject: [PATCH 033/198] Added drawConex and drawConez methods But they're not used yet --- .../java/carpet/commands/DrawCommand.java | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index a17123d3..b23a0d81 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -325,4 +325,128 @@ public class DrawCommand { return 1; } + + private static int drawConex(ServerCommandSource source, BlockPos pos, int radius, int height, boolean pointup, BlockStateArgument block, + Predicate replacement) { + return (int) drawConex(source, pos, radius, height, block, replacement, pointup, false); + } + + private static int drawConex(ServerCommandSource source, BlockPos pos, int radius, int height,BlockStateArgument block, + Predicate replacement, boolean pointup, boolean solid) { + int affected = 0; + int offset = 0; + if(pointup){ + offset=height-1; + } + BlockPos.Mutable mbpos = new BlockPos.Mutable(pos); + + List list = Lists.newArrayList(); + + ServerWorld world = source.getWorld(); + + CarpetSettings.impendingFillSkipUpdates = !CarpetSettings.fillUpdates; + + for (int x = -offset; x <= height-offset-1; ++x) { + + for (int y = -radius; y <= radius; ++y) { + + for (int z = -radius; z <= radius; ++z) { + + if (!(y*y+z*z<=(radius/height*x)*(radius/height*x))) { + continue; + } + + mbpos.set(pos.getX() + x+ offset, pos.getY() + y, pos.getZ() + z); + if (replacement == null || replacement.test(new CachedBlockPosition(world, mbpos, true))) { + BlockEntity tileentity = world.getBlockEntity(mbpos); + + if (tileentity instanceof Inventory) { + ((Inventory) tileentity).clear(); + } + + if (block.setBlockState(world, mbpos, 2)) { + list.add(mbpos.toImmutable()); + ++affected; + } + } + } + } + } + + CarpetSettings.impendingFillSkipUpdates = false; + + if (CarpetSettings.fillUpdates) { + + for (BlockPos blockpos1 : list) { + Block blokc = world.getBlockState(blockpos1).getBlock(); + world.updateNeighbors(blockpos1, blokc); + } + } + + Messenger.m(source, "gi Filled " + affected + " blocks"); + + return 1; + } + + private static int drawConez(ServerCommandSource source, BlockPos pos, int radius, int height, boolean pointup, BlockStateArgument block, + Predicate replacement) { + return (int) drawConez(source, pos, radius, height, block, replacement, pointup, false); + } + + private static int drawConez(ServerCommandSource source, BlockPos pos, int radius, int height,BlockStateArgument block, + Predicate replacement, boolean pointup, boolean solid) { + int affected = 0; + int offset = 0; + if(pointup){ + offset=height-1; + } + BlockPos.Mutable mbpos = new BlockPos.Mutable(pos); + + List list = Lists.newArrayList(); + + ServerWorld world = source.getWorld(); + + CarpetSettings.impendingFillSkipUpdates = !CarpetSettings.fillUpdates; + + for (int z = -offset; z <= height-offset-1; ++z) { + + for (int y = -radius; y <= radius; ++y) { + + for (int x = -radius; x <= radius; ++x) { + + if (!(x*x+y*y<=(radius/height*z)*(radius/height*z))) { + continue; + } + + mbpos.set(pos.getX() + x, pos.getY() + y, pos.getZ() + z + offset); + if (replacement == null || replacement.test(new CachedBlockPosition(world, mbpos, true))) { + BlockEntity tileentity = world.getBlockEntity(mbpos); + + if (tileentity instanceof Inventory) { + ((Inventory) tileentity).clear(); + } + + if (block.setBlockState(world, mbpos, 2)) { + list.add(mbpos.toImmutable()); + ++affected; + } + } + } + } + } + + CarpetSettings.impendingFillSkipUpdates = false; + + if (CarpetSettings.fillUpdates) { + + for (BlockPos blockpos1 : list) { + Block blokc = world.getBlockState(blockpos1).getBlock(); + world.updateNeighbors(blockpos1, blokc); + } + } + + Messenger.m(source, "gi Filled " + affected + " blocks"); + + return 1; + } } From 40dcd31bb052248ebfdea8d7910023c41e31596e Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Sun, 19 Apr 2020 10:01:30 +0200 Subject: [PATCH 034/198] added direction dtection and command running based on that --- .../java/carpet/commands/DrawCommand.java | 62 +++++++++++++------ 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index b23a0d81..6d5ce171 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -8,6 +8,8 @@ import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.arguments.BoolArgumentType; import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.arguments.StringArgumentType; + import net.minecraft.block.Block; import net.minecraft.block.pattern.CachedBlockPosition; import net.minecraft.server.command.ServerCommandSource; @@ -73,23 +75,27 @@ public class DrawCommand { .then(argument("radius", IntegerArgumentType.integer(1)) .then(argument("height",IntegerArgumentType.integer(1)) .then(argument("pointing up?",BoolArgumentType.bool()) - .then(argument("block", BlockStateArgumentType.blockState()) - .executes((c) -> drawConey(c.getSource(), - BlockPosArgumentType.getBlockPos(c, "center"), - IntegerArgumentType.getInteger(c, "radius"), - IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c, "pointing up?"), - BlockStateArgumentType.getBlockState(c, "block"), null) - ) - .then(literal("replace") - .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) - .executes((c) -> drawConey(c.getSource(), - BlockPosArgumentType.getBlockPos(c, "center"), - IntegerArgumentType.getInteger(c, "radius"), - IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c, "pointing up?"), - BlockStateArgumentType.getBlockState(c, "block"), - BlockPredicateArgumentType.getBlockPredicate(c,"filter") + .then(argument("which direction?", StringArgumentType.string()) + .then(argument("block", BlockStateArgumentType.blockState()) + .executes((c) -> selectCone(c.getSource(), + BlockPosArgumentType.getBlockPos(c, "center"), + IntegerArgumentType.getInteger(c, "radius"), + IntegerArgumentType.getInteger(c, "height"), + BoolArgumentType.getBool(c,"pointing up?"), + StringArgumentType.getString(c,"which direction?"), + BlockStateArgumentType.getBlockState(c, "block"), null) + ) + .then(literal("replace") + .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) + .executes((c) -> selectCone(c.getSource(), + BlockPosArgumentType.getBlockPos(c, "center"), + IntegerArgumentType.getInteger(c, "radius"), + IntegerArgumentType.getInteger(c, "height"), + BoolArgumentType.getBool(c,"pointing up?"), + StringArgumentType.getString(c,"which direction?"), + BlockStateArgumentType.getBlockState(c, "block"), + BlockPredicateArgumentType.getBlockPredicate(c,"filter") + ) ) ) ) @@ -264,12 +270,32 @@ public class DrawCommand { return 1; } + private static int selectCone(ServerCommandSource source, BlockPos pos, int radius, int height, boolean pointup, String direction, BlockStateArgument block, + Predicate replacement){ + if(direction=="x"){ + drawConex(source, pos, radius, height, pointup, block, replacement); + } + + if(direction=="y"){ + drawConey(source, pos, radius, height, pointup, block, replacement); + } + + if(direction=="z"){ + drawConez(source, pos, radius, height, pointup, block, replacement); + } + + if(direction!="x" && direction!="y" && direction!="z"){ + Messenger.m(source,"Invalid direction, must be \"x\",\"y\" or \"z\""); + } + return(1); + } + private static int drawConey(ServerCommandSource source, BlockPos pos, int radius, int height, boolean pointup, BlockStateArgument block, Predicate replacement) { return (int) drawConey(source, pos, radius, height, block, replacement, pointup, false); } - private static int drawConey(ServerCommandSource source, BlockPos pos, int radius, int height,BlockStateArgument block, + private static double drawConey(ServerCommandSource source, BlockPos pos, int radius, int height,BlockStateArgument block, Predicate replacement, boolean pointup, boolean solid) { int affected = 0; int offset = 0; From 771fc8a437746874c21611f263879c14c0ccd1fd Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Sun, 19 Apr 2020 10:03:11 +0200 Subject: [PATCH 035/198] added specific return statements I dont even know why --- src/main/java/carpet/commands/DrawCommand.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index 6d5ce171..4bd83166 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -272,22 +272,27 @@ public class DrawCommand { private static int selectCone(ServerCommandSource source, BlockPos pos, int radius, int height, boolean pointup, String direction, BlockStateArgument block, Predicate replacement){ + int succeeded=0; + if(direction=="x"){ drawConex(source, pos, radius, height, pointup, block, replacement); + succeeded=1; } if(direction=="y"){ drawConey(source, pos, radius, height, pointup, block, replacement); + succeeded=1; } if(direction=="z"){ drawConez(source, pos, radius, height, pointup, block, replacement); + succeeded=1; } if(direction!="x" && direction!="y" && direction!="z"){ Messenger.m(source,"Invalid direction, must be \"x\",\"y\" or \"z\""); } - return(1); + return succeeded; } private static int drawConey(ServerCommandSource source, BlockPos pos, int radius, int height, boolean pointup, BlockStateArgument block, From b16c0abc54ccd5e6bac66b8e7ff4a65a9622ff91 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Sun, 19 Apr 2020 10:23:53 +0200 Subject: [PATCH 036/198] I tried this way But it wont detect strings ofr some reason!? --- src/main/java/carpet/commands/DrawCommand.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index 4bd83166..2d270c9e 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -93,8 +93,8 @@ public class DrawCommand { IntegerArgumentType.getInteger(c, "height"), BoolArgumentType.getBool(c,"pointing up?"), StringArgumentType.getString(c,"which direction?"), - BlockStateArgumentType.getBlockState(c, "block"), - BlockPredicateArgumentType.getBlockPredicate(c,"filter") + BlockStateArgumentType.getBlockState(c, "block"), + BlockPredicateArgumentType.getBlockPredicate(c,"filter") ) ) ) @@ -274,6 +274,8 @@ public class DrawCommand { Predicate replacement){ int succeeded=0; + direction=direction.toLowerCase().replaceAll("\\s",""); + if(direction=="x"){ drawConex(source, pos, radius, height, pointup, block, replacement); succeeded=1; @@ -290,7 +292,8 @@ public class DrawCommand { } if(direction!="x" && direction!="y" && direction!="z"){ - Messenger.m(source,"Invalid direction, must be \"x\",\"y\" or \"z\""); + Messenger.m(source,"gi "+direction+" is an invalid direction, must be x, y or z"); + System.out.println(direction); } return succeeded; } From 4a02bb1572e998278a90f1d98308cab6722ad56c Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Sun, 19 Apr 2020 10:33:42 +0200 Subject: [PATCH 037/198] The stupid way At least it works --- .../java/carpet/commands/DrawCommand.java | 85 +++++++++++-------- 1 file changed, 51 insertions(+), 34 deletions(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index 2d270c9e..f40e7d42 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -8,7 +8,6 @@ import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.arguments.BoolArgumentType; import com.mojang.brigadier.arguments.IntegerArgumentType; -import com.mojang.brigadier.arguments.StringArgumentType; import net.minecraft.block.Block; import net.minecraft.block.pattern.CachedBlockPosition; @@ -75,24 +74,70 @@ public class DrawCommand { .then(argument("radius", IntegerArgumentType.integer(1)) .then(argument("height",IntegerArgumentType.integer(1)) .then(argument("pointing up?",BoolArgumentType.bool()) - .then(argument("which direction?", StringArgumentType.string()) + .then(literal("x") .then(argument("block", BlockStateArgumentType.blockState()) - .executes((c) -> selectCone(c.getSource(), + .executes((c) -> drawConex(c.getSource(), BlockPosArgumentType.getBlockPos(c, "center"), IntegerArgumentType.getInteger(c, "radius"), IntegerArgumentType.getInteger(c, "height"), BoolArgumentType.getBool(c,"pointing up?"), - StringArgumentType.getString(c,"which direction?"), BlockStateArgumentType.getBlockState(c, "block"), null) ) .then(literal("replace") .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) - .executes((c) -> selectCone(c.getSource(), + .executes((c) -> drawConex(c.getSource(), + BlockPosArgumentType.getBlockPos(c, "center"), + IntegerArgumentType.getInteger(c, "radius"), + IntegerArgumentType.getInteger(c, "height"), + BoolArgumentType.getBool(c,"pointing up?"), + BlockStateArgumentType.getBlockState(c, "block"), + BlockPredicateArgumentType.getBlockPredicate(c,"filter") + ) + ) + ) + ) + ) + ) + .then(literal("y") + .then(argument("block", BlockStateArgumentType.blockState()) + .executes((c) -> drawConey(c.getSource(), + BlockPosArgumentType.getBlockPos(c, "center"), + IntegerArgumentType.getInteger(c, "radius"), + IntegerArgumentType.getInteger(c, "height"), + BoolArgumentType.getBool(c,"pointing up?"), + BlockStateArgumentType.getBlockState(c, "block"), null) + ) + .then(literal("replace") + .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) + .executes((c) -> drawConey(c.getSource(), + BlockPosArgumentType.getBlockPos(c, "center"), + IntegerArgumentType.getInteger(c, "radius"), + IntegerArgumentType.getInteger(c, "height"), + BoolArgumentType.getBool(c,"pointing up?"), + BlockStateArgumentType.getBlockState(c, "block"), + BlockPredicateArgumentType.getBlockPredicate(c,"filter") + ) + ) + ) + ) + ) + ) + .then(literal("z") + .then(argument("block", BlockStateArgumentType.blockState()) + .executes((c) -> drawConez(c.getSource(), + BlockPosArgumentType.getBlockPos(c, "center"), + IntegerArgumentType.getInteger(c, "radius"), + IntegerArgumentType.getInteger(c, "height"), + BoolArgumentType.getBool(c,"pointing up?"), + BlockStateArgumentType.getBlockState(c, "block"), null) + ) + .then(literal("replace") + .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) + .executes((c) -> drawConez(c.getSource(), BlockPosArgumentType.getBlockPos(c, "center"), IntegerArgumentType.getInteger(c, "radius"), IntegerArgumentType.getInteger(c, "height"), BoolArgumentType.getBool(c,"pointing up?"), - StringArgumentType.getString(c,"which direction?"), BlockStateArgumentType.getBlockState(c, "block"), BlockPredicateArgumentType.getBlockPredicate(c,"filter") ) @@ -270,34 +315,6 @@ public class DrawCommand { return 1; } - private static int selectCone(ServerCommandSource source, BlockPos pos, int radius, int height, boolean pointup, String direction, BlockStateArgument block, - Predicate replacement){ - int succeeded=0; - - direction=direction.toLowerCase().replaceAll("\\s",""); - - if(direction=="x"){ - drawConex(source, pos, radius, height, pointup, block, replacement); - succeeded=1; - } - - if(direction=="y"){ - drawConey(source, pos, radius, height, pointup, block, replacement); - succeeded=1; - } - - if(direction=="z"){ - drawConez(source, pos, radius, height, pointup, block, replacement); - succeeded=1; - } - - if(direction!="x" && direction!="y" && direction!="z"){ - Messenger.m(source,"gi "+direction+" is an invalid direction, must be x, y or z"); - System.out.println(direction); - } - return succeeded; - } - private static int drawConey(ServerCommandSource source, BlockPos pos, int radius, int height, boolean pointup, BlockStateArgument block, Predicate replacement) { return (int) drawConey(source, pos, radius, height, block, replacement, pointup, false); From 571e5722a812be4973baea35e8087a70ee0d7029 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Sun, 19 Apr 2020 10:51:15 +0200 Subject: [PATCH 038/198] added wiki definition to ingame definition cos y not --- src/main/java/carpet/CarpetSettings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index cb9a3598..9f55f8d4 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -299,7 +299,7 @@ public class CarpetSettings ) public static String commandPerimeterInfo = "true"; - @Rule(desc = "Enables /draw commands", extra = "... allows for drawing simple shapes", category = COMMAND) + @Rule(desc = "Enables /draw commands", extra = "... allows for drawing simple shapes or other shapes which are sorta difficult to do normally", category = COMMAND) public static String commandDraw = "true"; @Rule( From 7783f60f6474a8e6bf0353711c21da2d9604062e Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Mon, 20 Apr 2020 11:52:07 +0200 Subject: [PATCH 039/198] This should be about 300% faster I completely revamped it, only iterate over necessary blocks, and it returns correct value --- .../java/carpet/commands/DrawCommand.java | 60 ++++++++++--------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index f40e7d42..ba2fd8ef 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -6,6 +6,7 @@ import carpet.utils.Messenger; import com.google.common.collect.Lists; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.builder.LiteralArgumentBuilder; + import com.mojang.brigadier.arguments.BoolArgumentType; import com.mojang.brigadier.arguments.IntegerArgumentType; @@ -251,8 +252,23 @@ public class DrawCommand { return (x * x) + (y * y) + (z * z); } - private static int manhattan(int x1, int y1, int z1, int x2, int y2, int z2) { - return Math.abs(x1 - x2) + Math.abs(y1 - y2) + Math.abs(z1 - z2); + private static int blockset(ServerCommandSource source, int x, int y, int z, Predicate replacement, List list, + BlockPos.Mutable mbpos, BlockStateArgument block){ + ServerWorld world = source.getWorld(); + mbpos.set(x, y, z); + int success=0; + if (replacement == null || replacement.test(new CachedBlockPosition(world, mbpos, true))) { + BlockEntity tileentity = world.getBlockEntity(mbpos); + if (tileentity instanceof Inventory) { + ((Inventory) tileentity).clear(); + } + if (block.setBlockState(world, mbpos, 2)) { + list.add(mbpos.toImmutable()); + ++success; + } + } + + return success; } private static int drawDiamond(ServerCommandSource source, BlockPos pos, int radius, BlockStateArgument block, @@ -262,44 +278,30 @@ public class DrawCommand { private static int drawDiamond(ServerCommandSource source, BlockPos pos, int radius,BlockStateArgument block, Predicate replacement, boolean solid) { - int affected = 0; + int affected=0; BlockPos.Mutable mbpos = new BlockPos.Mutable(pos); - List list = Lists.newArrayList(); ServerWorld world = source.getWorld(); CarpetSettings.impendingFillSkipUpdates = !CarpetSettings.fillUpdates; + int skipped=0;//testing-delete afterwards + for (int r = 0; r < radius; ++r) { + int y=r-radius+1; + for (int x = -r; x <= r; ++x) { + int z=r-Math.abs(x); - for (int x = -radius; x <= radius; ++x) { - - for (int y = -radius; y <= radius; ++y) { - - for (int z = -radius; z <= radius; ++z) { - - if (manhattan(0, 0, 0, x, y, z) != radius) { - continue; - } - - mbpos.set(pos.getX() + x, pos.getY() + y, pos.getZ() + z); - - if (replacement == null || replacement.test(new CachedBlockPosition(world, mbpos, true))) { - BlockEntity tileentity = world.getBlockEntity(mbpos); - - if (tileentity instanceof Inventory) { - ((Inventory) tileentity).clear(); - } - - if (block.setBlockState(world, mbpos, 2)) { - list.add(mbpos.toImmutable()); - ++affected; - } - } - } + affected+=blockset(source, pos.getX()+x, pos.getY()-y, pos.getZ()+z, replacement, list, mbpos, block); + affected+=blockset(source, pos.getX()+x, pos.getY()-y, pos.getZ()-z, replacement, list, mbpos, block); + affected+=blockset(source, pos.getX()+x, pos.getY()+y, pos.getZ()+z, replacement, list, mbpos, block); + affected+=blockset(source, pos.getX()+x, pos.getY()+y, pos.getZ()-z, replacement, list, mbpos, block); } } + + System.out.println("Skipped: "+skipped);//testing-delete afterwards + CarpetSettings.impendingFillSkipUpdates = false; if (CarpetSettings.fillUpdates) { From aa94ec0ebc3df106db1b6f1d649c4e6fae1debd1 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Mon, 20 Apr 2020 11:54:52 +0200 Subject: [PATCH 040/198] forgot to remove testing stuff I knew this would happen --- src/main/java/carpet/commands/DrawCommand.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index ba2fd8ef..8f5a9858 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -286,7 +286,7 @@ public class DrawCommand { ServerWorld world = source.getWorld(); CarpetSettings.impendingFillSkipUpdates = !CarpetSettings.fillUpdates; - int skipped=0;//testing-delete afterwards + for (int r = 0; r < radius; ++r) { int y=r-radius+1; for (int x = -r; x <= r; ++x) { @@ -299,9 +299,6 @@ public class DrawCommand { } } - - System.out.println("Skipped: "+skipped);//testing-delete afterwards - CarpetSettings.impendingFillSkipUpdates = false; if (CarpetSettings.fillUpdates) { From fe0ecccd4f079efb24dc99938f747a5c8c8fb6c7 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Mon, 20 Apr 2020 13:44:49 +0200 Subject: [PATCH 041/198] Made drawCone WAY more fficient and code WAY less messy --- .../java/carpet/commands/DrawCommand.java | 214 +++++------------- 1 file changed, 57 insertions(+), 157 deletions(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index 8f5a9858..9c0efe4c 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -36,13 +36,13 @@ public class DrawCommand { .then(literal("sphere").then(argument("center", BlockPosArgumentType.blockPos()) .then(argument("radius", IntegerArgumentType.integer(1)) .then(argument("block", BlockStateArgumentType.blockState()) - .executes((c) -> drawCircle(c.getSource(), + .executes((c) -> drawSphere(c.getSource(), BlockPosArgumentType.getBlockPos(c, "center"), IntegerArgumentType.getInteger(c, "radius"), BlockStateArgumentType.getBlockState(c, "block"), null)) .then(literal("replace") .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) - .executes((c) -> drawCircle(c.getSource(), + .executes((c) -> drawSphere(c.getSource(), BlockPosArgumentType.getBlockPos(c, "center"), IntegerArgumentType.getInteger(c, "radius"), BlockStateArgumentType.getBlockState(c, "block"), @@ -77,20 +77,20 @@ public class DrawCommand { .then(argument("pointing up?",BoolArgumentType.bool()) .then(literal("x") .then(argument("block", BlockStateArgumentType.blockState()) - .executes((c) -> drawConex(c.getSource(), + .executes((c) -> drawCone(c.getSource(), BlockPosArgumentType.getBlockPos(c, "center"), IntegerArgumentType.getInteger(c, "radius"), IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c,"pointing up?"), + BoolArgumentType.getBool(c,"pointing up?"),"x", BlockStateArgumentType.getBlockState(c, "block"), null) ) .then(literal("replace") .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) - .executes((c) -> drawConex(c.getSource(), + .executes((c) -> drawCone(c.getSource(), BlockPosArgumentType.getBlockPos(c, "center"), IntegerArgumentType.getInteger(c, "radius"), IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c,"pointing up?"), + BoolArgumentType.getBool(c,"pointing up?"),"x", BlockStateArgumentType.getBlockState(c, "block"), BlockPredicateArgumentType.getBlockPredicate(c,"filter") ) @@ -101,20 +101,20 @@ public class DrawCommand { ) .then(literal("y") .then(argument("block", BlockStateArgumentType.blockState()) - .executes((c) -> drawConey(c.getSource(), + .executes((c) -> drawCone(c.getSource(), BlockPosArgumentType.getBlockPos(c, "center"), IntegerArgumentType.getInteger(c, "radius"), IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c,"pointing up?"), + BoolArgumentType.getBool(c,"pointing up?"),"y", BlockStateArgumentType.getBlockState(c, "block"), null) ) .then(literal("replace") .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) - .executes((c) -> drawConey(c.getSource(), + .executes((c) -> drawCone(c.getSource(), BlockPosArgumentType.getBlockPos(c, "center"), IntegerArgumentType.getInteger(c, "radius"), IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c,"pointing up?"), + BoolArgumentType.getBool(c,"pointing up?"),"y", BlockStateArgumentType.getBlockState(c, "block"), BlockPredicateArgumentType.getBlockPredicate(c,"filter") ) @@ -125,20 +125,20 @@ public class DrawCommand { ) .then(literal("z") .then(argument("block", BlockStateArgumentType.blockState()) - .executes((c) -> drawConez(c.getSource(), + .executes((c) -> drawCone(c.getSource(), BlockPosArgumentType.getBlockPos(c, "center"), IntegerArgumentType.getInteger(c, "radius"), IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c,"pointing up?"), + BoolArgumentType.getBool(c,"pointing up?"),"z", BlockStateArgumentType.getBlockState(c, "block"), null) ) .then(literal("replace") .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) - .executes((c) -> drawConez(c.getSource(), + .executes((c) -> drawCone(c.getSource(), BlockPosArgumentType.getBlockPos(c, "center"), IntegerArgumentType.getInteger(c, "radius"), IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c,"pointing up?"), + BoolArgumentType.getBool(c,"pointing up?"),"z", BlockStateArgumentType.getBlockState(c, "block"), BlockPredicateArgumentType.getBlockPredicate(c,"filter") ) @@ -155,12 +155,12 @@ public class DrawCommand { dispatcher.register(command); } - private static int drawCircle(ServerCommandSource source, BlockPos pos, int radius, BlockStateArgument block, + private static int drawSphere(ServerCommandSource source, BlockPos pos, int radius, BlockStateArgument block, Predicate replacement) { - return drawCircle(source, pos, (double) radius, (double) radius, (double) radius, block, replacement, false); + return drawSphere(source, pos, (double) radius, (double) radius, (double) radius, block, replacement, false); } - private static int drawCircle(ServerCommandSource source, BlockPos pos, double radiusX, double radiusY, + private static int drawSphere(ServerCommandSource source, BlockPos pos, double radiusX, double radiusY, double radiusZ, BlockStateArgument block, Predicate replacement, boolean solid) { int affected = 0; ServerWorld world = source.getWorld(); @@ -314,80 +314,56 @@ public class DrawCommand { return 1; } - private static int drawConey(ServerCommandSource source, BlockPos pos, int radius, int height, boolean pointup, BlockStateArgument block, - Predicate replacement) { - return (int) drawConey(source, pos, radius, height, block, replacement, pointup, false); - } + private static int drawCircle(ServerCommandSource source, BlockPos pos, int offset, int radius, int height, boolean pointup, BlockStateArgument block, String orientation, + Predicate replacement, List list, BlockPos.Mutable mbpos){ + + if(orientation=="x"){ + for(int y=-radius;y<=radius;++y){ - private static double drawConey(ServerCommandSource source, BlockPos pos, int radius, int height,BlockStateArgument block, - Predicate replacement, boolean pointup, boolean solid) { - int affected = 0; - int offset = 0; - if(pointup){ - offset=height-1; - } - BlockPos.Mutable mbpos = new BlockPos.Mutable(pos); + for(int z=-radius;z<=radius;++z){ - List list = Lists.newArrayList(); - - ServerWorld world = source.getWorld(); - - CarpetSettings.impendingFillSkipUpdates = !CarpetSettings.fillUpdates; - - for (int x = -radius; x <= radius; ++x) { - - for (int y = -offset; y <= height-offset-1; ++y) { - - for (int z = -radius; z <= radius; ++z) { - - if (!(x*x+z*z<=(radius/height*y)*(radius/height*y))) { - continue; - } - - mbpos.set(pos.getX() + x, pos.getY() + y + offset, pos.getZ() + z); - if (replacement == null || replacement.test(new CachedBlockPosition(world, mbpos, true))) { - BlockEntity tileentity = world.getBlockEntity(mbpos); - - if (tileentity instanceof Inventory) { - ((Inventory) tileentity).clear(); - } - - if (block.setBlockState(world, mbpos, 2)) { - list.add(mbpos.toImmutable()); - ++affected; - } + if(y*y+z*z<=radius*radius){ + blockset(source, pos.getX()+offset, pos.getY()+y, pos.getZ()+z, replacement, list, mbpos, block); } } } } - CarpetSettings.impendingFillSkipUpdates = false; + if(orientation=="y"){ + for(int x=-radius;x<=radius;++x){ - if (CarpetSettings.fillUpdates) { + for(int z=-radius;z<=radius;++z){ - for (BlockPos blockpos1 : list) { - Block blokc = world.getBlockState(blockpos1).getBlock(); - world.updateNeighbors(blockpos1, blokc); + if(x*x+z*z<=radius*radius){ + blockset(source, pos.getX()+x, pos.getY()+offset, pos.getZ()+z, replacement, list, mbpos, block); + } + } } } - Messenger.m(source, "gi Filled " + affected + " blocks"); + if(orientation=="z"){ + for(int y=-radius;y<=radius;++y){ + + for(int x=-radius;x<=radius;++x){ + + if(y*y+x*x<=radius*radius){ + blockset(source, pos.getX()+x, pos.getY()+y, pos.getZ()+offset, replacement, list, mbpos, block); + } + } + } + } return 1; } - - private static int drawConex(ServerCommandSource source, BlockPos pos, int radius, int height, boolean pointup, BlockStateArgument block, + + private static int drawCone(ServerCommandSource source, BlockPos pos, int radius, int height, boolean pointup, String orientation, BlockStateArgument block, Predicate replacement) { - return (int) drawConex(source, pos, radius, height, block, replacement, pointup, false); + return (int) drawCone(source, pos, radius, height, block, replacement, pointup, orientation, false); } - private static int drawConex(ServerCommandSource source, BlockPos pos, int radius, int height,BlockStateArgument block, - Predicate replacement, boolean pointup, boolean solid) { + private static double drawCone(ServerCommandSource source, BlockPos pos, int radius, int height,BlockStateArgument block, + Predicate replacement, boolean pointup, String orientation, boolean solid) { int affected = 0; - int offset = 0; - if(pointup){ - offset=height-1; - } BlockPos.Mutable mbpos = new BlockPos.Mutable(pos); List list = Lists.newArrayList(); @@ -396,95 +372,19 @@ public class DrawCommand { CarpetSettings.impendingFillSkipUpdates = !CarpetSettings.fillUpdates; - for (int x = -offset; x <= height-offset-1; ++x) { + int r = radius; - for (int y = -radius; y <= radius; ++y) { - - for (int z = -radius; z <= radius; ++z) { - - if (!(y*y+z*z<=(radius/height*x)*(radius/height*x))) { - continue; - } - - mbpos.set(pos.getX() + x+ offset, pos.getY() + y, pos.getZ() + z); - if (replacement == null || replacement.test(new CachedBlockPosition(world, mbpos, true))) { - BlockEntity tileentity = world.getBlockEntity(mbpos); - - if (tileentity instanceof Inventory) { - ((Inventory) tileentity).clear(); - } - - if (block.setBlockState(world, mbpos, 2)) { - list.add(mbpos.toImmutable()); - ++affected; - } - } - } + for(int i =0; i replacement) { - return (int) drawConez(source, pos, radius, height, block, replacement, pointup, false); - } - - private static int drawConez(ServerCommandSource source, BlockPos pos, int radius, int height,BlockStateArgument block, - Predicate replacement, boolean pointup, boolean solid) { - int affected = 0; - int offset = 0; - if(pointup){ - offset=height-1; - } - BlockPos.Mutable mbpos = new BlockPos.Mutable(pos); - - List list = Lists.newArrayList(); - - ServerWorld world = source.getWorld(); - - CarpetSettings.impendingFillSkipUpdates = !CarpetSettings.fillUpdates; - - for (int z = -offset; z <= height-offset-1; ++z) { - - for (int y = -radius; y <= radius; ++y) { - - for (int x = -radius; x <= radius; ++x) { - - if (!(x*x+y*y<=(radius/height*z)*(radius/height*z))) { - continue; - } - - mbpos.set(pos.getX() + x, pos.getY() + y, pos.getZ() + z + offset); - if (replacement == null || replacement.test(new CachedBlockPosition(world, mbpos, true))) { - BlockEntity tileentity = world.getBlockEntity(mbpos); - - if (tileentity instanceof Inventory) { - ((Inventory) tileentity).clear(); - } - - if (block.setBlockState(world, mbpos, 2)) { - list.add(mbpos.toImmutable()); - ++affected; - } - } - } - } - } - + CarpetSettings.impendingFillSkipUpdates = false; if (CarpetSettings.fillUpdates) { From e0828513fa93c5d65289a5223606ac1f879e3ea6 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Mon, 20 Apr 2020 17:00:51 +0200 Subject: [PATCH 042/198] Added pyramid literal FIrst step towards adding other shape pyramids --- .../java/carpet/commands/DrawCommand.java | 125 +++++++++--------- 1 file changed, 64 insertions(+), 61 deletions(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index 9c0efe4c..853b8e6f 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -70,77 +70,79 @@ public class DrawCommand { ) ) ) - .then(literal("cone") - .then(argument("center", BlockPosArgumentType.blockPos()) - .then(argument("radius", IntegerArgumentType.integer(1)) - .then(argument("height",IntegerArgumentType.integer(1)) - .then(argument("pointing up?",BoolArgumentType.bool()) - .then(literal("x") - .then(argument("block", BlockStateArgumentType.blockState()) - .executes((c) -> drawCone(c.getSource(), - BlockPosArgumentType.getBlockPos(c, "center"), - IntegerArgumentType.getInteger(c, "radius"), - IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c,"pointing up?"),"x", - BlockStateArgumentType.getBlockState(c, "block"), null) - ) - .then(literal("replace") - .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) - .executes((c) -> drawCone(c.getSource(), - BlockPosArgumentType.getBlockPos(c, "center"), - IntegerArgumentType.getInteger(c, "radius"), - IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c,"pointing up?"),"x", - BlockStateArgumentType.getBlockState(c, "block"), - BlockPredicateArgumentType.getBlockPredicate(c,"filter") + .then(literal("pyramid") + .then(literal("cone") + .then(argument("center", BlockPosArgumentType.blockPos()) + .then(argument("radius", IntegerArgumentType.integer(1)) + .then(argument("height",IntegerArgumentType.integer(1)) + .then(argument("pointing up?",BoolArgumentType.bool()) + .then(literal("x") + .then(argument("block", BlockStateArgumentType.blockState()) + .executes((c) -> drawCone(c.getSource(), + BlockPosArgumentType.getBlockPos(c, "center"), + IntegerArgumentType.getInteger(c, "radius"), + IntegerArgumentType.getInteger(c, "height"), + BoolArgumentType.getBool(c,"pointing up?"),"x", + BlockStateArgumentType.getBlockState(c, "block"), null) + ) + .then(literal("replace") + .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) + .executes((c) -> drawCone(c.getSource(), + BlockPosArgumentType.getBlockPos(c, "center"), + IntegerArgumentType.getInteger(c, "radius"), + IntegerArgumentType.getInteger(c, "height"), + BoolArgumentType.getBool(c,"pointing up?"),"x", + BlockStateArgumentType.getBlockState(c, "block"), + BlockPredicateArgumentType.getBlockPredicate(c,"filter") + ) ) ) ) ) ) - ) - .then(literal("y") - .then(argument("block", BlockStateArgumentType.blockState()) - .executes((c) -> drawCone(c.getSource(), - BlockPosArgumentType.getBlockPos(c, "center"), - IntegerArgumentType.getInteger(c, "radius"), - IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c,"pointing up?"),"y", - BlockStateArgumentType.getBlockState(c, "block"), null) - ) - .then(literal("replace") - .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) - .executes((c) -> drawCone(c.getSource(), - BlockPosArgumentType.getBlockPos(c, "center"), - IntegerArgumentType.getInteger(c, "radius"), - IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c,"pointing up?"),"y", - BlockStateArgumentType.getBlockState(c, "block"), - BlockPredicateArgumentType.getBlockPredicate(c,"filter") + .then(literal("y") + .then(argument("block", BlockStateArgumentType.blockState()) + .executes((c) -> drawCone(c.getSource(), + BlockPosArgumentType.getBlockPos(c, "center"), + IntegerArgumentType.getInteger(c, "radius"), + IntegerArgumentType.getInteger(c, "height"), + BoolArgumentType.getBool(c,"pointing up?"),"y", + BlockStateArgumentType.getBlockState(c, "block"), null) + ) + .then(literal("replace") + .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) + .executes((c) -> drawCone(c.getSource(), + BlockPosArgumentType.getBlockPos(c, "center"), + IntegerArgumentType.getInteger(c, "radius"), + IntegerArgumentType.getInteger(c, "height"), + BoolArgumentType.getBool(c,"pointing up?"),"y", + BlockStateArgumentType.getBlockState(c, "block"), + BlockPredicateArgumentType.getBlockPredicate(c,"filter") + ) ) ) ) ) ) - ) - .then(literal("z") - .then(argument("block", BlockStateArgumentType.blockState()) - .executes((c) -> drawCone(c.getSource(), - BlockPosArgumentType.getBlockPos(c, "center"), - IntegerArgumentType.getInteger(c, "radius"), - IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c,"pointing up?"),"z", - BlockStateArgumentType.getBlockState(c, "block"), null) - ) - .then(literal("replace") - .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) - .executes((c) -> drawCone(c.getSource(), - BlockPosArgumentType.getBlockPos(c, "center"), - IntegerArgumentType.getInteger(c, "radius"), - IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c,"pointing up?"),"z", - BlockStateArgumentType.getBlockState(c, "block"), - BlockPredicateArgumentType.getBlockPredicate(c,"filter") + .then(literal("z") + .then(argument("block", BlockStateArgumentType.blockState()) + .executes((c) -> drawCone(c.getSource(), + BlockPosArgumentType.getBlockPos(c, "center"), + IntegerArgumentType.getInteger(c, "radius"), + IntegerArgumentType.getInteger(c, "height"), + BoolArgumentType.getBool(c,"pointing up?"),"z", + BlockStateArgumentType.getBlockState(c, "block"), null) + ) + .then(literal("replace") + .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) + .executes((c) -> drawCone(c.getSource(), + BlockPosArgumentType.getBlockPos(c, "center"), + IntegerArgumentType.getInteger(c, "radius"), + IntegerArgumentType.getInteger(c, "height"), + BoolArgumentType.getBool(c,"pointing up?"),"z", + BlockStateArgumentType.getBlockState(c, "block"), + BlockPredicateArgumentType.getBlockPredicate(c,"filter") + ) ) ) ) @@ -151,6 +153,7 @@ public class DrawCommand { ) ) ) + ); dispatcher.register(command); } From 94a0f5584046f6986bb1850d1dc64497fcf4ac0c Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Mon, 20 Apr 2020 17:20:15 +0200 Subject: [PATCH 043/198] undid eqyptian braces I hope you're happy now https://github.com/gnembon/fabric-carpet/pull/232#discussion_r411022932 --- .../java/carpet/commands/DrawCommand.java | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index 853b8e6f..0dd280ff 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -159,12 +159,14 @@ public class DrawCommand { } private static int drawSphere(ServerCommandSource source, BlockPos pos, int radius, BlockStateArgument block, - Predicate replacement) { + Predicate replacement) + { return drawSphere(source, pos, (double) radius, (double) radius, (double) radius, block, replacement, false); } private static int drawSphere(ServerCommandSource source, BlockPos pos, double radiusX, double radiusY, - double radiusZ, BlockStateArgument block, Predicate replacement, boolean solid) { + double radiusZ, BlockStateArgument block, Predicate replacement, boolean solid) + { int affected = 0; ServerWorld world = source.getWorld(); @@ -209,25 +211,30 @@ public class DrawCommand { } if (!solid) { - if (lengthSq(nextXn, yn, zn) <= 1 && lengthSq(xn, nextYn, zn) <= 1 - && lengthSq(xn, yn, nextZn) <= 1) { + if (lengthSq(nextXn, yn, zn) <= 1 && lengthSq(xn, nextYn, zn) <= 1 && lengthSq(xn, yn, nextZn) <= 1) + { continue; } } CarpetSettings.impendingFillSkipUpdates = !CarpetSettings.fillUpdates; - for (int xmod = -1; xmod < 2; xmod += 2) { - for (int ymod = -1; ymod < 2; ymod += 2) { - for (int zmod = -1; zmod < 2; zmod += 2) { + for (int xmod = -1; xmod < 2; xmod += 2) + { + for (int ymod = -1; ymod < 2; ymod += 2) + { + for (int zmod = -1; zmod < 2; zmod += 2) + { mbpos.set(pos.getX() + xmod * x, pos.getY() + ymod * y, pos.getZ() + zmod * z); if (replacement == null || replacement.test(new CachedBlockPosition(world, mbpos, true))) { BlockEntity tileentity = world.getBlockEntity(mbpos); - if (tileentity instanceof Inventory) { + if (tileentity instanceof Inventory) + { ((Inventory) tileentity).clear(); } - if (block.setBlockState(world, mbpos, 2)) { + if (block.setBlockState(world, mbpos, 2)) + { list.add(mbpos.toImmutable()); ++affected; } From 36797a79e22c98cc271f2126d9563688d6f1f4d9 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Mon, 20 Apr 2020 17:22:56 +0200 Subject: [PATCH 044/198] Made cone actually return affected blocks I forgot for some reason --- src/main/java/carpet/commands/DrawCommand.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index 0dd280ff..34ae1c06 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -326,14 +326,14 @@ public class DrawCommand { private static int drawCircle(ServerCommandSource source, BlockPos pos, int offset, int radius, int height, boolean pointup, BlockStateArgument block, String orientation, Predicate replacement, List list, BlockPos.Mutable mbpos){ - + int successes=0; if(orientation=="x"){ for(int y=-radius;y<=radius;++y){ for(int z=-radius;z<=radius;++z){ if(y*y+z*z<=radius*radius){ - blockset(source, pos.getX()+offset, pos.getY()+y, pos.getZ()+z, replacement, list, mbpos, block); + successes+=blockset(source, pos.getX()+offset, pos.getY()+y, pos.getZ()+z, replacement, list, mbpos, block); } } } @@ -345,7 +345,7 @@ public class DrawCommand { for(int z=-radius;z<=radius;++z){ if(x*x+z*z<=radius*radius){ - blockset(source, pos.getX()+x, pos.getY()+offset, pos.getZ()+z, replacement, list, mbpos, block); + successes+=blockset(source, pos.getX()+x, pos.getY()+offset, pos.getZ()+z, replacement, list, mbpos, block); } } } @@ -357,13 +357,13 @@ public class DrawCommand { for(int x=-radius;x<=radius;++x){ if(y*y+x*x<=radius*radius){ - blockset(source, pos.getX()+x, pos.getY()+y, pos.getZ()+offset, replacement, list, mbpos, block); + successes+=blockset(source, pos.getX()+x, pos.getY()+y, pos.getZ()+offset, replacement, list, mbpos, block); } } } } - return 1; + return successes; } private static int drawCone(ServerCommandSource source, BlockPos pos, int radius, int height, boolean pointup, String orientation, BlockStateArgument block, @@ -391,7 +391,7 @@ public class DrawCommand { if(pointup==false){ r=radius*i/height; } - drawCircle(source, pos, i, (int) Math.round(r), height, pointup, block, orientation, replacement, list, mbpos); + affected=drawCircle(source, pos, i, (int) Math.round(r), height, pointup, block, orientation, replacement, list, mbpos); //circle(cx+_,cy,cz,'x',ceil(r),block) in scarpet implementation, _ is i here, and is added in offset parameter } From 582f39b98d4778b34509991f98682f23f1e3038d Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Mon, 20 Apr 2020 17:41:21 +0200 Subject: [PATCH 045/198] Renamed drawCone and added further steps toward pyramids --- .../java/carpet/commands/DrawCommand.java | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index 34ae1c06..94b55f0e 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -78,8 +78,9 @@ public class DrawCommand { .then(argument("pointing up?",BoolArgumentType.bool()) .then(literal("x") .then(argument("block", BlockStateArgumentType.blockState()) - .executes((c) -> drawCone(c.getSource(), + .executes((c) -> drawPyramid(c.getSource(), BlockPosArgumentType.getBlockPos(c, "center"), + "circle", IntegerArgumentType.getInteger(c, "radius"), IntegerArgumentType.getInteger(c, "height"), BoolArgumentType.getBool(c,"pointing up?"),"x", @@ -87,8 +88,9 @@ public class DrawCommand { ) .then(literal("replace") .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) - .executes((c) -> drawCone(c.getSource(), + .executes((c) -> drawPyramid(c.getSource(), BlockPosArgumentType.getBlockPos(c, "center"), + "circle", IntegerArgumentType.getInteger(c, "radius"), IntegerArgumentType.getInteger(c, "height"), BoolArgumentType.getBool(c,"pointing up?"),"x", @@ -102,8 +104,9 @@ public class DrawCommand { ) .then(literal("y") .then(argument("block", BlockStateArgumentType.blockState()) - .executes((c) -> drawCone(c.getSource(), + .executes((c) -> drawPyramid(c.getSource(), BlockPosArgumentType.getBlockPos(c, "center"), + "circle", IntegerArgumentType.getInteger(c, "radius"), IntegerArgumentType.getInteger(c, "height"), BoolArgumentType.getBool(c,"pointing up?"),"y", @@ -111,8 +114,9 @@ public class DrawCommand { ) .then(literal("replace") .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) - .executes((c) -> drawCone(c.getSource(), + .executes((c) -> drawPyramid(c.getSource(), BlockPosArgumentType.getBlockPos(c, "center"), + "circle", IntegerArgumentType.getInteger(c, "radius"), IntegerArgumentType.getInteger(c, "height"), BoolArgumentType.getBool(c,"pointing up?"),"y", @@ -126,8 +130,9 @@ public class DrawCommand { ) .then(literal("z") .then(argument("block", BlockStateArgumentType.blockState()) - .executes((c) -> drawCone(c.getSource(), + .executes((c) -> drawPyramid(c.getSource(), BlockPosArgumentType.getBlockPos(c, "center"), + "circle", IntegerArgumentType.getInteger(c, "radius"), IntegerArgumentType.getInteger(c, "height"), BoolArgumentType.getBool(c,"pointing up?"),"z", @@ -135,8 +140,9 @@ public class DrawCommand { ) .then(literal("replace") .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) - .executes((c) -> drawCone(c.getSource(), + .executes((c) -> drawPyramid(c.getSource(), BlockPosArgumentType.getBlockPos(c, "center"), + "circle", IntegerArgumentType.getInteger(c, "radius"), IntegerArgumentType.getInteger(c, "height"), BoolArgumentType.getBool(c,"pointing up?"),"z", @@ -366,13 +372,13 @@ public class DrawCommand { return successes; } - private static int drawCone(ServerCommandSource source, BlockPos pos, int radius, int height, boolean pointup, String orientation, BlockStateArgument block, + private static int drawPyramid(ServerCommandSource source, BlockPos pos, String shape, int radius, int height, boolean pointup, String orientation, BlockStateArgument block, Predicate replacement) { - return (int) drawCone(source, pos, radius, height, block, replacement, pointup, orientation, false); + return (int) drawPyramid(source, pos, radius, height, block, replacement, pointup, orientation, false, shape); } - private static double drawCone(ServerCommandSource source, BlockPos pos, int radius, int height,BlockStateArgument block, - Predicate replacement, boolean pointup, String orientation, boolean solid) { + private static double drawPyramid(ServerCommandSource source, BlockPos pos, int radius, int height,BlockStateArgument block, + Predicate replacement, boolean pointup, String orientation, boolean solid, String shape) { int affected = 0; BlockPos.Mutable mbpos = new BlockPos.Mutable(pos); From 2f780688753070996531d2aeebf16573d91bcb19 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Mon, 20 Apr 2020 17:41:45 +0200 Subject: [PATCH 046/198] figured out why it wasnt showing proper affected blocks --- src/main/java/carpet/commands/DrawCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index 94b55f0e..9dd11be3 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -397,7 +397,7 @@ public class DrawCommand { if(pointup==false){ r=radius*i/height; } - affected=drawCircle(source, pos, i, (int) Math.round(r), height, pointup, block, orientation, replacement, list, mbpos); + affected+=drawCircle(source, pos, i, (int) Math.round(r), height, pointup, block, orientation, replacement, list, mbpos); //circle(cx+_,cy,cz,'x',ceil(r),block) in scarpet implementation, _ is i here, and is added in offset parameter } From fcf2a6775c416e7675d39202aa4fb186ca9736f1 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Mon, 20 Apr 2020 21:29:19 +0200 Subject: [PATCH 047/198] Added square based pyramid also edited command tree to make it more understandable. Cones are, after all, simply circular-based pyramids. I may or may not add octagons in the future. --- .../java/carpet/commands/DrawCommand.java | 125 +++++++++++++++++- 1 file changed, 120 insertions(+), 5 deletions(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index 9dd11be3..fe25bc44 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -71,7 +71,7 @@ public class DrawCommand { ) ) .then(literal("pyramid") - .then(literal("cone") + .then(literal("circular") .then(argument("center", BlockPosArgumentType.blockPos()) .then(argument("radius", IntegerArgumentType.integer(1)) .then(argument("height",IntegerArgumentType.integer(1)) @@ -159,6 +159,94 @@ public class DrawCommand { ) ) ) + .then(literal("square") + .then(argument("center", BlockPosArgumentType.blockPos()) + .then(argument("radius", IntegerArgumentType.integer(1)) + .then(argument("height",IntegerArgumentType.integer(1)) + .then(argument("pointing up?",BoolArgumentType.bool()) + .then(literal("x") + .then(argument("block", BlockStateArgumentType.blockState()) + .executes((c) -> drawPyramid(c.getSource(), + BlockPosArgumentType.getBlockPos(c, "center"), + "square", + IntegerArgumentType.getInteger(c, "radius"), + IntegerArgumentType.getInteger(c, "height"), + BoolArgumentType.getBool(c,"pointing up?"),"x", + BlockStateArgumentType.getBlockState(c, "block"), null) + ) + .then(literal("replace") + .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) + .executes((c) -> drawPyramid(c.getSource(), + BlockPosArgumentType.getBlockPos(c, "center"), + "square", + IntegerArgumentType.getInteger(c, "radius"), + IntegerArgumentType.getInteger(c, "height"), + BoolArgumentType.getBool(c,"pointing up?"),"x", + BlockStateArgumentType.getBlockState(c, "block"), + BlockPredicateArgumentType.getBlockPredicate(c,"filter") + ) + ) + ) + ) + ) + ) + .then(literal("y") + .then(argument("block", BlockStateArgumentType.blockState()) + .executes((c) -> drawPyramid(c.getSource(), + BlockPosArgumentType.getBlockPos(c, "center"), + "square", + IntegerArgumentType.getInteger(c, "radius"), + IntegerArgumentType.getInteger(c, "height"), + BoolArgumentType.getBool(c,"pointing up?"),"y", + BlockStateArgumentType.getBlockState(c, "block"), null) + ) + .then(literal("replace") + .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) + .executes((c) -> drawPyramid(c.getSource(), + BlockPosArgumentType.getBlockPos(c, "center"), + "square", + IntegerArgumentType.getInteger(c, "radius"), + IntegerArgumentType.getInteger(c, "height"), + BoolArgumentType.getBool(c,"pointing up?"),"y", + BlockStateArgumentType.getBlockState(c, "block"), + BlockPredicateArgumentType.getBlockPredicate(c,"filter") + ) + ) + ) + ) + ) + ) + .then(literal("z") + .then(argument("block", BlockStateArgumentType.blockState()) + .executes((c) -> drawPyramid(c.getSource(), + BlockPosArgumentType.getBlockPos(c, "center"), + "square", + IntegerArgumentType.getInteger(c, "radius"), + IntegerArgumentType.getInteger(c, "height"), + BoolArgumentType.getBool(c,"pointing up?"),"z", + BlockStateArgumentType.getBlockState(c, "block"), null) + ) + .then(literal("replace") + .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) + .executes((c) -> drawPyramid(c.getSource(), + BlockPosArgumentType.getBlockPos(c, "center"), + "square", + IntegerArgumentType.getInteger(c, "radius"), + IntegerArgumentType.getInteger(c, "height"), + BoolArgumentType.getBool(c,"pointing up?"),"z", + BlockStateArgumentType.getBlockState(c, "block"), + BlockPredicateArgumentType.getBlockPredicate(c,"filter") + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) ); dispatcher.register(command); @@ -330,7 +418,7 @@ public class DrawCommand { return 1; } - private static int drawCircle(ServerCommandSource source, BlockPos pos, int offset, int radius, int height, boolean pointup, BlockStateArgument block, String orientation, + private static int drawCircle(ServerCommandSource source, BlockPos pos, int offset, int radius,BlockStateArgument block, String orientation, Predicate replacement, List list, BlockPos.Mutable mbpos){ int successes=0; if(orientation=="x"){ @@ -371,13 +459,35 @@ public class DrawCommand { return successes; } + + private static int drawSquare(ServerCommandSource source, BlockPos pos, int offset, int radius, BlockStateArgument block, String orientation, + Predicate replacement, List list, BlockPos.Mutable mbpos){ + int success=0; + + for(int axis1=-radius;axis1<=radius;++axis1){ + + for(int axis2=-radius;axis2<=radius;++axis2){ + if(orientation=="x"){ + success+=blockset(source, pos.getX()+offset, pos.getY()+axis1, pos.getZ()+axis2,replacement, list, mbpos, block); + } + if(orientation=="y"){ + success+=blockset(source, pos.getX()+axis1, pos.getY()+offset, pos.getZ()+axis2,replacement, list, mbpos, block); + } + if(orientation=="z"){ + success+=blockset(source, pos.getX()+axis2, pos.getY()+axis1, pos.getZ()+offset,replacement, list, mbpos, block); + } + } + } + + return success; + } private static int drawPyramid(ServerCommandSource source, BlockPos pos, String shape, int radius, int height, boolean pointup, String orientation, BlockStateArgument block, Predicate replacement) { return (int) drawPyramid(source, pos, radius, height, block, replacement, pointup, orientation, false, shape); } - private static double drawPyramid(ServerCommandSource source, BlockPos pos, int radius, int height,BlockStateArgument block, + private static double drawPyramid(ServerCommandSource source, BlockPos pos, int radius, int height, BlockStateArgument block, Predicate replacement, boolean pointup, String orientation, boolean solid, String shape) { int affected = 0; BlockPos.Mutable mbpos = new BlockPos.Mutable(pos); @@ -397,8 +507,13 @@ public class DrawCommand { if(pointup==false){ r=radius*i/height; } - affected+=drawCircle(source, pos, i, (int) Math.round(r), height, pointup, block, orientation, replacement, list, mbpos); - //circle(cx+_,cy,cz,'x',ceil(r),block) in scarpet implementation, _ is i here, and is added in offset parameter + if(shape=="circle"){ + affected+=drawCircle(source, pos, i, (int) Math.round(r), block, orientation, replacement, list, mbpos); + //circle(cx+_,cy,cz,'x',ceil(r),block) in scarpet implementation, _ is i here, and is added in offset parameter + } + if(shape=="square"){ + affected+=drawSquare(source, pos, i, (int) Math.round(r), block, orientation, replacement, list, mbpos); + } } CarpetSettings.impendingFillSkipUpdates = false; From d56706b133e38cc7318a561a84e98e45c389f37c Mon Sep 17 00:00:00 2001 From: gnembon Date: Tue, 21 Apr 2020 03:03:28 -0300 Subject: [PATCH 048/198] fixes #234 --- src/main/java/carpet/fakes/ItemEntityInterface.java | 4 ++-- src/main/java/carpet/mixins/ItemEntityMixin.java | 8 ++++---- src/main/java/carpet/script/value/EntityValue.java | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/carpet/fakes/ItemEntityInterface.java b/src/main/java/carpet/fakes/ItemEntityInterface.java index d4b8e839..5faa1f74 100644 --- a/src/main/java/carpet/fakes/ItemEntityInterface.java +++ b/src/main/java/carpet/fakes/ItemEntityInterface.java @@ -2,6 +2,6 @@ package carpet.fakes; public interface ItemEntityInterface { - int getAge(); - int getPickupDelay(); + int getAgeCM(); + int getPickupDelayCM(); } diff --git a/src/main/java/carpet/mixins/ItemEntityMixin.java b/src/main/java/carpet/mixins/ItemEntityMixin.java index dcc185ee..3c4620c5 100644 --- a/src/main/java/carpet/mixins/ItemEntityMixin.java +++ b/src/main/java/carpet/mixins/ItemEntityMixin.java @@ -30,12 +30,12 @@ public abstract class ItemEntityMixin extends Entity implements ItemEntityInterf } @Override - public int getAge() { + public int getAgeCM() { return this.age; } @Override - public int getPickupDelay() { + public int getPickupDelayCM() { return this.pickupDelay; } @@ -91,8 +91,8 @@ public abstract class ItemEntityMixin extends Entity implements ItemEntityInterf selfStack.increment(amount); self.setStack(selfStack); - this.pickupDelay = Math.max(((ItemEntityInterface)other).getPickupDelay(), this.pickupDelay); - this.age = Math.min(((ItemEntityInterface)other).getAge(), this.age); + this.pickupDelay = Math.max(((ItemEntityInterface)other).getPickupDelayCM(), this.pickupDelay); + this.age = Math.min(((ItemEntityInterface)other).getAgeCM(), this.age); otherStack.decrement(amount); if (otherStack.isEmpty()) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index 88c9f14a..97418977 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -254,7 +254,7 @@ public class EntityValue extends Value put("despawn_timer", (e, a) -> e instanceof LivingEntity?new NumericValue(((LivingEntity) e).getDespawnCounter()):Value.NULL); put("item", (e, a) -> (e instanceof ItemEntity)?ListValue.fromItemStack(((ItemEntity) e).getStack()):Value.NULL); put("count", (e, a) -> (e instanceof ItemEntity)?new NumericValue(((ItemEntity) e).getStack().getCount()):Value.NULL); - put("pickup_delay", (e, a) -> (e instanceof ItemEntity)?new NumericValue(((ItemEntityInterface) e).getPickupDelay()):Value.NULL); + put("pickup_delay", (e, a) -> (e instanceof ItemEntity)?new NumericValue(((ItemEntityInterface) e).getPickupDelayCM()):Value.NULL); // ItemEntity -> despawn timer via ssGetAge put("is_baby", (e, a) -> (e instanceof LivingEntity)?new NumericValue(((LivingEntity) e).isBaby()):Value.NULL); put("target", (e, a) -> { From f5316a1e2d19e124dd51b40e29639436808e82ce Mon Sep 17 00:00:00 2001 From: gnembon Date: Tue, 21 Apr 2020 01:38:48 -0300 Subject: [PATCH 049/198] fixes #228 --- .../java/carpet/script/value/EntityValue.java | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index 97418977..a0237460 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -532,7 +532,37 @@ public class EntityValue extends Value private static final Map> featureModifiers = new HashMap>() {{ put("remove", (entity, value) -> entity.remove()); put("age", (e, v) -> e.age = Math.abs((int)NumericValue.asNumber(v).getLong()) ); - put("health", (e, v) -> { if (e instanceof LivingEntity) ((LivingEntity) e).setHealth((float) NumericValue.asNumber(v).getDouble()); }); + put("health", (e, v) -> { + float health = (float) NumericValue.asNumber(v).getDouble(); + if (health <= 0f && e instanceof ServerPlayerEntity) + { + ServerPlayerEntity player = (ServerPlayerEntity) e; + if (player.container != null) + { + // if player dies with open container, then that causes NPE on the client side + // its a client side bug that may never surface unless vanilla gets into scripting at some point + // bug: #228 + player.closeContainer(); + } + ((LivingEntity) e).setHealth(health); + } + if (e instanceof LivingEntity) ((LivingEntity) e).setHealth(health); + }); + // todo add handling of the source for extra effects + /*put("damage", (e, v) -> { + float dmgPoints; + DamageSource source; + if (v instanceof ListValue && ((ListValue) v).getItems().size() > 1) + { + List vals = ((ListValue) v).getItems(); + dmgPoints = (float) NumericValue.asNumber(v).getDouble(); + source = DamageSource ... yeah... + } + else + { + + } + });*/ put("kill", (e, v) -> e.kill()); put("location", (e, v) -> { From 2b6a1bf1c528b3cae367391bb425ef25d3af3a32 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Tue, 21 Apr 2020 11:07:00 +0200 Subject: [PATCH 050/198] added gamemode_id and jump modifications --- .../java/carpet/script/value/EntityValue.java | 62 ++++++++++++++----- 1 file changed, 47 insertions(+), 15 deletions(-) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index a0237460..e89d634a 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -4,6 +4,7 @@ import carpet.fakes.EntityInterface; import carpet.fakes.ItemEntityInterface; import carpet.fakes.MobEntityInterface; import carpet.helpers.Tracer; +import carpet.helpers.EntityPlayerActionPack; import carpet.patches.EntityPlayerMPFake; import carpet.script.CarpetContext; import carpet.script.EntityEventsGroup; @@ -45,6 +46,7 @@ import net.minecraft.util.math.Direction; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.util.registry.Registry; +import net.minecraft.world.GameMode; import org.apache.commons.lang3.tuple.Pair; import java.util.ArrayList; @@ -891,21 +893,51 @@ public class EntityValue extends Value throw new InternalExpressionException("'effect' needs either no arguments (clear) or effect name, duration, and optional amplifier, show particles and show icon"); }); - // gamemode - // spectate - // "fire" - // "extinguish" - // "silent" - // "gravity" - // "invulnerable" - // "dimension" - // "item" - // "count", - // "age", - // "effect_"name - // "hold" - // "hold_offhand" - // "jump" + put("gamemode", (e,v)->{ + if(!(e instanceof ServerPlayerEntity)){ + throw new InternalExpressionException("Cannot change the gamemode of non-player entities"); + } + if(v.readInteger()==0){ + ((ServerPlayerEntity) e).setGameMode(GameMode.SURVIVAL); + return; + } + if(v.getString()=="creative"){ + ((ServerPlayerEntity) e).setGameMode(GameMode.CREATIVE); + return; + } + if(v.getString()=="spectator"){ + ((ServerPlayerEntity) e).setGameMode(GameMode.SPECTATOR); + return; + } + if(v.getString()=="adventure"){ + ((ServerPlayerEntity) e).setGameMode(GameMode.ADVENTURE); + return; + } + throw new InternalExpressionException("s"+v.getString()+"s is an invalid gamemode type"); + }); + + put("jump",(e,v)->{ + if(!(e instanceof ServerPlayerEntity)){ + throw new InternalExpressionException("Non-player entities can't jump"); + } + ((PlayerEntity) e).jump(); + }); + + // gamemode_id [check](gamemode just wont read string) + // spectate [check] + // "fire" [] + // "extinguish" [] + // "silent" [] + // "gravity" [] + // "invulnerable" [] + // "dimension" [] + // "item" [] + // "count", [] + // "age", [] + // "effect_"name [] + // "hold" [inventory_set?] + // "hold_offhand" [inventory_set?] + // "jump" [check] // "nbt" <-big one, for now use run('data merge entity ... }}; From db48a5c0611bd93baf4f110699d22730ed02494a Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Tue, 21 Apr 2020 11:08:40 +0200 Subject: [PATCH 051/198] wait, I hadn't amde it to gamemode_id! oops --- src/main/java/carpet/script/value/EntityValue.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index e89d634a..d20c34f5 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -893,7 +893,7 @@ public class EntityValue extends Value throw new InternalExpressionException("'effect' needs either no arguments (clear) or effect name, duration, and optional amplifier, show particles and show icon"); }); - put("gamemode", (e,v)->{ + put("gamemode_id", (e,v)->{ if(!(e instanceof ServerPlayerEntity)){ throw new InternalExpressionException("Cannot change the gamemode of non-player entities"); } @@ -901,15 +901,15 @@ public class EntityValue extends Value ((ServerPlayerEntity) e).setGameMode(GameMode.SURVIVAL); return; } - if(v.getString()=="creative"){ + if(v.readInteger()==0){ ((ServerPlayerEntity) e).setGameMode(GameMode.CREATIVE); return; } - if(v.getString()=="spectator"){ + if(v.readInteger()==0){ ((ServerPlayerEntity) e).setGameMode(GameMode.SPECTATOR); return; } - if(v.getString()=="adventure"){ + if(v.readInteger()==0){ ((ServerPlayerEntity) e).setGameMode(GameMode.ADVENTURE); return; } From 786ce3116ae1307e9d6c738a6e2238d8567646ad Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Tue, 21 Apr 2020 11:10:26 +0200 Subject: [PATCH 052/198] added different gamemode ids cos i copypastad code and forgot to do that --- src/main/java/carpet/script/value/EntityValue.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index d20c34f5..423b88d0 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -901,15 +901,15 @@ public class EntityValue extends Value ((ServerPlayerEntity) e).setGameMode(GameMode.SURVIVAL); return; } - if(v.readInteger()==0){ + if(v.readInteger()==1){ ((ServerPlayerEntity) e).setGameMode(GameMode.CREATIVE); return; } - if(v.readInteger()==0){ + if(v.readInteger()==3){ ((ServerPlayerEntity) e).setGameMode(GameMode.SPECTATOR); return; } - if(v.readInteger()==0){ + if(v.readInteger()==2){ ((ServerPlayerEntity) e).setGameMode(GameMode.ADVENTURE); return; } From 8d41bfa167e42c4d75932e04fcbaea50244abfe3 Mon Sep 17 00:00:00 2001 From: Ghoulboy Date: Tue, 21 Apr 2020 11:15:55 +0200 Subject: [PATCH 053/198] Undid egyptian bracing cos gnembon hates egyptians --- .../java/carpet/commands/DrawCommand.java | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index fe25bc44..ee952072 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -29,14 +29,17 @@ import java.lang.Math; import static net.minecraft.server.command.CommandManager.argument; import static net.minecraft.server.command.CommandManager.literal; -public class DrawCommand { - public static void register(CommandDispatcher dispatcher) { - LiteralArgumentBuilder command = literal("draw") - .requires((player) -> SettingsManager.canUseCommand(player, CarpetSettings.commandDraw)) - .then(literal("sphere").then(argument("center", BlockPosArgumentType.blockPos()) - .then(argument("radius", IntegerArgumentType.integer(1)) - .then(argument("block", BlockStateArgumentType.blockState()) - .executes((c) -> drawSphere(c.getSource(), +public class DrawCommand +{ + public static void register(CommandDispatcher dispatcher) + { + LiteralArgumentBuilder command = literal("draw"). + requires((player) -> SettingsManager.canUseCommand(player, CarpetSettings.commandDraw)). + then(literal("sphere"). + then(argument("center", BlockPosArgumentType.blockPos()). + then(argument("radius", IntegerArgumentType.integer(1)). + then(argument("block", BlockStateArgumentType.blockState()). + executes((c) -> drawSphere(c.getSource(), BlockPosArgumentType.getBlockPos(c, "center"), IntegerArgumentType.getInteger(c, "radius"), BlockStateArgumentType.getBlockState(c, "block"), null)) From 24787e8e5617dbdc248a5e5a9ff4daa400326e9b Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 22 Apr 2020 01:26:06 -0300 Subject: [PATCH 054/198] renaming getTicketManager to de-conflict with other mods --- src/main/java/carpet/fakes/ServerChunkManagerInterface.java | 2 +- src/main/java/carpet/mixins/ServerChunkManagerMixin.java | 2 +- src/main/java/carpet/script/CarpetExpression.java | 2 +- src/main/java/carpet/utils/SpawnChunks.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/carpet/fakes/ServerChunkManagerInterface.java b/src/main/java/carpet/fakes/ServerChunkManagerInterface.java index 9f7daddc..f63cb266 100644 --- a/src/main/java/carpet/fakes/ServerChunkManagerInterface.java +++ b/src/main/java/carpet/fakes/ServerChunkManagerInterface.java @@ -4,5 +4,5 @@ import net.minecraft.server.world.ChunkTicketManager; public interface ServerChunkManagerInterface { - ChunkTicketManager getTicketManager(); + ChunkTicketManager getCMTicketManager(); } diff --git a/src/main/java/carpet/mixins/ServerChunkManagerMixin.java b/src/main/java/carpet/mixins/ServerChunkManagerMixin.java index ce4b9132..f0fab105 100644 --- a/src/main/java/carpet/mixins/ServerChunkManagerMixin.java +++ b/src/main/java/carpet/mixins/ServerChunkManagerMixin.java @@ -35,7 +35,7 @@ public abstract class ServerChunkManagerMixin implements ServerChunkManagerInter @Shadow @Final private ChunkTicketManager ticketManager; @Override // shared between scarpet and spawnChunks setting - public ChunkTicketManager getTicketManager() + public ChunkTicketManager getCMTicketManager() { return ticketManager; } diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 5692dbe7..30c3f3e4 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -713,7 +713,7 @@ public class CarpetExpression ServerWorld world = ((CarpetContext) c).s.getWorld(); Long2ObjectOpenHashMap>> levelTickets = ( (ChunkTicketManagerInterface) ((ServerChunkManagerInterface) world.getChunkManager()) - .getTicketManager() + .getCMTicketManager() ).getTicketsByPosition(); List res = new ArrayList<>(); if (lv.size() == 0) diff --git a/src/main/java/carpet/utils/SpawnChunks.java b/src/main/java/carpet/utils/SpawnChunks.java index e97cb531..f2e8f117 100644 --- a/src/main/java/carpet/utils/SpawnChunks.java +++ b/src/main/java/carpet/utils/SpawnChunks.java @@ -10,7 +10,7 @@ public class SpawnChunks { public static void changeSpawnChunks(ServerChunkManager chunkManager, ChunkPos pos, int size) { - ChunkTicketManager ticketManager = ((ServerChunkManagerInterface)chunkManager).getTicketManager(); + ChunkTicketManager ticketManager = ((ServerChunkManagerInterface)chunkManager).getCMTicketManager(); ((ChunkTicketManagerInterface)ticketManager).changeSpawnChunks(pos, size); } } From 699d0abc5247c48012b371266a5239ea7c1bf1b7 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Wed, 22 Apr 2020 09:54:49 +0200 Subject: [PATCH 055/198] broke into 2 lines --- src/main/java/carpet/CarpetSettings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index 9f55f8d4..5376a05b 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -299,7 +299,7 @@ public class CarpetSettings ) public static String commandPerimeterInfo = "true"; - @Rule(desc = "Enables /draw commands", extra = "... allows for drawing simple shapes or other shapes which are sorta difficult to do normally", category = COMMAND) + @Rule(desc = "Enables /draw commands", extra = {"... allows for drawing simple shapes or","other shapes which are sorta difficult to do normally"}, category = COMMAND) public static String commandDraw = "true"; @Rule( From e8c8e68333a030ac86dc6b6cf135b7dafa807d28 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Wed, 22 Apr 2020 10:34:42 +0200 Subject: [PATCH 056/198] moved it all to ints less intuitive but code syntax is much better! --- .../java/carpet/commands/DrawCommand.java | 196 +++--------------- 1 file changed, 28 insertions(+), 168 deletions(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index ee952072..ee57d491 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -6,7 +6,6 @@ import carpet.utils.Messenger; import com.google.common.collect.Lists; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.builder.LiteralArgumentBuilder; - import com.mojang.brigadier.arguments.BoolArgumentType; import com.mojang.brigadier.arguments.IntegerArgumentType; @@ -17,6 +16,7 @@ import net.minecraft.command.arguments.BlockPosArgumentType; import net.minecraft.command.arguments.BlockPredicateArgumentType; import net.minecraft.command.arguments.BlockStateArgument; import net.minecraft.command.arguments.BlockStateArgumentType; +import static net.minecraft.server.command.CommandSource.suggestMatching; import net.minecraft.inventory.Inventory; import net.minecraft.block.entity.BlockEntity; import net.minecraft.util.math.BlockPos; @@ -74,81 +74,33 @@ public class DrawCommand ) ) .then(literal("pyramid") - .then(literal("circular") - .then(argument("center", BlockPosArgumentType.blockPos()) - .then(argument("radius", IntegerArgumentType.integer(1)) - .then(argument("height",IntegerArgumentType.integer(1)) - .then(argument("pointing up?",BoolArgumentType.bool()) - .then(literal("x") + .then(argument("center", BlockPosArgumentType.blockPos()) + .then(argument("radius", IntegerArgumentType.integer(1)) + .then(argument("height",IntegerArgumentType.integer(1)) + .then(argument("pointing up?",BoolArgumentType.bool()) + .then(argument("type",IntegerArgumentType.integer(1)) + .suggests( (c, b) -> suggestMatching(new String[]{"square=0","circle=1"},b)) + .then(argument("orientation",IntegerArgumentType.integer(1)) + .suggests( (c, b) -> suggestMatching(new String[]{"x=0","y=1","z=2"},b)) .then(argument("block", BlockStateArgumentType.blockState()) .executes((c) -> drawPyramid(c.getSource(), BlockPosArgumentType.getBlockPos(c, "center"), - "circle", + IntegerArgumentType.getInteger(c, "type"), IntegerArgumentType.getInteger(c, "radius"), IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c,"pointing up?"),"x", + BoolArgumentType.getBool(c,"pointing up?"), + IntegerArgumentType.getInteger(c,"orientation"), BlockStateArgumentType.getBlockState(c, "block"), null) ) .then(literal("replace") .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) .executes((c) -> drawPyramid(c.getSource(), BlockPosArgumentType.getBlockPos(c, "center"), - "circle", + IntegerArgumentType.getInteger(c, "type"), IntegerArgumentType.getInteger(c, "radius"), IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c,"pointing up?"),"x", - BlockStateArgumentType.getBlockState(c, "block"), - BlockPredicateArgumentType.getBlockPredicate(c,"filter") - ) - ) - ) - ) - ) - ) - .then(literal("y") - .then(argument("block", BlockStateArgumentType.blockState()) - .executes((c) -> drawPyramid(c.getSource(), - BlockPosArgumentType.getBlockPos(c, "center"), - "circle", - IntegerArgumentType.getInteger(c, "radius"), - IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c,"pointing up?"),"y", - BlockStateArgumentType.getBlockState(c, "block"), null) - ) - .then(literal("replace") - .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) - .executes((c) -> drawPyramid(c.getSource(), - BlockPosArgumentType.getBlockPos(c, "center"), - "circle", - IntegerArgumentType.getInteger(c, "radius"), - IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c,"pointing up?"),"y", - BlockStateArgumentType.getBlockState(c, "block"), - BlockPredicateArgumentType.getBlockPredicate(c,"filter") - ) - ) - ) - ) - ) - ) - .then(literal("z") - .then(argument("block", BlockStateArgumentType.blockState()) - .executes((c) -> drawPyramid(c.getSource(), - BlockPosArgumentType.getBlockPos(c, "center"), - "circle", - IntegerArgumentType.getInteger(c, "radius"), - IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c,"pointing up?"),"z", - BlockStateArgumentType.getBlockState(c, "block"), null) - ) - .then(literal("replace") - .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) - .executes((c) -> drawPyramid(c.getSource(), - BlockPosArgumentType.getBlockPos(c, "center"), - "circle", - IntegerArgumentType.getInteger(c, "radius"), - IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c,"pointing up?"),"z", + BoolArgumentType.getBool(c,"pointing up?"), + IntegerArgumentType.getInteger(c,"orientation"), BlockStateArgumentType.getBlockState(c, "block"), BlockPredicateArgumentType.getBlockPredicate(c,"filter") ) @@ -162,95 +114,6 @@ public class DrawCommand ) ) ) - .then(literal("square") - .then(argument("center", BlockPosArgumentType.blockPos()) - .then(argument("radius", IntegerArgumentType.integer(1)) - .then(argument("height",IntegerArgumentType.integer(1)) - .then(argument("pointing up?",BoolArgumentType.bool()) - .then(literal("x") - .then(argument("block", BlockStateArgumentType.blockState()) - .executes((c) -> drawPyramid(c.getSource(), - BlockPosArgumentType.getBlockPos(c, "center"), - "square", - IntegerArgumentType.getInteger(c, "radius"), - IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c,"pointing up?"),"x", - BlockStateArgumentType.getBlockState(c, "block"), null) - ) - .then(literal("replace") - .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) - .executes((c) -> drawPyramid(c.getSource(), - BlockPosArgumentType.getBlockPos(c, "center"), - "square", - IntegerArgumentType.getInteger(c, "radius"), - IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c,"pointing up?"),"x", - BlockStateArgumentType.getBlockState(c, "block"), - BlockPredicateArgumentType.getBlockPredicate(c,"filter") - ) - ) - ) - ) - ) - ) - .then(literal("y") - .then(argument("block", BlockStateArgumentType.blockState()) - .executes((c) -> drawPyramid(c.getSource(), - BlockPosArgumentType.getBlockPos(c, "center"), - "square", - IntegerArgumentType.getInteger(c, "radius"), - IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c,"pointing up?"),"y", - BlockStateArgumentType.getBlockState(c, "block"), null) - ) - .then(literal("replace") - .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) - .executes((c) -> drawPyramid(c.getSource(), - BlockPosArgumentType.getBlockPos(c, "center"), - "square", - IntegerArgumentType.getInteger(c, "radius"), - IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c,"pointing up?"),"y", - BlockStateArgumentType.getBlockState(c, "block"), - BlockPredicateArgumentType.getBlockPredicate(c,"filter") - ) - ) - ) - ) - ) - ) - .then(literal("z") - .then(argument("block", BlockStateArgumentType.blockState()) - .executes((c) -> drawPyramid(c.getSource(), - BlockPosArgumentType.getBlockPos(c, "center"), - "square", - IntegerArgumentType.getInteger(c, "radius"), - IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c,"pointing up?"),"z", - BlockStateArgumentType.getBlockState(c, "block"), null) - ) - .then(literal("replace") - .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) - .executes((c) -> drawPyramid(c.getSource(), - BlockPosArgumentType.getBlockPos(c, "center"), - "square", - IntegerArgumentType.getInteger(c, "radius"), - IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c,"pointing up?"),"z", - BlockStateArgumentType.getBlockState(c, "block"), - BlockPredicateArgumentType.getBlockPredicate(c,"filter") - ) - ) - ) - ) - ) - ) - ) - ) - ) - ) - ) - ); dispatcher.register(command); } @@ -421,10 +284,10 @@ public class DrawCommand return 1; } - private static int drawCircle(ServerCommandSource source, BlockPos pos, int offset, int radius,BlockStateArgument block, String orientation, + private static int drawCircle(ServerCommandSource source, BlockPos pos, int offset, int radius,BlockStateArgument block, int orientation, Predicate replacement, List list, BlockPos.Mutable mbpos){ int successes=0; - if(orientation=="x"){ + if(orientation==0){ for(int y=-radius;y<=radius;++y){ for(int z=-radius;z<=radius;++z){ @@ -436,7 +299,7 @@ public class DrawCommand } } - if(orientation=="y"){ + if(orientation==1){ for(int x=-radius;x<=radius;++x){ for(int z=-radius;z<=radius;++z){ @@ -448,7 +311,7 @@ public class DrawCommand } } - if(orientation=="z"){ + if(orientation==2){ for(int y=-radius;y<=radius;++y){ for(int x=-radius;x<=radius;++x){ @@ -463,20 +326,20 @@ public class DrawCommand return successes; } - private static int drawSquare(ServerCommandSource source, BlockPos pos, int offset, int radius, BlockStateArgument block, String orientation, + private static int drawSquare(ServerCommandSource source, BlockPos pos, int offset, int radius, BlockStateArgument block, int orientation, Predicate replacement, List list, BlockPos.Mutable mbpos){ int success=0; for(int axis1=-radius;axis1<=radius;++axis1){ for(int axis2=-radius;axis2<=radius;++axis2){ - if(orientation=="x"){ + if(orientation==0){ success+=blockset(source, pos.getX()+offset, pos.getY()+axis1, pos.getZ()+axis2,replacement, list, mbpos, block); } - if(orientation=="y"){ + if(orientation==1){ success+=blockset(source, pos.getX()+axis1, pos.getY()+offset, pos.getZ()+axis2,replacement, list, mbpos, block); } - if(orientation=="z"){ + if(orientation==2){ success+=blockset(source, pos.getX()+axis2, pos.getY()+axis1, pos.getZ()+offset,replacement, list, mbpos, block); } } @@ -485,13 +348,13 @@ public class DrawCommand return success; } - private static int drawPyramid(ServerCommandSource source, BlockPos pos, String shape, int radius, int height, boolean pointup, String orientation, BlockStateArgument block, + private static int drawPyramid(ServerCommandSource source, BlockPos pos, int shape, int radius, int height, boolean pointup, int orientation, BlockStateArgument block, Predicate replacement) { return (int) drawPyramid(source, pos, radius, height, block, replacement, pointup, orientation, false, shape); } private static double drawPyramid(ServerCommandSource source, BlockPos pos, int radius, int height, BlockStateArgument block, - Predicate replacement, boolean pointup, String orientation, boolean solid, String shape) { + Predicate replacement, boolean pointup, int orientation, boolean solid, int shape) { int affected = 0; BlockPos.Mutable mbpos = new BlockPos.Mutable(pos); @@ -506,15 +369,12 @@ public class DrawCommand for(int i =0; i Date: Wed, 22 Apr 2020 10:38:07 +0200 Subject: [PATCH 057/198] undoingn egyptian braces seriously gnemobn, what do you have against them? --- src/main/java/carpet/commands/DrawCommand.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index ee57d491..8cffb9ae 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -186,7 +186,8 @@ public class DrawCommand { mbpos.set(pos.getX() + xmod * x, pos.getY() + ymod * y, pos.getZ() + zmod * z); if (replacement == null - || replacement.test(new CachedBlockPosition(world, mbpos, true))) { + || replacement.test(new CachedBlockPosition(world, mbpos, true))) + { BlockEntity tileentity = world.getBlockEntity(mbpos); if (tileentity instanceof Inventory) { From 0ee96174b823577c1f17970bb9b1c44e8c2bef7f Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Wed, 22 Apr 2020 10:56:14 +0200 Subject: [PATCH 058/198] apparently you can't input 0 otherwise its fine --- src/main/java/carpet/commands/DrawCommand.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index 8cffb9ae..fcc55d82 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -79,9 +79,9 @@ public class DrawCommand .then(argument("height",IntegerArgumentType.integer(1)) .then(argument("pointing up?",BoolArgumentType.bool()) .then(argument("type",IntegerArgumentType.integer(1)) - .suggests( (c, b) -> suggestMatching(new String[]{"square=0","circle=1"},b)) + .suggests( (c, b) -> suggestMatching(new String[]{"square=2","circle=1"},b)) .then(argument("orientation",IntegerArgumentType.integer(1)) - .suggests( (c, b) -> suggestMatching(new String[]{"x=0","y=1","z=2"},b)) + .suggests( (c, b) -> suggestMatching(new String[]{"x=1","y=2","z=3"},b)) .then(argument("block", BlockStateArgumentType.blockState()) .executes((c) -> drawPyramid(c.getSource(), BlockPosArgumentType.getBlockPos(c, "center"), @@ -288,7 +288,7 @@ public class DrawCommand private static int drawCircle(ServerCommandSource source, BlockPos pos, int offset, int radius,BlockStateArgument block, int orientation, Predicate replacement, List list, BlockPos.Mutable mbpos){ int successes=0; - if(orientation==0){ + if(orientation==1){ for(int y=-radius;y<=radius;++y){ for(int z=-radius;z<=radius;++z){ @@ -300,7 +300,7 @@ public class DrawCommand } } - if(orientation==1){ + if(orientation==2){ for(int x=-radius;x<=radius;++x){ for(int z=-radius;z<=radius;++z){ @@ -312,7 +312,7 @@ public class DrawCommand } } - if(orientation==2){ + if(orientation==3){ for(int y=-radius;y<=radius;++y){ for(int x=-radius;x<=radius;++x){ @@ -334,13 +334,13 @@ public class DrawCommand for(int axis1=-radius;axis1<=radius;++axis1){ for(int axis2=-radius;axis2<=radius;++axis2){ - if(orientation==0){ + if(orientation==1){ success+=blockset(source, pos.getX()+offset, pos.getY()+axis1, pos.getZ()+axis2,replacement, list, mbpos, block); } - if(orientation==1){ + if(orientation==2){ success+=blockset(source, pos.getX()+axis1, pos.getY()+offset, pos.getZ()+axis2,replacement, list, mbpos, block); } - if(orientation==2){ + if(orientation==3){ success+=blockset(source, pos.getX()+axis2, pos.getY()+axis1, pos.getZ()+offset,replacement, list, mbpos, block); } } @@ -375,7 +375,7 @@ public class DrawCommand } if(shape==1){ affected+=drawCircle(source, pos, i, (int) Math.round(r), block, orientation, replacement, list, mbpos); - }else if(shape==0){ + }else if(shape==2){ affected+=drawSquare(source, pos, i, (int) Math.round(r), block, orientation, replacement, list, mbpos); } } From 890617c8ba433a50c704517d8c542749f51909ab Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Wed, 22 Apr 2020 11:11:20 +0200 Subject: [PATCH 059/198] Added error messages cos no throw statements available --- src/main/java/carpet/commands/DrawCommand.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index fcc55d82..c37ad9b0 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -366,6 +366,11 @@ public class DrawCommand CarpetSettings.impendingFillSkipUpdates = !CarpetSettings.fillUpdates; int r = radius; + + if(orientation<1||orientation>3){ + Messenger.m(source,"gi Incorrect orientation, 1 for x, 2 for y and 3 for z"); + return 0; + } for(int i =0; i Date: Wed, 22 Apr 2020 12:45:28 +0200 Subject: [PATCH 060/198] made integer reading better --- src/main/java/carpet/script/value/EntityValue.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index 423b88d0..c67a5bdd 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -897,19 +897,17 @@ public class EntityValue extends Value if(!(e instanceof ServerPlayerEntity)){ throw new InternalExpressionException("Cannot change the gamemode of non-player entities"); } - if(v.readInteger()==0){ + + if(NumericValue.asNumber(v).getLong()==0){ ((ServerPlayerEntity) e).setGameMode(GameMode.SURVIVAL); return; - } - if(v.readInteger()==1){ + }else if(NumericValue.asNumber(v).getLong()==1){ ((ServerPlayerEntity) e).setGameMode(GameMode.CREATIVE); return; - } - if(v.readInteger()==3){ + }else if(NumericValue.asNumber(v).getLong()==3){ ((ServerPlayerEntity) e).setGameMode(GameMode.SPECTATOR); return; - } - if(v.readInteger()==2){ + }else if(NumericValue.asNumber(v).getLong()==2){ ((ServerPlayerEntity) e).setGameMode(GameMode.ADVENTURE); return; } From 7740f9dc7f5106aceb5868a9d46332d3a3007871 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Wed, 22 Apr 2020 12:48:27 +0200 Subject: [PATCH 061/198] removed unused import --- src/main/java/carpet/script/value/EntityValue.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index c67a5bdd..4d7d238c 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -4,7 +4,6 @@ import carpet.fakes.EntityInterface; import carpet.fakes.ItemEntityInterface; import carpet.fakes.MobEntityInterface; import carpet.helpers.Tracer; -import carpet.helpers.EntityPlayerActionPack; import carpet.patches.EntityPlayerMPFake; import carpet.script.CarpetContext; import carpet.script.EntityEventsGroup; From 1ab00ef957fbb0fbfc45d5fcba972665a55ffd1f Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 22 Apr 2020 17:08:55 -0300 Subject: [PATCH 062/198] 1.3.20 --- gradle.properties | 2 +- src/main/java/carpet/CarpetSettings.java | 2 +- src/main/resources/fabric.mod.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 4a2d7082..98ac82ca 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ org.gradle.jvmargs=-Xmx1G loader_version=0.7.8+build.188 # Mod Properties - mod_version = 1.3.19+v200415 + mod_version = 1.3.20+v200422 maven_group = carpet archives_base_name = fabric-carpet diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index 963b2eb3..e69647a1 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -33,7 +33,7 @@ import static carpet.settings.RuleCategory.CLIENT; @SuppressWarnings("CanBeFinal") public class CarpetSettings { - public static final String carpetVersion = "1.3.19+v200415"; + public static final String carpetVersion = "1.3.20+v200422"; public static final Logger LOG = LogManager.getLogger(); public static boolean skipGenerationChecks = false; public static boolean impendingFillSkipUpdates = false; diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 758e0adf..61d93fb5 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,7 +1,7 @@ { "schemaVersion": 1, "id": "carpet", - "version": "1.3.19", + "version": "1.3.20", "name": "Carpet Mod in Fabric", "description": "Carpet made out of fabric", From c2e09d48e58686c6738e001755166fb1d405762c Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Fri, 24 Apr 2020 11:12:26 +0200 Subject: [PATCH 063/198] improved definitions COs messing about --- src/main/java/carpet/commands/DrawCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index c37ad9b0..27655836 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -368,7 +368,7 @@ public class DrawCommand int r = radius; if(orientation<1||orientation>3){ - Messenger.m(source,"gi Incorrect orientation, 1 for x, 2 for y and 3 for z"); + Messenger.m(source,"gi Incorrect orientation, must be 1 for x,2 for y or 3 for z"); return 0; } From e5317a6f29b8da244b0cb866453af1cf3fafa639 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Fri, 24 Apr 2020 11:52:18 +0200 Subject: [PATCH 064/198] Very useful indeed --- src/main/java/carpet/script/value/EntityValue.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index a0237460..faa76d40 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -479,6 +479,8 @@ public class EntityValue extends Value return new NBTSerializableValue(nbttagcompound); return new NBTSerializableValue(nbttagcompound).get(a); }); + + put("category",(e,a)->{return new StringValue(e.getType().getCategory().toString());}); }}; public void set(String what, Value toWhat) From 3790889b6d73bf9fd2ae07e071cd35d49be591be Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Fri, 24 Apr 2020 12:02:57 +0200 Subject: [PATCH 065/198] made it lowercase more inkeeping with rest of scarpet Ill remove if u want --- src/main/java/carpet/script/value/EntityValue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index faa76d40..18f0d4f4 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -480,7 +480,7 @@ public class EntityValue extends Value return new NBTSerializableValue(nbttagcompound).get(a); }); - put("category",(e,a)->{return new StringValue(e.getType().getCategory().toString());}); + put("category",(e,a)->{return new StringValue(e.getType().getCategory().toString().toLowerCase());}); }}; public void set(String what, Value toWhat) From e6b4f496de6ae50bf29d4f700bbd88aa59f43afb Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Fri, 24 Apr 2020 12:08:03 +0200 Subject: [PATCH 066/198] took out testing stuff --- src/main/java/carpet/script/value/EntityValue.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index 4d7d238c..012c1647 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -892,7 +892,7 @@ public class EntityValue extends Value throw new InternalExpressionException("'effect' needs either no arguments (clear) or effect name, duration, and optional amplifier, show particles and show icon"); }); - put("gamemode_id", (e,v)->{ + put("gamemode", (e,v)->{ if(!(e instanceof ServerPlayerEntity)){ throw new InternalExpressionException("Cannot change the gamemode of non-player entities"); } @@ -910,7 +910,7 @@ public class EntityValue extends Value ((ServerPlayerEntity) e).setGameMode(GameMode.ADVENTURE); return; } - throw new InternalExpressionException("s"+v.getString()+"s is an invalid gamemode type"); + throw new InternalExpressionException(NumericValue.asNumber(v).getLong()+" is an invalid gamemode id"); }); put("jump",(e,v)->{ From e8946fe9d5c9069fa7d7f4301f6fd128686be3df Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Fri, 24 Apr 2020 12:10:49 +0200 Subject: [PATCH 067/198] changed to switch statement much shorter and less messier --- .../java/carpet/script/value/EntityValue.java | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index 012c1647..090d4402 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -897,18 +897,11 @@ public class EntityValue extends Value throw new InternalExpressionException("Cannot change the gamemode of non-player entities"); } - if(NumericValue.asNumber(v).getLong()==0){ - ((ServerPlayerEntity) e).setGameMode(GameMode.SURVIVAL); - return; - }else if(NumericValue.asNumber(v).getLong()==1){ - ((ServerPlayerEntity) e).setGameMode(GameMode.CREATIVE); - return; - }else if(NumericValue.asNumber(v).getLong()==3){ - ((ServerPlayerEntity) e).setGameMode(GameMode.SPECTATOR); - return; - }else if(NumericValue.asNumber(v).getLong()==2){ - ((ServerPlayerEntity) e).setGameMode(GameMode.ADVENTURE); - return; + switch((int)NumericValue.asNumber(v).getLong()){ + case 0:((ServerPlayerEntity) e).setGameMode(GameMode.SURVIVAL);return; + case 1:((ServerPlayerEntity) e).setGameMode(GameMode.CREATIVE);return; + case 2:((ServerPlayerEntity) e).setGameMode(GameMode.ADVENTURE);return; + case 3:((ServerPlayerEntity) e).setGameMode(GameMode.SPECTATOR);return; } throw new InternalExpressionException(NumericValue.asNumber(v).getLong()+" is an invalid gamemode id"); }); From 367e584e43e34cad8c29fbb3bfbdfa14d556ce95 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Fri, 24 Apr 2020 12:17:07 +0200 Subject: [PATCH 068/198] Now it just continues to jump --- src/main/java/carpet/script/value/EntityValue.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index 090d4402..583fd72d 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -907,10 +907,10 @@ public class EntityValue extends Value }); put("jump",(e,v)->{ - if(!(e instanceof ServerPlayerEntity)){ - throw new InternalExpressionException("Non-player entities can't jump"); + if(!(e instanceof LivingEntity)){ + throw new InternalExpressionException("Non-living entities can't jump"); } - ((PlayerEntity) e).jump(); + ((LivingEntity) e).setJumping(v.getBoolean()); }); // gamemode_id [check](gamemode just wont read string) From 182d34936a971386a8d7a75eba179fcd9f7e83fa Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Fri, 24 Apr 2020 12:26:39 +0200 Subject: [PATCH 069/198] rename to jumpingcm --- src/main/java/carpet/script/value/EntityValue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index 583fd72d..b01489a4 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -906,7 +906,7 @@ public class EntityValue extends Value throw new InternalExpressionException(NumericValue.asNumber(v).getLong()+" is an invalid gamemode id"); }); - put("jump",(e,v)->{ + put("jumping",(e,v)->{ if(!(e instanceof LivingEntity)){ throw new InternalExpressionException("Non-living entities can't jump"); } From 64f760564dee36d5a2635cd0d879a249e92fc28d Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Fri, 24 Apr 2020 13:12:48 +0200 Subject: [PATCH 070/198] added string not case-sensitive --- src/main/java/carpet/script/value/EntityValue.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index b01489a4..82ef8219 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -897,6 +897,13 @@ public class EntityValue extends Value throw new InternalExpressionException("Cannot change the gamemode of non-player entities"); } + switch(v.getString().toLowerCase()){ + case "survival":((ServerPlayerEntity) e).setGameMode(GameMode.SURVIVAL);return; + case "creative":((ServerPlayerEntity) e).setGameMode(GameMode.CREATIVE);return; + case "adventure":((ServerPlayerEntity) e).setGameMode(GameMode.ADVENTURE);return; + case "spectator":((ServerPlayerEntity) e).setGameMode(GameMode.SPECTATOR);return; + } + switch((int)NumericValue.asNumber(v).getLong()){ case 0:((ServerPlayerEntity) e).setGameMode(GameMode.SURVIVAL);return; case 1:((ServerPlayerEntity) e).setGameMode(GameMode.CREATIVE);return; From 6146ff8ed86335b40e8223bfacc42743eaf895e0 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Fri, 24 Apr 2020 13:36:41 +0200 Subject: [PATCH 071/198] Let's see if this works --- .../java/carpet/commands/DrawCommand.java | 65 ++++++++++--------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index 27655836..5df76879 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -8,6 +8,7 @@ import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.arguments.BoolArgumentType; import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.arguments.StringArgumentType; import net.minecraft.block.Block; import net.minecraft.block.pattern.CachedBlockPosition; @@ -78,29 +79,29 @@ public class DrawCommand .then(argument("radius", IntegerArgumentType.integer(1)) .then(argument("height",IntegerArgumentType.integer(1)) .then(argument("pointing up?",BoolArgumentType.bool()) - .then(argument("type",IntegerArgumentType.integer(1)) - .suggests( (c, b) -> suggestMatching(new String[]{"square=2","circle=1"},b)) - .then(argument("orientation",IntegerArgumentType.integer(1)) - .suggests( (c, b) -> suggestMatching(new String[]{"x=1","y=2","z=3"},b)) + .then(argument("type",StringArgumentType.string()) + .suggests( (c, b) -> suggestMatching(new String[]{"square","circle"},b)) + .then(argument("orientation",StringArgumentType.string()) + .suggests( (c, b) -> suggestMatching(new String[]{"x","y","z"},b)) .then(argument("block", BlockStateArgumentType.blockState()) .executes((c) -> drawPyramid(c.getSource(), BlockPosArgumentType.getBlockPos(c, "center"), - IntegerArgumentType.getInteger(c, "type"), + StringArgumentType.getString(c,"type"), IntegerArgumentType.getInteger(c, "radius"), IntegerArgumentType.getInteger(c, "height"), BoolArgumentType.getBool(c,"pointing up?"), - IntegerArgumentType.getInteger(c,"orientation"), + StringArgumentType.getString(c,"orientation"), BlockStateArgumentType.getBlockState(c, "block"), null) ) .then(literal("replace") .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) .executes((c) -> drawPyramid(c.getSource(), BlockPosArgumentType.getBlockPos(c, "center"), - IntegerArgumentType.getInteger(c, "type"), + StringArgumentType.getString(c,"type"), IntegerArgumentType.getInteger(c, "radius"), IntegerArgumentType.getInteger(c, "height"), BoolArgumentType.getBool(c,"pointing up?"), - IntegerArgumentType.getInteger(c,"orientation"), + StringArgumentType.getString(c,"orientation"), BlockStateArgumentType.getBlockState(c, "block"), BlockPredicateArgumentType.getBlockPredicate(c,"filter") ) @@ -285,10 +286,10 @@ public class DrawCommand return 1; } - private static int drawCircle(ServerCommandSource source, BlockPos pos, int offset, int radius,BlockStateArgument block, int orientation, + private static int drawCircle(ServerCommandSource source, BlockPos pos, int offset, int radius,BlockStateArgument block, String orientation, Predicate replacement, List list, BlockPos.Mutable mbpos){ int successes=0; - if(orientation==1){ + if(orientation=="x"){ for(int y=-radius;y<=radius;++y){ for(int z=-radius;z<=radius;++z){ @@ -300,7 +301,7 @@ public class DrawCommand } } - if(orientation==2){ + if(orientation=="y"){ for(int x=-radius;x<=radius;++x){ for(int z=-radius;z<=radius;++z){ @@ -312,7 +313,7 @@ public class DrawCommand } } - if(orientation==3){ + if(orientation=="z"){ for(int y=-radius;y<=radius;++y){ for(int x=-radius;x<=radius;++x){ @@ -327,20 +328,20 @@ public class DrawCommand return successes; } - private static int drawSquare(ServerCommandSource source, BlockPos pos, int offset, int radius, BlockStateArgument block, int orientation, + private static int drawSquare(ServerCommandSource source, BlockPos pos, int offset, int radius, BlockStateArgument block, String orientation, Predicate replacement, List list, BlockPos.Mutable mbpos){ int success=0; for(int axis1=-radius;axis1<=radius;++axis1){ for(int axis2=-radius;axis2<=radius;++axis2){ - if(orientation==1){ + if(orientation=="x"){ success+=blockset(source, pos.getX()+offset, pos.getY()+axis1, pos.getZ()+axis2,replacement, list, mbpos, block); } - if(orientation==2){ + if(orientation=="y"){ success+=blockset(source, pos.getX()+axis1, pos.getY()+offset, pos.getZ()+axis2,replacement, list, mbpos, block); } - if(orientation==3){ + if(orientation=="z"){ success+=blockset(source, pos.getX()+axis2, pos.getY()+axis1, pos.getZ()+offset,replacement, list, mbpos, block); } } @@ -349,13 +350,13 @@ public class DrawCommand return success; } - private static int drawPyramid(ServerCommandSource source, BlockPos pos, int shape, int radius, int height, boolean pointup, int orientation, BlockStateArgument block, + private static int drawPyramid(ServerCommandSource source, BlockPos pos, String shape, int radius, int height, boolean pointup, String orientation, BlockStateArgument block, Predicate replacement) { return (int) drawPyramid(source, pos, radius, height, block, replacement, pointup, orientation, false, shape); } private static double drawPyramid(ServerCommandSource source, BlockPos pos, int radius, int height, BlockStateArgument block, - Predicate replacement, boolean pointup, int orientation, boolean solid, int shape) { + Predicate replacement, boolean pointup, String orientation, boolean solid, String shape) { int affected = 0; BlockPos.Mutable mbpos = new BlockPos.Mutable(pos); @@ -367,24 +368,30 @@ public class DrawCommand int r = radius; - if(orientation<1||orientation>3){ - Messenger.m(source,"gi Incorrect orientation, must be 1 for x,2 for y or 3 for z"); - return 0; + switch (orientation){ + case "x":break; + case "y":break; + case "z":break; + default:{ + Messenger.m(source,"gi Invalid orientation, must be x,y or z"); + return 0; + } } - for(int i =0; i Date: Fri, 24 Apr 2020 14:12:59 +0200 Subject: [PATCH 072/198] I removed the ++i statement and like crashed the world! --- .../java/carpet/commands/DrawCommand.java | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index 5df76879..4b21d68d 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -324,7 +324,6 @@ public class DrawCommand } } } - return successes; } @@ -379,19 +378,25 @@ public class DrawCommand } - for(int i =0; i Date: Fri, 24 Apr 2020 16:19:35 +0200 Subject: [PATCH 073/198] moved everything to switch statement It all works now --- .../java/carpet/commands/DrawCommand.java | 80 +++++-------------- 1 file changed, 19 insertions(+), 61 deletions(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index 4b21d68d..e2ca0bb3 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -289,44 +289,22 @@ public class DrawCommand private static int drawCircle(ServerCommandSource source, BlockPos pos, int offset, int radius,BlockStateArgument block, String orientation, Predicate replacement, List list, BlockPos.Mutable mbpos){ int successes=0; - if(orientation=="x"){ - for(int y=-radius;y<=radius;++y){ + for(int axis1=-radius;axis1<=radius;++axis1){ - for(int z=-radius;z<=radius;++z){ + for(int axis2=-radius;axis2<=radius;++axis2){ - if(y*y+z*z<=radius*radius){ - successes+=blockset(source, pos.getX()+offset, pos.getY()+y, pos.getZ()+z, replacement, list, mbpos, block); - } - } - } - } - - if(orientation=="y"){ - for(int x=-radius;x<=radius;++x){ - - for(int z=-radius;z<=radius;++z){ - - if(x*x+z*z<=radius*radius){ - successes+=blockset(source, pos.getX()+x, pos.getY()+offset, pos.getZ()+z, replacement, list, mbpos, block); - } - } - } - } - - if(orientation=="z"){ - for(int y=-radius;y<=radius;++y){ - - for(int x=-radius;x<=radius;++x){ - - if(y*y+x*x<=radius*radius){ - successes+=blockset(source, pos.getX()+x, pos.getY()+y, pos.getZ()+offset, replacement, list, mbpos, block); + if(axis1*axis1+axis2*axis2<=radius*radius){ + switch (orientation){ + case "x":successes+=blockset(source, pos.getX()+offset, pos.getY()+axis1, pos.getZ()+axis2,replacement, list, mbpos, block);break; + case "y":successes+=blockset(source, pos.getX()+axis1, pos.getY()+offset, pos.getZ()+axis2,replacement, list, mbpos, block);break; + case "z":successes+=blockset(source, pos.getX()+axis2, pos.getY()+axis1, pos.getZ()+offset,replacement, list, mbpos, block);break; + default:Messenger.m(source,"gi Invalid orientation, must be x, y or z");return 0; } } } } return successes; } - private static int drawSquare(ServerCommandSource source, BlockPos pos, int offset, int radius, BlockStateArgument block, String orientation, Predicate replacement, List list, BlockPos.Mutable mbpos){ int success=0; @@ -334,14 +312,11 @@ public class DrawCommand for(int axis1=-radius;axis1<=radius;++axis1){ for(int axis2=-radius;axis2<=radius;++axis2){ - if(orientation=="x"){ - success+=blockset(source, pos.getX()+offset, pos.getY()+axis1, pos.getZ()+axis2,replacement, list, mbpos, block); - } - if(orientation=="y"){ - success+=blockset(source, pos.getX()+axis1, pos.getY()+offset, pos.getZ()+axis2,replacement, list, mbpos, block); - } - if(orientation=="z"){ - success+=blockset(source, pos.getX()+axis2, pos.getY()+axis1, pos.getZ()+offset,replacement, list, mbpos, block); + switch (orientation){ + case "x":success+=blockset(source, pos.getX()+offset, pos.getY()+axis1, pos.getZ()+axis2,replacement, list, mbpos, block);break; + case "y":success+=blockset(source, pos.getX()+axis1, pos.getY()+offset, pos.getZ()+axis2,replacement, list, mbpos, block);break; + case "z":success+=blockset(source, pos.getX()+axis2, pos.getY()+axis1, pos.getZ()+offset,replacement, list, mbpos, block);break; + default:Messenger.m(source,"gi Invalid orientation, must be x, y or z");return 0; } } } @@ -366,17 +341,6 @@ public class DrawCommand CarpetSettings.impendingFillSkipUpdates = !CarpetSettings.fillUpdates; int r = radius; - - switch (orientation){ - case "x":break; - case "y":break; - case "z":break; - default:{ - Messenger.m(source,"gi Invalid orientation, must be x,y or z"); - return 0; - } - } - for(int i =0; i Date: Fri, 24 Apr 2020 16:29:40 +0200 Subject: [PATCH 074/198] Updatd docs --- docs/scarpet/Full.md | 13 +++++++++++++ docs/scarpet/api/Entities.md | 13 +++++++++++++ 2 files changed, 26 insertions(+) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index 45d8eb9e..0290668a 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -2712,6 +2712,19 @@ and `true`. If no duration is specified, or it is null or 0, the effect is remov Sets AI to stay around the home position, within `distance` blocks from it. `distance` defaults to 16 blocks. `null` removes it. _May_ not work fully with mobs that have this AI built in, like Villagers. +### `modify(e, 'gamemode', gamemode?), modify(e, 'gamemode',gamemode_id?)` + +Modifies gamemode of player to whatever string (case-insensitive) or number you put in. + +* 0: survival +* 1: creative +* 2: adventure +* 3: spectator + +### `modify(e, 'jumping', true/false?)` + +Will make the entity constantly jump if set to true, and will stop the entity from jumping if set to false. No current way to make it jump once only. + ## Entity Events There is a number of events that happen to entities that you can attach your own code to in the form of event handlers. diff --git a/docs/scarpet/api/Entities.md b/docs/scarpet/api/Entities.md index 3bd7634f..a6555441 100644 --- a/docs/scarpet/api/Entities.md +++ b/docs/scarpet/api/Entities.md @@ -455,6 +455,19 @@ and `true`. If no duration is specified, or it is null or 0, the effect is remov Sets AI to stay around the home position, within `distance` blocks from it. `distance` defaults to 16 blocks. `null` removes it. _May_ not work fully with mobs that have this AI built in, like Villagers. +### `modify(e, 'gamemode', gamemode?), modify(e, 'gamemode',gamemode_id?)` + +Modifies gamemode of player to whatever string (case-insensitive) or number you put in. + +* 0: survival +* 1: creative +* 2: adventure +* 3: spectator + +### `modify(e, 'jumping', true/false?)` + +Will make the entity constantly jump if set to true, and will stop the entity from jumping if set to false. No current way to make it jump once only. + ## Entity Events There is a number of events that happen to entities that you can attach your own code to in the form of event handlers. From c8f31a3f891be7d52016ddab0c99d9e4cce89bcc Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Fri, 24 Apr 2020 16:35:07 +0200 Subject: [PATCH 075/198] added to docs --- docs/scarpet/Full.md | 3 +++ docs/scarpet/api/Entities.md | 3 +++ 2 files changed, 6 insertions(+) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index 45d8eb9e..68206456 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -2532,6 +2532,9 @@ Returns `null` if the argument is not a player, otherwise: * `shadow`: any carpet-shadowed real player * `realms`: ? +### `query(e, 'category')` +Returns a lowercase string containing the category of the entity (hostile, passive, water, ambient, misc) + ### `query(e, 'team')` Team name for entity, or `null` if no team is assigned. diff --git a/docs/scarpet/api/Entities.md b/docs/scarpet/api/Entities.md index 3bd7634f..9b808752 100644 --- a/docs/scarpet/api/Entities.md +++ b/docs/scarpet/api/Entities.md @@ -275,6 +275,9 @@ Returns `null` if the argument is not a player, otherwise: * `shadow`: any carpet-shadowed real player * `realms`: ? +### `query(e, 'category')` +Returns a lowercase string containing the category of the entity (hostile, passive, water, ambient, misc) + ### `query(e, 'team')` Team name for entity, or `null` if no team is assigned. From 4f6ebb49271f8f096676586d18c44fdaaef8ed18 Mon Sep 17 00:00:00 2001 From: gnembon <41132274+gnembon@users.noreply.github.com> Date: Sat, 25 Apr 2020 16:23:59 -0400 Subject: [PATCH 076/198] Update src/main/java/carpet/script/value/EntityValue.java Added locale --- src/main/java/carpet/script/value/EntityValue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index 18f0d4f4..3ec78696 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -480,7 +480,7 @@ public class EntityValue extends Value return new NBTSerializableValue(nbttagcompound).get(a); }); - put("category",(e,a)->{return new StringValue(e.getType().getCategory().toString().toLowerCase());}); + put("category",(e,a)->{return new StringValue(e.getType().getCategory().toString().toLowerCase(Locale.ROOT));}); }}; public void set(String what, Value toWhat) From c255e6f33010951af17fe8a789985e896b7d2900 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Sun, 26 Apr 2020 11:25:22 +0200 Subject: [PATCH 077/198] changed to return null instead of throwing exception --- src/main/java/carpet/script/value/EntityValue.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index 82ef8219..a7f4fc29 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -894,7 +894,7 @@ public class EntityValue extends Value put("gamemode", (e,v)->{ if(!(e instanceof ServerPlayerEntity)){ - throw new InternalExpressionException("Cannot change the gamemode of non-player entities"); + return; } switch(v.getString().toLowerCase()){ @@ -910,7 +910,7 @@ public class EntityValue extends Value case 2:((ServerPlayerEntity) e).setGameMode(GameMode.ADVENTURE);return; case 3:((ServerPlayerEntity) e).setGameMode(GameMode.SPECTATOR);return; } - throw new InternalExpressionException(NumericValue.asNumber(v).getLong()+" is an invalid gamemode id"); + return; }); put("jumping",(e,v)->{ From 63a49f0386241132ae94b67a1e3f0780989298f0 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Sun, 26 Apr 2020 11:34:12 +0200 Subject: [PATCH 078/198] no need for that --- src/main/java/carpet/script/value/EntityValue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index a7f4fc29..7e2cb392 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -920,7 +920,7 @@ public class EntityValue extends Value ((LivingEntity) e).setJumping(v.getBoolean()); }); - // gamemode_id [check](gamemode just wont read string) + // gamemode [check] // spectate [check] // "fire" [] // "extinguish" [] From cdfce6f0050abe0a41661bf02d0af19c7d74ec41 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Sun, 26 Apr 2020 11:34:49 +0200 Subject: [PATCH 079/198] not throwing exception --- src/main/java/carpet/script/value/EntityValue.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index 7e2cb392..59ebc428 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -914,9 +914,8 @@ public class EntityValue extends Value }); put("jumping",(e,v)->{ - if(!(e instanceof LivingEntity)){ - throw new InternalExpressionException("Non-living entities can't jump"); - } + if(!(e instanceof LivingEntity)) return; + ((LivingEntity) e).setJumping(v.getBoolean()); }); From 2873494f5c99c7cc1fc771f649762885f7f998b5 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Sun, 26 Apr 2020 12:03:14 +0200 Subject: [PATCH 080/198] Most convoluted way of doing things --- .../java/carpet/script/value/EntityValue.java | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index 59ebc428..38a9a86a 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -10,6 +10,7 @@ import carpet.script.EntityEventsGroup; import carpet.script.exception.InternalExpressionException; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.entity.effect.StatusEffects; import net.minecraft.network.packet.s2c.play.EntityPassengersSetS2CPacket; import net.minecraft.network.packet.s2c.play.EntityPositionS2CPacket; import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket; @@ -875,7 +876,7 @@ public class EntityValue extends Value { le.removeStatusEffect(effect); return; - } + } int amplifier = 0; if (lv.size() > 2) amplifier = (int)NumericValue.asNumber(lv.get(2)).getLong(); @@ -896,7 +897,7 @@ public class EntityValue extends Value if(!(e instanceof ServerPlayerEntity)){ return; } - + switch(v.getString().toLowerCase()){ case "survival":((ServerPlayerEntity) e).setGameMode(GameMode.SURVIVAL);return; case "creative":((ServerPlayerEntity) e).setGameMode(GameMode.CREATIVE);return; @@ -919,6 +920,27 @@ public class EntityValue extends Value ((LivingEntity) e).setJumping(v.getBoolean()); }); + put("jump",(e,v)->{//Most *REDACTED* up code in the world + + float m = e.world.getBlockState(new BlockPos(e)).getBlock().getJumpVelocityMultiplier(); + float g = e.world.getBlockState(new BlockPos(e.getX(), e.getBoundingBox().y1 - 0.5000001D, e.getZ())).getBlock().getJumpVelocityMultiplier(); + float JumpVelocityMultiplier= (double)m == 1.0D ? g : m; + + float f = (0.42F * JumpVelocityMultiplier); + if (((LivingEntity)e).hasStatusEffect(StatusEffects.JUMP_BOOST)) { + f += 0.1F * (float)(((LivingEntity)e).getStatusEffect(StatusEffects.JUMP_BOOST).getAmplifier() + 1); + } + + Vec3d vec3d = e.getVelocity(); + e.setVelocity(vec3d.x, (double)f, vec3d.z); + if (e.isSprinting()) { + float u = e.yaw * 0.017453292F; + e.setVelocity(e.getVelocity().add((double)(-MathHelper.sin(g) * 0.2F), 0.0D, (double)(MathHelper.cos(u) * 0.2F))); + } + + e.velocityDirty = true; + }); + // gamemode [check] // spectate [check] // "fire" [] From 7c620a83bb110448c466b7b2d30a50fc31554fc9 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Sun, 26 Apr 2020 12:18:03 +0200 Subject: [PATCH 081/198] changed docs --- docs/scarpet/Full.md | 6 +++++- docs/scarpet/api/Entities.md | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index 0290668a..3b944c5d 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -2723,7 +2723,11 @@ Modifies gamemode of player to whatever string (case-insensitive) or number you ### `modify(e, 'jumping', true/false?)` -Will make the entity constantly jump if set to true, and will stop the entity from jumping if set to false. No current way to make it jump once only. +Will make the entity constantly jump if set to true, and will stop the entity from jumping if set to false. + +### `modify(e, 'jump'))` + +Will make the entity jump once only ## Entity Events diff --git a/docs/scarpet/api/Entities.md b/docs/scarpet/api/Entities.md index a6555441..65f69f51 100644 --- a/docs/scarpet/api/Entities.md +++ b/docs/scarpet/api/Entities.md @@ -466,7 +466,11 @@ Modifies gamemode of player to whatever string (case-insensitive) or number you ### `modify(e, 'jumping', true/false?)` -Will make the entity constantly jump if set to true, and will stop the entity from jumping if set to false. No current way to make it jump once only. +Will make the entity constantly jump if set to true, and will stop the entity from jumping if set to false. + +### `modify(e, 'jump'))` + +Will make the entity jump once only ## Entity Events From aba2d605c807a8b5f9351232b589e3a6eccbe851 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Sun, 26 Apr 2020 12:25:49 +0200 Subject: [PATCH 082/198] removing unnecessary stuff cos Idea told me to --- .../java/carpet/script/value/EntityValue.java | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index 38a9a86a..fbe5a8c4 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -899,19 +899,18 @@ public class EntityValue extends Value } switch(v.getString().toLowerCase()){ - case "survival":((ServerPlayerEntity) e).setGameMode(GameMode.SURVIVAL);return; - case "creative":((ServerPlayerEntity) e).setGameMode(GameMode.CREATIVE);return; - case "adventure":((ServerPlayerEntity) e).setGameMode(GameMode.ADVENTURE);return; - case "spectator":((ServerPlayerEntity) e).setGameMode(GameMode.SPECTATOR);return; + case "survival":((ServerPlayerEntity) e).setGameMode(GameMode.SURVIVAL);break; + case "creative":((ServerPlayerEntity) e).setGameMode(GameMode.CREATIVE);break; + case "adventure":((ServerPlayerEntity) e).setGameMode(GameMode.ADVENTURE);break; + case "spectator":((ServerPlayerEntity) e).setGameMode(GameMode.SPECTATOR);break; } switch((int)NumericValue.asNumber(v).getLong()){ - case 0:((ServerPlayerEntity) e).setGameMode(GameMode.SURVIVAL);return; - case 1:((ServerPlayerEntity) e).setGameMode(GameMode.CREATIVE);return; - case 2:((ServerPlayerEntity) e).setGameMode(GameMode.ADVENTURE);return; - case 3:((ServerPlayerEntity) e).setGameMode(GameMode.SPECTATOR);return; + case 0:((ServerPlayerEntity) e).setGameMode(GameMode.SURVIVAL);break; + case 1:((ServerPlayerEntity) e).setGameMode(GameMode.CREATIVE);break; + case 2:((ServerPlayerEntity) e).setGameMode(GameMode.ADVENTURE);break; + case 3:((ServerPlayerEntity) e).setGameMode(GameMode.SPECTATOR);break; } - return; }); put("jumping",(e,v)->{ @@ -932,10 +931,10 @@ public class EntityValue extends Value } Vec3d vec3d = e.getVelocity(); - e.setVelocity(vec3d.x, (double)f, vec3d.z); + e.setVelocity(vec3d.x, f, vec3d.z); if (e.isSprinting()) { float u = e.yaw * 0.017453292F; - e.setVelocity(e.getVelocity().add((double)(-MathHelper.sin(g) * 0.2F), 0.0D, (double)(MathHelper.cos(u) * 0.2F))); + e.setVelocity(e.getVelocity().add((-MathHelper.sin(g) * 0.2F), 0.0D, (MathHelper.cos(u) * 0.2F))); } e.velocityDirty = true; From e1c87126562c92020ad1e92b7f6931a616582a79 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Mon, 27 Apr 2020 09:07:44 +0200 Subject: [PATCH 083/198] best way I could think of doing this --- .../java/carpet/script/value/EntityValue.java | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index fbe5a8c4..32c9967e 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -897,19 +897,11 @@ public class EntityValue extends Value if(!(e instanceof ServerPlayerEntity)){ return; } - switch(v.getString().toLowerCase()){ - case "survival":((ServerPlayerEntity) e).setGameMode(GameMode.SURVIVAL);break; - case "creative":((ServerPlayerEntity) e).setGameMode(GameMode.CREATIVE);break; - case "adventure":((ServerPlayerEntity) e).setGameMode(GameMode.ADVENTURE);break; - case "spectator":((ServerPlayerEntity) e).setGameMode(GameMode.SPECTATOR);break; - } - - switch((int)NumericValue.asNumber(v).getLong()){ - case 0:((ServerPlayerEntity) e).setGameMode(GameMode.SURVIVAL);break; - case 1:((ServerPlayerEntity) e).setGameMode(GameMode.CREATIVE);break; - case 2:((ServerPlayerEntity) e).setGameMode(GameMode.ADVENTURE);break; - case 3:((ServerPlayerEntity) e).setGameMode(GameMode.SPECTATOR);break; + case "survival": case "0":((ServerPlayerEntity) e).setGameMode(GameMode.SURVIVAL);break; + case "creative": case "1":((ServerPlayerEntity) e).setGameMode(GameMode.CREATIVE);break; + case "adventure": case "2":((ServerPlayerEntity) e).setGameMode(GameMode.ADVENTURE);break; + case "spectator": case "3":((ServerPlayerEntity) e).setGameMode(GameMode.SPECTATOR);break; } }); From a19e759039cb5c5e680de9a30c30bc72a93abcd7 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Mon, 27 Apr 2020 09:30:31 +0200 Subject: [PATCH 084/198] added jump method to MobAi.java My justification: https://github.com/gnembon/fabric-carpet/pull/241#discussion_r415576459 --- .../java/carpet/script/value/EntityValue.java | 20 ++------------- src/main/java/carpet/utils/MobAI.java | 25 +++++++++++++++++++ 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index 32c9967e..be53b844 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -62,6 +62,7 @@ import java.util.function.Predicate; import java.util.stream.Collectors; import static carpet.script.value.NBTSerializableValue.nameFromRegistryId; +import static carpet.utils.MobAI.jump; // TODO: decide whether copy(entity) should duplicate entity in the world. public class EntityValue extends Value @@ -912,24 +913,7 @@ public class EntityValue extends Value }); put("jump",(e,v)->{//Most *REDACTED* up code in the world - - float m = e.world.getBlockState(new BlockPos(e)).getBlock().getJumpVelocityMultiplier(); - float g = e.world.getBlockState(new BlockPos(e.getX(), e.getBoundingBox().y1 - 0.5000001D, e.getZ())).getBlock().getJumpVelocityMultiplier(); - float JumpVelocityMultiplier= (double)m == 1.0D ? g : m; - - float f = (0.42F * JumpVelocityMultiplier); - if (((LivingEntity)e).hasStatusEffect(StatusEffects.JUMP_BOOST)) { - f += 0.1F * (float)(((LivingEntity)e).getStatusEffect(StatusEffects.JUMP_BOOST).getAmplifier() + 1); - } - - Vec3d vec3d = e.getVelocity(); - e.setVelocity(vec3d.x, f, vec3d.z); - if (e.isSprinting()) { - float u = e.yaw * 0.017453292F; - e.setVelocity(e.getVelocity().add((-MathHelper.sin(g) * 0.2F), 0.0D, (MathHelper.cos(u) * 0.2F))); - } - - e.velocityDirty = true; + jump((LivingEntity)e); }); // gamemode [check] diff --git a/src/main/java/carpet/utils/MobAI.java b/src/main/java/carpet/utils/MobAI.java index 0a202b16..ff01c0e0 100644 --- a/src/main/java/carpet/utils/MobAI.java +++ b/src/main/java/carpet/utils/MobAI.java @@ -4,7 +4,12 @@ import carpet.CarpetServer; import com.google.common.collect.Sets; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.effect.StatusEffects; import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.registry.Registry; import java.util.HashMap; @@ -93,4 +98,24 @@ public class MobAI } } + public static void jump(LivingEntity e){ + float m = e.world.getBlockState(new BlockPos(e)).getBlock().getJumpVelocityMultiplier(); + float g = e.world.getBlockState(new BlockPos(e.getX(), e.getBoundingBox().y1 - 0.5000001D, e.getZ())).getBlock().getJumpVelocityMultiplier(); + float JumpVelocityMultiplier= (double)m == 1.0D ? g : m; + + float f = (0.42F * JumpVelocityMultiplier); + if (e.hasStatusEffect(StatusEffects.JUMP_BOOST)) { + f += 0.1F * (float)(e.getStatusEffect(StatusEffects.JUMP_BOOST).getAmplifier() + 1); + } + + Vec3d vec3d = e.getVelocity(); + e.setVelocity(vec3d.x, f, vec3d.z); + if (e.isSprinting()) { + float u = e.yaw * 0.017453292F; + e.setVelocity(e.getVelocity().add((-MathHelper.sin(g) * 0.2F), 0.0D, (MathHelper.cos(u) * 0.2F))); + } + + e.velocityDirty = true; + } + } From 8ea79b5837dadedcd0790584ab3bbc81d561ec0a Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Mon, 27 Apr 2020 09:41:24 +0200 Subject: [PATCH 085/198] moved the swearing very important business, swearing... --- src/main/java/carpet/utils/MobAI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/carpet/utils/MobAI.java b/src/main/java/carpet/utils/MobAI.java index ff01c0e0..77c4fd94 100644 --- a/src/main/java/carpet/utils/MobAI.java +++ b/src/main/java/carpet/utils/MobAI.java @@ -98,7 +98,7 @@ public class MobAI } } - public static void jump(LivingEntity e){ + public static void jump(LivingEntity e){//Most *REDACTED* up code in the world float m = e.world.getBlockState(new BlockPos(e)).getBlock().getJumpVelocityMultiplier(); float g = e.world.getBlockState(new BlockPos(e.getX(), e.getBoundingBox().y1 - 0.5000001D, e.getZ())).getBlock().getJumpVelocityMultiplier(); float JumpVelocityMultiplier= (double)m == 1.0D ? g : m; From 332c04dd934538ec86ef44efdc4cd828e8dda646 Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Mon, 27 Apr 2020 09:46:17 +0200 Subject: [PATCH 086/198] added silent, gravity, fire and age cos i was bored, and I also checked it off for u --- docs/scarpet/Full.md | 11 ++++++ docs/scarpet/api/Entities.md | 12 ++++++- .../java/carpet/script/value/EntityValue.java | 34 +++++++++++++++---- 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index 3b944c5d..c6e69326 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -2729,6 +2729,17 @@ Will make the entity constantly jump if set to true, and will stop the entity fr Will make the entity jump once only +### `modify(e, 'silent', true/false)` + +### `modify(e, 'gravity', true/false)` + +### `modify(e, 'fire', ticks)` + +Will set mob on fire for `ticks` ticks. Set to 0 to extinguish. + +### `modify(e, 'age', age)` + + ## Entity Events There is a number of events that happen to entities that you can attach your own code to in the form of event handlers. diff --git a/docs/scarpet/api/Entities.md b/docs/scarpet/api/Entities.md index 65f69f51..659acc2a 100644 --- a/docs/scarpet/api/Entities.md +++ b/docs/scarpet/api/Entities.md @@ -464,7 +464,7 @@ Modifies gamemode of player to whatever string (case-insensitive) or number you * 2: adventure * 3: spectator -### `modify(e, 'jumping', true/false?)` +### `modify(e, 'jumping', true/false)` Will make the entity constantly jump if set to true, and will stop the entity from jumping if set to false. @@ -472,6 +472,16 @@ Will make the entity constantly jump if set to true, and will stop the entity fr Will make the entity jump once only +### `modify(e, 'silent', true/false)` + +### `modify(e, 'gravity', true/false)` + +### `modify(e, 'fire', ticks)` + +Will set mob on fire for `ticks` ticks. Set to 0 to extinguish. + +### `modify(e, 'age', age)` + ## Entity Events There is a number of events that happen to entities that you can attach your own code to in the form of event handlers. diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index be53b844..f09b6cd9 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -912,21 +912,41 @@ public class EntityValue extends Value ((LivingEntity) e).setJumping(v.getBoolean()); }); - put("jump",(e,v)->{//Most *REDACTED* up code in the world + put("jump",(e,v)->{ jump((LivingEntity)e); }); + put("silent",(e,v)->{ + e.setSilent(v.getBoolean()); + }); + + put("gravity",(e,v)->{ + e.setNoGravity(!v.getBoolean()); + }); + + put("invulnerable",(e,v)->{ + e.setInvulnerable(v.getBoolean()); + }); + + put("fire",(e,v)->{ + e.setFireTicks((int)NumericValue.asNumber(v).getLong()); + }); + + put("age",(e,v)->{ + e.age=(int)NumericValue.asNumber(v).getLong(); + }); + // gamemode [check] // spectate [check] - // "fire" [] - // "extinguish" [] - // "silent" [] - // "gravity" [] - // "invulnerable" [] + // "fire" [check] + // "extinguish" [set fire ticks to 0] + // "silent" [check] + // "gravity" [check] + // "invulnerable" [check] // "dimension" [] // "item" [] // "count", [] - // "age", [] + // "age", [check] // "effect_"name [] // "hold" [inventory_set?] // "hold_offhand" [inventory_set?] From 049e44887f7ebbbf7e8a73f5408537d2710ba0dd Mon Sep 17 00:00:00 2001 From: Nameless-123 <53367549+Nameless-123@users.noreply.github.com> Date: Mon, 27 Apr 2020 09:50:51 +0200 Subject: [PATCH 087/198] removed unused import --- src/main/java/carpet/script/value/EntityValue.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index f09b6cd9..840568c1 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -10,7 +10,6 @@ import carpet.script.EntityEventsGroup; import carpet.script.exception.InternalExpressionException; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; -import net.minecraft.entity.effect.StatusEffects; import net.minecraft.network.packet.s2c.play.EntityPassengersSetS2CPacket; import net.minecraft.network.packet.s2c.play.EntityPositionS2CPacket; import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket; From 30dd0217037ccaa42d3baf7bd1c73a0f7dda4d90 Mon Sep 17 00:00:00 2001 From: gnembon Date: Mon, 27 Apr 2020 16:10:34 -0300 Subject: [PATCH 088/198] incorrect monitoring of player movement --- .../java/carpet/mixins/ServerPlayNetworkHandler_tickMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/carpet/mixins/ServerPlayNetworkHandler_tickMixin.java b/src/main/java/carpet/mixins/ServerPlayNetworkHandler_tickMixin.java index 7b6ec9f2..167e80aa 100644 --- a/src/main/java/carpet/mixins/ServerPlayNetworkHandler_tickMixin.java +++ b/src/main/java/carpet/mixins/ServerPlayNetworkHandler_tickMixin.java @@ -40,7 +40,7 @@ public class ServerPlayNetworkHandler_tickMixin { if (Math.abs(p.getX(player.getX()) - lastTickX) > 0.0001D || Math.abs(p.getY(player.getY()) - lastTickY) > 0.0001D - || Math.abs(p.getY(player.getZ()) - lastTickZ) > 0.0001D) + || Math.abs(p.getZ(player.getZ()) - lastTickZ) > 0.0001D) { TickSpeed.reset_player_active_timeout(); } From 291268c14f2b912cecde984cef457284391fdefe Mon Sep 17 00:00:00 2001 From: gnembon Date: Mon, 27 Apr 2020 18:05:08 -0300 Subject: [PATCH 089/198] reset tick rate when changing worlds in SP --- src/main/java/carpet/CarpetServer.java | 1 + src/main/java/carpet/helpers/TickSpeed.java | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/main/java/carpet/CarpetServer.java b/src/main/java/carpet/CarpetServer.java index 7f471737..554a4ca1 100644 --- a/src/main/java/carpet/CarpetServer.java +++ b/src/main/java/carpet/CarpetServer.java @@ -118,6 +118,7 @@ public class CarpetServer // static for now - easier to handle all around the co if (scriptServer != null) scriptServer.onClose(); settingsManager.detachServer(); LoggerRegistry.stopLoggers(); + TickSpeed.reset(); extensions.forEach(e -> e.onServerClosed(server)); minecraft_server = null; } diff --git a/src/main/java/carpet/helpers/TickSpeed.java b/src/main/java/carpet/helpers/TickSpeed.java index 2daf4fd1..33d735b7 100644 --- a/src/main/java/carpet/helpers/TickSpeed.java +++ b/src/main/java/carpet/helpers/TickSpeed.java @@ -44,6 +44,24 @@ public class TickSpeed } } + public static void reset() + { + tickrate = 20.0f; + mspt = 50.0f; + time_bias = 0; + time_warp_start_time = 0; + time_warp_scheduled_ticks = 0; + time_advancerer = null; + tick_warp_callback = null; + tick_warp_sender = null; + player_active_timeout = 0; + process_entities = true; + deepFreeze = false; + is_paused = false; + is_superHot = false; + notifyTickrateListeners("carpet"); + } + public static void add_ticks_to_run_in_pause(int ticks) { player_active_timeout = PLAYER_GRACE+ticks; From c6efb4219554b8eb2dc2f5330dc9ddaa604bfce2 Mon Sep 17 00:00:00 2001 From: gnembon Date: Mon, 27 Apr 2020 19:55:01 -0300 Subject: [PATCH 090/198] fixed position correction packets for superhot --- .../ServerPlayNetworkHandler_tickMixin.java | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/main/java/carpet/mixins/ServerPlayNetworkHandler_tickMixin.java b/src/main/java/carpet/mixins/ServerPlayNetworkHandler_tickMixin.java index 167e80aa..919fc3ad 100644 --- a/src/main/java/carpet/mixins/ServerPlayNetworkHandler_tickMixin.java +++ b/src/main/java/carpet/mixins/ServerPlayNetworkHandler_tickMixin.java @@ -31,6 +31,10 @@ public class ServerPlayNetworkHandler_tickMixin } } + // to skip reposition adjustment check + private static long lastMovedTick = 0L; + private static double lastMoved = 0.0D; + @Inject(method = "onPlayerMove", at = @At( value = "INVOKE", target = "Lnet/minecraft/server/network/ServerPlayerEntity;isSleeping()Z", @@ -38,10 +42,23 @@ public class ServerPlayNetworkHandler_tickMixin )) private void checkMove(PlayerMoveC2SPacket p, CallbackInfo ci) { - if (Math.abs(p.getX(player.getX()) - lastTickX) > 0.0001D - || Math.abs(p.getY(player.getY()) - lastTickY) > 0.0001D - || Math.abs(p.getZ(player.getZ()) - lastTickZ) > 0.0001D) + double movedBy = player.getPos().squaredDistanceTo(lastTickX, lastTickY, lastTickZ); + if (movedBy == 0.0D) return; + // corrective tick + if (movedBy < 0.0009 && lastMoved > 0.0009 && Math.abs(player.getServer().getTicks()-lastMovedTick-20)<2) { + //CarpetSettings.LOG.error("Corrective movement packet"); + return; + } + if (movedBy > 0.0D) + { + //CarpetSettings.LOG.error(String.format( + // "moved by %.6f at %d", + // player.getPos().squaredDistanceTo(lastTickX, lastTickY, lastTickZ), + // player.getServer().getTicks()-lastMovedTick + //)); + lastMoved = movedBy; + lastMovedTick = player.getServer().getTicks(); TickSpeed.reset_player_active_timeout(); } } From 5542a46b430eda126c09c2d123562f9375d922a0 Mon Sep 17 00:00:00 2001 From: gnembon Date: Tue, 28 Apr 2020 00:03:39 -0300 Subject: [PATCH 091/198] First, not second --- src/main/java/carpet/script/Expression.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index b441ec71..daf0a4cf 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -1131,7 +1131,7 @@ public class Expression { Value rval= lv.get(0).evalValue(c); if (!(rval instanceof AbstractListValue)) - throw new InternalExpressionException("Second argument of 'for' function should be a list or iterator"); + throw new InternalExpressionException("First argument of 'for' function should be a list or iterator"); Iterator iterator = ((AbstractListValue) rval).iterator(); LazyValue expr = lv.get(1); //scoping From 714bf1ce1958fc42f91f22cb9122d23abdbf4a64 Mon Sep 17 00:00:00 2001 From: gnembon Date: Tue, 28 Apr 2020 02:55:26 -0300 Subject: [PATCH 092/198] refactor and fix new draw shapes --- .../java/carpet/commands/DrawCommand.java | 459 +++++++++--------- 1 file changed, 238 insertions(+), 221 deletions(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index e2ca0bb3..ed53dfb5 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -6,10 +6,12 @@ import carpet.utils.Messenger; import com.google.common.collect.Lists; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import com.mojang.brigadier.arguments.BoolArgumentType; import com.mojang.brigadier.arguments.IntegerArgumentType; import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.block.Block; import net.minecraft.block.pattern.CachedBlockPosition; import net.minecraft.server.command.ServerCommandSource; @@ -17,11 +19,11 @@ import net.minecraft.command.arguments.BlockPosArgumentType; import net.minecraft.command.arguments.BlockPredicateArgumentType; import net.minecraft.command.arguments.BlockStateArgument; import net.minecraft.command.arguments.BlockStateArgumentType; -import static net.minecraft.server.command.CommandSource.suggestMatching; import net.minecraft.inventory.Inventory; import net.minecraft.block.entity.BlockEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.MathHelper; import java.util.List; import java.util.function.Predicate; @@ -29,6 +31,7 @@ import java.lang.Math; import static net.minecraft.server.command.CommandManager.argument; import static net.minecraft.server.command.CommandManager.literal; +import static net.minecraft.server.command.CommandSource.suggestMatching; public class DrawCommand { @@ -37,103 +40,130 @@ public class DrawCommand LiteralArgumentBuilder command = literal("draw"). requires((player) -> SettingsManager.canUseCommand(player, CarpetSettings.commandDraw)). then(literal("sphere"). - then(argument("center", BlockPosArgumentType.blockPos()). - then(argument("radius", IntegerArgumentType.integer(1)). - then(argument("block", BlockStateArgumentType.blockState()). - executes((c) -> drawSphere(c.getSource(), - BlockPosArgumentType.getBlockPos(c, "center"), - IntegerArgumentType.getInteger(c, "radius"), - BlockStateArgumentType.getBlockState(c, "block"), null)) - .then(literal("replace") - .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) - .executes((c) -> drawSphere(c.getSource(), - BlockPosArgumentType.getBlockPos(c, "center"), - IntegerArgumentType.getInteger(c, "radius"), - BlockStateArgumentType.getBlockState(c, "block"), - BlockPredicateArgumentType.getBlockPredicate(c, - "filter"))))))))) - .then(literal("diamond").then(argument("center", BlockPosArgumentType.blockPos()) - .then(argument("radius", IntegerArgumentType.integer(1)) - .then(argument("block", BlockStateArgumentType.blockState()) - .executes((c) -> drawDiamond(c.getSource(), - BlockPosArgumentType.getBlockPos(c, "center"), - IntegerArgumentType.getInteger(c, "radius"), - BlockStateArgumentType.getBlockState(c, "block"), null)) - .then(literal("replace") - .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) - .executes((c) -> drawDiamond(c.getSource(), - BlockPosArgumentType.getBlockPos(c, "center"), - IntegerArgumentType.getInteger(c, "radius"), - BlockStateArgumentType.getBlockState(c, "block"), - BlockPredicateArgumentType.getBlockPredicate(c,"filter") - ) - ) - ) - ) - ) - ) - ) - ) - .then(literal("pyramid") - .then(argument("center", BlockPosArgumentType.blockPos()) - .then(argument("radius", IntegerArgumentType.integer(1)) - .then(argument("height",IntegerArgumentType.integer(1)) - .then(argument("pointing up?",BoolArgumentType.bool()) - .then(argument("type",StringArgumentType.string()) - .suggests( (c, b) -> suggestMatching(new String[]{"square","circle"},b)) - .then(argument("orientation",StringArgumentType.string()) - .suggests( (c, b) -> suggestMatching(new String[]{"x","y","z"},b)) - .then(argument("block", BlockStateArgumentType.blockState()) - .executes((c) -> drawPyramid(c.getSource(), - BlockPosArgumentType.getBlockPos(c, "center"), - StringArgumentType.getString(c,"type"), - IntegerArgumentType.getInteger(c, "radius"), - IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c,"pointing up?"), - StringArgumentType.getString(c,"orientation"), - BlockStateArgumentType.getBlockState(c, "block"), null) - ) - .then(literal("replace") - .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) - .executes((c) -> drawPyramid(c.getSource(), - BlockPosArgumentType.getBlockPos(c, "center"), - StringArgumentType.getString(c,"type"), - IntegerArgumentType.getInteger(c, "radius"), - IntegerArgumentType.getInteger(c, "height"), - BoolArgumentType.getBool(c,"pointing up?"), - StringArgumentType.getString(c,"orientation"), - BlockStateArgumentType.getBlockState(c, "block"), - BlockPredicateArgumentType.getBlockPredicate(c,"filter") - ) - ) - ) - ) - ) - ) - ) - ) - ) - ) - ) - ); + then(argument("center", BlockPosArgumentType.blockPos()). + then(argument("radius", IntegerArgumentType.integer(1)). + then(drawShape(c -> DrawCommand.drawSphere(c, false)))))). + then(literal("ball"). + then(argument("center", BlockPosArgumentType.blockPos()). + then(argument("radius", IntegerArgumentType.integer(1)). + then(drawShape(c -> DrawCommand.drawSphere(c, true)))))). + then(literal("diamond"). + then(argument("center", BlockPosArgumentType.blockPos()). + then(argument("radius", IntegerArgumentType.integer(1)). + then(drawShape(c -> DrawCommand.drawDiamond(c, true)))))). + then(literal("pyramid"). + then(argument("center", BlockPosArgumentType.blockPos()). + then(argument("radius", IntegerArgumentType.integer(1)). + then(argument("height",IntegerArgumentType.integer(1)). + then(argument("pointing",StringArgumentType.word()).suggests( (c, b) -> suggestMatching(new String[]{"up","down"},b)). + then(argument("orientation",StringArgumentType.word()).suggests( (c, b) -> suggestMatching(new String[]{"y","x","z"},b)). + then(drawShape(c -> DrawCommand.drawPyramid(c, "square", true))))))))). + then(literal("cone"). + then(argument("center", BlockPosArgumentType.blockPos()). + then(argument("radius", IntegerArgumentType.integer(1)). + then(argument("height",IntegerArgumentType.integer(1)). + then(argument("pointing",StringArgumentType.word()).suggests( (c, b) -> suggestMatching(new String[]{"up","down"},b)). + then(argument("orientation",StringArgumentType.word()).suggests( (c, b) -> suggestMatching(new String[]{"y","x","z"},b)) + .then(drawShape(c -> DrawCommand.drawPyramid(c, "circle", true))))))))); dispatcher.register(command); } - private static int drawSphere(ServerCommandSource source, BlockPos pos, int radius, BlockStateArgument block, - Predicate replacement) + @FunctionalInterface + private interface OptionalBlockSelector { - return drawSphere(source, pos, (double) radius, (double) radius, (double) radius, block, replacement, false); + Integer apply(final CommandContext ctx) throws CommandSyntaxException; } - private static int drawSphere(ServerCommandSource source, BlockPos pos, double radiusX, double radiusY, - double radiusZ, BlockStateArgument block, Predicate replacement, boolean solid) + @FunctionalInterface + private interface ArgumentExtractor { - int affected = 0; - ServerWorld world = source.getWorld(); + T apply(final CommandContext ctx, final String argName) throws CommandSyntaxException; + } - radiusX += 0.5; - radiusY += 0.5; - radiusZ += 0.5; + private static RequiredArgumentBuilder + drawShape(OptionalBlockSelector drawer) + { + return argument("block", BlockStateArgumentType.blockState()). + executes(drawer::apply) + .then(literal("replace") + .then(argument("filter", BlockPredicateArgumentType.blockPredicate()) + .executes(drawer::apply))); + } + + private static class ErrorHandled extends RuntimeException {} + + private static T getArg(CommandContext ctx, ArgumentExtractor extract, String hwat) throws CommandSyntaxException + { + return getArg(ctx, extract, hwat, false); + } + + private static T getArg(CommandContext ctx, ArgumentExtractor extract, String hwat, boolean optional) throws CommandSyntaxException + { + T arg = null; + try + { + arg = extract.apply(ctx, hwat); + } + catch (IllegalArgumentException e) + { + if (optional) return null; + Messenger.m(ctx.getSource(), "rb Missing "+hwat); + throw new ErrorHandled(); + } + return arg; + } + + private static double lengthSq(double x, double y, double z) + { + return (x * x) + (y * y) + (z * z); + } + + private static int setBlock( + ServerWorld world, BlockPos.Mutable mbpos, int x, int y, int z, + BlockStateArgument block, Predicate replacement, + List list + ) + { + mbpos.set(x, y, z); + int success=0; + if (replacement == null || replacement.test(new CachedBlockPosition(world, mbpos, true))) + { + BlockEntity tileentity = world.getBlockEntity(mbpos); + if (tileentity instanceof Inventory) + { + ((Inventory) tileentity).clear(); + } + if (block.setBlockState(world, mbpos, 2)) + { + list.add(mbpos.toImmutable()); + ++success; + } + } + + return success; + } + + private static int drawSphere(CommandContext ctx, boolean solid) throws CommandSyntaxException + { + BlockPos pos; + int radius; + BlockStateArgument block; + Predicate replacement; + try + { + pos = getArg(ctx, BlockPosArgumentType::getBlockPos, "center"); + radius = getArg(ctx, IntegerArgumentType::getInteger, "radius"); + block = getArg(ctx, BlockStateArgumentType::getBlockState, "block"); + replacement = getArg(ctx, BlockPredicateArgumentType::getBlockPredicate, "filter", true); + } + catch (ErrorHandled ignored) { return 0; } + + int affected = 0; + ServerWorld world = ctx.getSource().getWorld(); + + double radiusX = radius+0.5; + double radiusY = radius+0.5; + double radiusZ = radius+0.5; final double invRadiusX = 1 / radiusX; final double invRadiusY = 1 / radiusY; @@ -148,22 +178,28 @@ public class DrawCommand double nextXn = 0; - forX: for (int x = 0; x <= ceilRadiusX; ++x) { + forX: for (int x = 0; x <= ceilRadiusX; ++x) + { final double xn = nextXn; nextXn = (x + 1) * invRadiusX; double nextYn = 0; - forY: for (int y = 0; y <= ceilRadiusY; ++y) { + forY: for (int y = 0; y <= ceilRadiusY; ++y) + { final double yn = nextYn; nextYn = (y + 1) * invRadiusY; double nextZn = 0; - forZ: for (int z = 0; z <= ceilRadiusZ; ++z) { + forZ: for (int z = 0; z <= ceilRadiusZ; ++z) + { final double zn = nextZn; nextZn = (z + 1) * invRadiusZ; double distanceSq = lengthSq(xn, yn, zn); - if (distanceSq > 1) { - if (z == 0) { - if (y == 0) { + if (distanceSq > 1) + { + if (z == 0) + { + if (y == 0) + { break forX; } break forY; @@ -171,11 +207,9 @@ public class DrawCommand break forZ; } - if (!solid) { - if (lengthSq(nextXn, yn, zn) <= 1 && lengthSq(xn, nextYn, zn) <= 1 && lengthSq(xn, yn, nextZn) <= 1) - { - continue; - } + if (!solid && lengthSq(nextXn, yn, zn) <= 1 && lengthSq(xn, nextYn, zn) <= 1 && lengthSq(xn, yn, nextZn) <= 1) + { + continue; } CarpetSettings.impendingFillSkipUpdates = !CarpetSettings.fillUpdates; @@ -185,22 +219,10 @@ public class DrawCommand { for (int zmod = -1; zmod < 2; zmod += 2) { - mbpos.set(pos.getX() + xmod * x, pos.getY() + ymod * y, pos.getZ() + zmod * z); - if (replacement == null - || replacement.test(new CachedBlockPosition(world, mbpos, true))) - { - BlockEntity tileentity = world.getBlockEntity(mbpos); - if (tileentity instanceof Inventory) - { - ((Inventory) tileentity).clear(); - } - - if (block.setBlockState(world, mbpos, 2)) - { - list.add(mbpos.toImmutable()); - ++affected; - } - } + affected+= setBlock(world, mbpos, + pos.getX() + xmod * x, pos.getY() + ymod * y, pos.getZ() + zmod * z, + block, replacement, list + ); } } } @@ -208,48 +230,31 @@ public class DrawCommand } } } - if (CarpetSettings.fillUpdates) { - - for (BlockPos blockpos1 : list) { - Block blokc = world.getBlockState(blockpos1).getBlock(); - world.updateNeighbors(blockpos1, blokc); // or always version???? - } + if (CarpetSettings.fillUpdates) + { + list.forEach(blockpos1 -> world.updateNeighbors(blockpos1, world.getBlockState(blockpos1).getBlock())); } - Messenger.m(source, "gi Filled " + affected + " blocks"); - - return 1; + Messenger.m(ctx.getSource(), "gi Filled " + affected + " blocks"); + return affected; } - private static double lengthSq(double x, double y, double z) { - return (x * x) + (y * y) + (z * z); - } - - private static int blockset(ServerCommandSource source, int x, int y, int z, Predicate replacement, List list, - BlockPos.Mutable mbpos, BlockStateArgument block){ - ServerWorld world = source.getWorld(); - mbpos.set(x, y, z); - int success=0; - if (replacement == null || replacement.test(new CachedBlockPosition(world, mbpos, true))) { - BlockEntity tileentity = world.getBlockEntity(mbpos); - if (tileentity instanceof Inventory) { - ((Inventory) tileentity).clear(); - } - if (block.setBlockState(world, mbpos, 2)) { - list.add(mbpos.toImmutable()); - ++success; - } + private static int drawDiamond(CommandContext ctx, boolean solid) throws CommandSyntaxException + { + BlockPos pos; + int radius; + BlockStateArgument block; + Predicate replacement; + try + { + pos = getArg(ctx, BlockPosArgumentType::getBlockPos, "center"); + radius = getArg(ctx, IntegerArgumentType::getInteger, "radius"); + block = getArg(ctx, BlockStateArgumentType::getBlockState, "block"); + replacement = getArg(ctx, BlockPredicateArgumentType::getBlockPredicate, "filter", true); } + catch (ErrorHandled ignored) { return 0; } - return success; - } + ServerCommandSource source = ctx.getSource(); - private static int drawDiamond(ServerCommandSource source, BlockPos pos, int radius, BlockStateArgument block, - Predicate replacement) { - return (int) drawDiamond(source, pos, radius, block, replacement, false); - } - - private static int drawDiamond(ServerCommandSource source, BlockPos pos, int radius,BlockStateArgument block, - Predicate replacement, boolean solid) { int affected=0; BlockPos.Mutable mbpos = new BlockPos.Mutable(pos); @@ -259,78 +264,100 @@ public class DrawCommand CarpetSettings.impendingFillSkipUpdates = !CarpetSettings.fillUpdates; - for (int r = 0; r < radius; ++r) { + for (int r = 0; r < radius; ++r) + { int y=r-radius+1; - for (int x = -r; x <= r; ++x) { + for (int x = -r; x <= r; ++x) + { int z=r-Math.abs(x); - affected+=blockset(source, pos.getX()+x, pos.getY()-y, pos.getZ()+z, replacement, list, mbpos, block); - affected+=blockset(source, pos.getX()+x, pos.getY()-y, pos.getZ()-z, replacement, list, mbpos, block); - affected+=blockset(source, pos.getX()+x, pos.getY()+y, pos.getZ()+z, replacement, list, mbpos, block); - affected+=blockset(source, pos.getX()+x, pos.getY()+y, pos.getZ()-z, replacement, list, mbpos, block); + affected+= setBlock(world, mbpos, pos.getX()+x, pos.getY()-y, pos.getZ()+z, block, replacement, list); + affected+= setBlock(world, mbpos, pos.getX()+x, pos.getY()-y, pos.getZ()-z, block, replacement, list); + affected+= setBlock(world, mbpos, pos.getX()+x, pos.getY()+y, pos.getZ()+z, block, replacement, list); + affected+= setBlock(world, mbpos, pos.getX()+x, pos.getY()+y, pos.getZ()-z, block, replacement, list); } } CarpetSettings.impendingFillSkipUpdates = false; - if (CarpetSettings.fillUpdates) { - - for (BlockPos blockpos1 : list) { - Block blokc = world.getBlockState(blockpos1).getBlock(); - world.updateNeighbors(blockpos1, blokc); - } + if (CarpetSettings.fillUpdates) + { + list.forEach(p -> world.updateNeighbors(p, world.getBlockState(p).getBlock())); } Messenger.m(source, "gi Filled " + affected + " blocks"); - return 1; + return affected; } - private static int drawCircle(ServerCommandSource source, BlockPos pos, int offset, int radius,BlockStateArgument block, String orientation, - Predicate replacement, List list, BlockPos.Mutable mbpos){ + private static int fillFlat( + ServerWorld world, BlockPos pos, int offset, double dr, boolean rectangle, String orientation, + BlockStateArgument block, Predicate replacement, + List list, BlockPos.Mutable mbpos + ) + { int successes=0; - for(int axis1=-radius;axis1<=radius;++axis1){ - - for(int axis2=-radius;axis2<=radius;++axis2){ - - if(axis1*axis1+axis2*axis2<=radius*radius){ - switch (orientation){ - case "x":successes+=blockset(source, pos.getX()+offset, pos.getY()+axis1, pos.getZ()+axis2,replacement, list, mbpos, block);break; - case "y":successes+=blockset(source, pos.getX()+axis1, pos.getY()+offset, pos.getZ()+axis2,replacement, list, mbpos, block);break; - case "z":successes+=blockset(source, pos.getX()+axis2, pos.getY()+axis1, pos.getZ()+offset,replacement, list, mbpos, block);break; - default:Messenger.m(source,"gi Invalid orientation, must be x, y or z");return 0; - } - } + int r = MathHelper.floor(dr); + double drsq = dr*dr; + if (orientation.equalsIgnoreCase("x")) + { + for(int a=-r; a<=r; ++a) for(int b=-r; b<=r; ++b) if(rectangle || a*a + b*b <= drsq) + { + successes += setBlock( + world, mbpos,pos.getX()+offset, pos.getY()+a, pos.getZ()+b, + block, replacement, list + ); } + return successes; } - return successes; - } - private static int drawSquare(ServerCommandSource source, BlockPos pos, int offset, int radius, BlockStateArgument block, String orientation, - Predicate replacement, List list, BlockPos.Mutable mbpos){ - int success=0; - - for(int axis1=-radius;axis1<=radius;++axis1){ - - for(int axis2=-radius;axis2<=radius;++axis2){ - switch (orientation){ - case "x":success+=blockset(source, pos.getX()+offset, pos.getY()+axis1, pos.getZ()+axis2,replacement, list, mbpos, block);break; - case "y":success+=blockset(source, pos.getX()+axis1, pos.getY()+offset, pos.getZ()+axis2,replacement, list, mbpos, block);break; - case "z":success+=blockset(source, pos.getX()+axis2, pos.getY()+axis1, pos.getZ()+offset,replacement, list, mbpos, block);break; - default:Messenger.m(source,"gi Invalid orientation, must be x, y or z");return 0; - } + if (orientation.equalsIgnoreCase("y")) + { + for(int a=-r; a<=r; ++a) for(int b=-r; b<=r; ++b) if(rectangle || a*a + b*b <= drsq) + { + successes += setBlock( + world, mbpos,pos.getX()+a, pos.getY()+offset, pos.getZ()+b, + block, replacement, list + ); } + return successes; } - - return success; - } - - private static int drawPyramid(ServerCommandSource source, BlockPos pos, String shape, int radius, int height, boolean pointup, String orientation, BlockStateArgument block, - Predicate replacement) { - return (int) drawPyramid(source, pos, radius, height, block, replacement, pointup, orientation, false, shape); + if (orientation.equalsIgnoreCase("z")) + { + for(int a=-r; a<=r; ++a) for(int b=-r; b<=r; ++b) if(rectangle || a*a + b*b <= drsq) + { + successes += setBlock( + world, mbpos,pos.getX()+b, pos.getY()+a, pos.getZ()+offset, + block, replacement, list + ); + } + return successes; + } + return 0; } - private static double drawPyramid(ServerCommandSource source, BlockPos pos, int radius, int height, BlockStateArgument block, - Predicate replacement, boolean pointup, String orientation, boolean solid, String shape) { + private static int drawPyramid(CommandContext ctx, String base, boolean solid) throws CommandSyntaxException + { + BlockPos pos; + double radius; + int height; + boolean pointup; + String orientation; + BlockStateArgument block; + Predicate replacement; + try + { + pos = getArg(ctx, BlockPosArgumentType::getBlockPos, "center"); + radius = getArg(ctx, IntegerArgumentType::getInteger, "radius")+0.5D; + height = getArg(ctx, IntegerArgumentType::getInteger, "height"); + pointup = getArg(ctx, StringArgumentType::getString, "pointing").equalsIgnoreCase("up"); + orientation = getArg(ctx, StringArgumentType::getString,"orientation"); + block = getArg(ctx, BlockStateArgumentType::getBlockState, "block"); + replacement = getArg(ctx, BlockPredicateArgumentType::getBlockPredicate, "filter", true); + } + catch (ErrorHandled ignored) { return 0; } + + ServerCommandSource source = ctx.getSource(); + int affected = 0; BlockPos.Mutable mbpos = new BlockPos.Mutable(pos); @@ -340,22 +367,12 @@ public class DrawCommand CarpetSettings.impendingFillSkipUpdates = !CarpetSettings.fillUpdates; - int r = radius; + boolean isSquare = base.equalsIgnoreCase("square"); - for(int i =0; i Date: Tue, 28 Apr 2020 18:38:56 -0300 Subject: [PATCH 093/198] scoreboard_remove(obj, key) will remove the key from the objective. Fixes #255 --- docs/scarpet/Full.md | 19 ++++--- docs/scarpet/api/Scoreboard.md | 7 ++- .../java/carpet/script/CarpetExpression.java | 54 +++++++++++-------- 3 files changed, 51 insertions(+), 29 deletions(-) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index 68206456..427ecb67 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -2217,11 +2217,15 @@ It returns a `map` with a report indicating how many chunks were affected, and h These functions help scan larger areas of blocks without using generic loop functions, like nested `loop`. -### `scan(cx, cy, cz, dx, dy, dz, px?, py?, pz?, expr)` +### `scan(cx, cy, cz, dx, dy, dz, px?, py?, pz?, expr)`, `scan(center, range, lower_range?, expr)` -Evaluates expression over area of blocks defined by its center (`cx, cy, cz`), expanded in all directions -by `dx, dy, dz` blocks, or optionally in negative with `d` coords, and `p` coords in positive values. `expr` -receives `_x, _y, _z` as coords of current analyzed block and `_`, which represents the block itself. +Evaluates expression over area of blocks defined by its center `center = (cx, cy, cz)`, expanded in all directions +by `range = (dx, dy, dz)` blocks, or optionally in negative with `range` coords, and `upper_range` coords in +positive values. +`center` can be defined either as a three coordinates, list of three coords, or block value. +`range` and `lower_range` can have the same representations, just if its a block, it computes the distance to the center +as range instead of taking the values as is. +`expr` receives `_x, _y, _z` as coords of current analyzed block and `_`, which represents the block itself. Returns number of successful evaluations of `expr` (with `true` boolean result) unless called in void context, which would cause the expression not be evaluated for their boolean value. @@ -2951,9 +2955,12 @@ scoreboard_add('counter') scoreboard_add('lvl','level')
-### `scoreboard_remove(objective)` +### `scoreboard_remove(objective)` `scoreboard_remove(objective, key)` -Removes an objective. Returns `true` if objective has existed and has been removed. +Removes an entire objective, or an entry in the scoreboard associated with the key. +Returns `true` if objective has existed and has been removed, or previous +value of the scoreboard if players score is removed. Returns `null` if objective didn't exist, or a key was missing +for the objective. ### `scoreboard_display(place, objective)` diff --git a/docs/scarpet/api/Scoreboard.md b/docs/scarpet/api/Scoreboard.md index a509bb15..b638fb93 100644 --- a/docs/scarpet/api/Scoreboard.md +++ b/docs/scarpet/api/Scoreboard.md @@ -17,9 +17,12 @@ scoreboard_add('counter') scoreboard_add('lvl','level')
-### `scoreboard_remove(objective)` +### `scoreboard_remove(objective)` `scoreboard_remove(objective, key)` -Removes an objective. Returns `true` if objective has existed and has been removed. +Removes an entire objective, or an entry in the scoreboard associated with the key. +Returns `true` if objective has existed and has been removed, or previous +value of the scoreboard if players score is removed. Returns `null` if objective didn't exist, or a key was missing +for the objective. ### `scoreboard_display(place, objective)` diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 30c3f3e4..3bf675f1 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -1296,6 +1296,26 @@ public class CarpetExpression } + private static String getScoreboardKeyFromValue(Value keyValue) + { + if (keyValue instanceof EntityValue) + { + Entity e = ((EntityValue) keyValue).getEntity(); + if (e instanceof PlayerEntity) + { + return e.getName().getString(); + } + else + { + return e.getUuidAsString(); + } + } + else + { + return keyValue.getString(); + } + } + private void API_Scoreboard() { // scoreboard(player,'objective') @@ -1317,24 +1337,7 @@ public class CarpetExpression Value ret = ListValue.wrap(scoreboard.getAllPlayerScores(objective).stream().map(s -> new StringValue(s.getPlayerName())).collect(Collectors.toList())); return (_c, _t) -> ret; } - String key; - Value keyValue = lv.get(1).evalValue(c); - if (keyValue instanceof EntityValue) - { - Entity e = ((EntityValue) keyValue).getEntity(); - if (e instanceof PlayerEntity) - { - key = e.getDisplayName().getString(); - } - else - { - key = e.getUuidAsString(); - } - } - else - { - key = keyValue.getString(); - } + String key = getScoreboardKeyFromValue(lv.get(1).evalValue(c)); if (!scoreboard.playerHasObjective(key, objective) && lv.size()==2) return LazyValue.NULL; ScoreboardPlayerScore scoreboardPlayerScore = scoreboard.getPlayerScore(key, objective); @@ -1346,15 +1349,24 @@ public class CarpetExpression return (_c, _t) -> retval; }); - this.expr.addLazyFunction("scoreboard_remove", 1, (c, t, lv)-> { + this.expr.addLazyFunction("scoreboard_remove", -1, (c, t, lv)-> { CarpetContext cc = (CarpetContext)c; Scoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard(); String objectiveName = lv.get(0).evalValue(c).getString(); ScoreboardObjective objective = scoreboard.getObjective(objectiveName); if (objective == null) return LazyValue.FALSE; - scoreboard.removeObjective(objective); - return LazyValue.TRUE; + if (lv.size() == 0) + { + scoreboard.removeObjective(objective); + return LazyValue.TRUE; + } + String key = getScoreboardKeyFromValue(lv.get(1).evalValue(c)); + if (!scoreboard.playerHasObjective(key, objective)) return LazyValue.NULL; + ScoreboardPlayerScore scoreboardPlayerScore = scoreboard.getPlayerScore(key, objective); + Value previous = new NumericValue(scoreboardPlayerScore.getScore()); + scoreboard.resetPlayerScore(key, objective); + return (c_, t_) -> previous; }); // objective_add('lvl','level') From 0b72f85474bb3dc49f9fc800233eea4fe93b03bb Mon Sep 17 00:00:00 2001 From: gnembon Date: Tue, 28 Apr 2020 19:39:13 -0300 Subject: [PATCH 094/198] messenger can parse style --- src/main/java/carpet/utils/Messenger.java | 65 ++++++++++++----------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/src/main/java/carpet/utils/Messenger.java b/src/main/java/carpet/utils/Messenger.java index 3b422262..7604d13e 100644 --- a/src/main/java/carpet/utils/Messenger.java +++ b/src/main/java/carpet/utils/Messenger.java @@ -3,14 +3,15 @@ package carpet.utils; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.entity.EntityCategory; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3d; -import net.minecraft.text.LiteralText; -import net.minecraft.util.Formatting; import net.minecraft.text.BaseText; -import net.minecraft.server.MinecraftServer; import net.minecraft.text.ClickEvent; import net.minecraft.text.HoverEvent; +import net.minecraft.text.LiteralText; +import net.minecraft.text.Style; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.Formatting; +import net.minecraft.server.MinecraftServer; import net.minecraft.world.dimension.DimensionType; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -52,32 +53,33 @@ public class Messenger / = action added to the previous component */ - private static BaseText _applyStyleToTextComponent(BaseText comp, String style) + public static Style parseStyle(String style) { //could be rewritten to be more efficient - comp.getStyle().setItalic(style.indexOf('i')>=0); - comp.getStyle().setStrikethrough(style.indexOf('s')>=0); - comp.getStyle().setUnderline(style.indexOf('u')>=0); - comp.getStyle().setBold(style.indexOf('b')>=0); - comp.getStyle().setObfuscated(style.indexOf('o')>=0); - comp.getStyle().setColor(Formatting.WHITE); - if (style.indexOf('w')>=0) comp.getStyle().setColor(Formatting.WHITE); // not needed - if (style.indexOf('y')>=0) comp.getStyle().setColor(Formatting.YELLOW); - if (style.indexOf('m')>=0) comp.getStyle().setColor(Formatting.LIGHT_PURPLE); - if (style.indexOf('r')>=0) comp.getStyle().setColor(Formatting.RED); - if (style.indexOf('c')>=0) comp.getStyle().setColor(Formatting.AQUA); - if (style.indexOf('l')>=0) comp.getStyle().setColor(Formatting.GREEN); - if (style.indexOf('t')>=0) comp.getStyle().setColor(Formatting.BLUE); - if (style.indexOf('f')>=0) comp.getStyle().setColor(Formatting.DARK_GRAY); - if (style.indexOf('g')>=0) comp.getStyle().setColor(Formatting.GRAY); - if (style.indexOf('d')>=0) comp.getStyle().setColor(Formatting.GOLD); - if (style.indexOf('p')>=0) comp.getStyle().setColor(Formatting.DARK_PURPLE); - if (style.indexOf('n')>=0) comp.getStyle().setColor(Formatting.DARK_RED); - if (style.indexOf('q')>=0) comp.getStyle().setColor(Formatting.DARK_AQUA); - if (style.indexOf('e')>=0) comp.getStyle().setColor(Formatting.DARK_GREEN); - if (style.indexOf('v')>=0) comp.getStyle().setColor(Formatting.DARK_BLUE); - if (style.indexOf('k')>=0) comp.getStyle().setColor(Formatting.BLACK); - return comp; + Style styleInstance = new Style(); + styleInstance.setItalic(style.indexOf('i')>=0); + styleInstance.setStrikethrough(style.indexOf('s')>=0); + styleInstance.setUnderline(style.indexOf('u')>=0); + styleInstance.setBold(style.indexOf('b')>=0); + styleInstance.setObfuscated(style.indexOf('o')>=0); + styleInstance.setColor(Formatting.WHITE); + if (style.indexOf('w')>=0) styleInstance.setColor(Formatting.WHITE); // not needed + if (style.indexOf('y')>=0) styleInstance.setColor(Formatting.YELLOW); + if (style.indexOf('m')>=0) styleInstance.setColor(Formatting.LIGHT_PURPLE); + if (style.indexOf('r')>=0) styleInstance.setColor(Formatting.RED); + if (style.indexOf('c')>=0) styleInstance.setColor(Formatting.AQUA); + if (style.indexOf('l')>=0) styleInstance.setColor(Formatting.GREEN); + if (style.indexOf('t')>=0) styleInstance.setColor(Formatting.BLUE); + if (style.indexOf('f')>=0) styleInstance.setColor(Formatting.DARK_GRAY); + if (style.indexOf('g')>=0) styleInstance.setColor(Formatting.GRAY); + if (style.indexOf('d')>=0) styleInstance.setColor(Formatting.GOLD); + if (style.indexOf('p')>=0) styleInstance.setColor(Formatting.DARK_PURPLE); + if (style.indexOf('n')>=0) styleInstance.setColor(Formatting.DARK_RED); + if (style.indexOf('q')>=0) styleInstance.setColor(Formatting.DARK_AQUA); + if (style.indexOf('e')>=0) styleInstance.setColor(Formatting.DARK_GREEN); + if (style.indexOf('v')>=0) styleInstance.setColor(Formatting.DARK_BLUE); + if (style.indexOf('k')>=0) styleInstance.setColor(Formatting.BLACK); + return styleInstance; } public static String heatmap_color(double actual, double reference) { @@ -143,7 +145,8 @@ public class Messenger return previous_message; } BaseText txt = new LiteralText(str); - return _applyStyleToTextComponent(txt, desc); + txt.setStyle(parseStyle(desc)); + return txt; } public static BaseText tp(String desc, Vec3d pos) { return tp(desc, pos.x, pos.y, pos.z); } public static BaseText tp(String desc, BlockPos pos) { return tp(desc, pos.getX(), pos.getY(), pos.getZ()); } @@ -263,7 +266,7 @@ public class Messenger public static BaseText s(String text, String style) { BaseText message = new LiteralText(text); - _applyStyleToTextComponent(message, style); + message.setStyle(parseStyle(style)); return message; } From 7577c475f61f383d5321bec2b262dff255978501 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 29 Apr 2020 00:48:02 -0300 Subject: [PATCH 095/198] format, fixes #254 --- docs/scarpet/Full.md | 54 +++++++++++++++++++ docs/scarpet/api/Auxiliary.md | 54 +++++++++++++++++++ mergedoc.sh | 2 + .../java/carpet/script/CarpetExpression.java | 23 ++++++-- .../script/value/FormattedTextValue.java | 40 ++++++++++++++ src/main/java/carpet/utils/Messenger.java | 10 ++-- 6 files changed, 177 insertions(+), 6 deletions(-) create mode 100755 mergedoc.sh create mode 100644 src/main/java/carpet/script/value/FormattedTextValue.java diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index 427ecb67..efc638e8 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -3028,6 +3028,60 @@ as a string value. Displays the result of the expression to the chat. Overrides default `scarpet` behaviour of sending everyting to stderr. +### `format(components, ...)`, `format(l(components, ...))` + +Creates a line of formatted text. Each component is either a string indicating formatting and text it corresponds to +or a decorator affecting the component preceding it. + +Regular formatting components is a string that have the structure of: +`' '`, like `'gi Hi'`, which in this case indicates a grey, italicised word `'Hi'`. The space to separate the format and the text is mandatory. The format can be empty, but the space still +needs to be there otherwise the first word of the text will be used as format, which nobody wants. + +Format is a list of formatting symbols indicating the format. They can be mixed and matched although color will only be +applied once. Available symbols include: + * `i` - _italic_ + * `b` - **bold** + * `s` - ~~strikethrough~~ + * `u` - underline + * `o` - obfuscated + +And colors: + * `w` - White (default) + * `y` - Yellow + * `m` - Magenta (light purple) + * `r` - Red + * `c` - Cyan (aqua) + * `l` - Lime + * `t` - lighT blue + * `f` - dark grayF (weird Flex, but ok) + * `g` - Gray + * `d` - golD + * `p` - PurPle + * `n` - browN (dark red) + * `q` - turQuoise (dark aqua) + * `e` - grEEn + * `v` - naVy blue + * `k` - blaK + * `#FFAACC` - arbitrary RGB color (1.16+), hex notation + +Decorators (listed as extra argument after the component they would affect): + * `'^ '` - hover over tooltip text, appearing when hovering with your mouse over the text below. + * `'?` - command suggestion - a message that will be pasted to chat when text below it is clicked. + * `'!'` - a chat message that will be executed when the text below it is clicked. + +Both suggestions and messages can contain a command, which will be executed as a player that clicks it. + +So far the only usecase for formatted texts is with a `print` command. Otherwise it functions like a normal +string value representing what is actually displayed on screen. + +Example usages: +
+ print(format('rbu Error: ', 'r Stuff happened!'))
+ print(format('w Click ','tb [HERE]', '^di Awesome!', '!/kill', 'w \ button to win $1000'))
+  // the reason why I backslash the second space is that otherwise command parser may contract consecutive spaces
+  // not a problem in apps
+
+ ### `logger(expr)` Prints the message to system logs, and not to chat. diff --git a/docs/scarpet/api/Auxiliary.md b/docs/scarpet/api/Auxiliary.md index db5cba2e..0a752150 100644 --- a/docs/scarpet/api/Auxiliary.md +++ b/docs/scarpet/api/Auxiliary.md @@ -61,6 +61,60 @@ as a string value. Displays the result of the expression to the chat. Overrides default `scarpet` behaviour of sending everyting to stderr. +### `format(components, ...)`, `format(l(components, ...))` + +Creates a line of formatted text. Each component is either a string indicating formatting and text it corresponds to +or a decorator affecting the component preceding it. + +Regular formatting components is a string that have the structure of: +`' '`, like `'gi Hi'`, which in this case indicates a grey, italicised word `'Hi'`. The space to separate the format and the text is mandatory. The format can be empty, but the space still +needs to be there otherwise the first word of the text will be used as format, which nobody wants. + +Format is a list of formatting symbols indicating the format. They can be mixed and matched although color will only be +applied once. Available symbols include: + * `i` - _italic_ + * `b` - **bold** + * `s` - ~~strikethrough~~ + * `u` - underline + * `o` - obfuscated + +And colors: + * `w` - White (default) + * `y` - Yellow + * `m` - Magenta (light purple) + * `r` - Red + * `c` - Cyan (aqua) + * `l` - Lime + * `t` - lighT blue + * `f` - dark grayF (weird Flex, but ok) + * `g` - Gray + * `d` - golD + * `p` - PurPle + * `n` - browN (dark red) + * `q` - turQuoise (dark aqua) + * `e` - grEEn + * `v` - naVy blue + * `k` - blaK + * `#FFAACC` - arbitrary RGB color (1.16+), hex notation + +Decorators (listed as extra argument after the component they would affect): + * `'^ '` - hover over tooltip text, appearing when hovering with your mouse over the text below. + * `'?` - command suggestion - a message that will be pasted to chat when text below it is clicked. + * `'!'` - a chat message that will be executed when the text below it is clicked. + +Both suggestions and messages can contain a command, which will be executed as a player that clicks it. + +So far the only usecase for formatted texts is with a `print` command. Otherwise it functions like a normal +string value representing what is actually displayed on screen. + +Example usages: +
+ print(format('rbu Error: ', 'r Stuff happened!'))
+ print(format('w Click ','tb [HERE]', '^di Awesome!', '!/kill', 'w \ button to win $1000'))
+  // the reason why I backslash the second space is that otherwise command parser may contract consecutive spaces
+  // not a problem in apps
+
+ ### `logger(expr)` Prints the message to system logs, and not to chat. diff --git a/mergedoc.sh b/mergedoc.sh new file mode 100755 index 00000000..16559437 --- /dev/null +++ b/mergedoc.sh @@ -0,0 +1,2 @@ +cat docs/scarpet/language/Overview.md docs/scarpet/language/VariablesAndConstants.md docs/scarpet/language/Operators.md docs/scarpet/language/Math.md docs/scarpet/language/SystemFunctions.md docs/scarpet/language/LoopsAndHigherOrderFunctions.md docs/scarpet/language/FunctionsAndControlFlow.md docs/scarpet/language/Containers.md docs/scarpet/api/Overview.md docs/scarpet/api/BlocksAndWorldAccess.md docs/scarpet/api/BlockIterations.md docs/scarpet/api/Entities.md docs/scarpet/api/Inventories.md docs/scarpet/api/Events.md docs/scarpet/api/Scoreboard.md docs/scarpet/api/Auxiliary.md docs/scarpet/api/ScriptCommand.md > docs/scarpet/Full.md + diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 3bf675f1..03e42147 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -23,6 +23,7 @@ import carpet.script.exception.ExpressionException; import carpet.script.exception.InternalExpressionException; import carpet.script.value.BlockValue; import carpet.script.value.EntityValue; +import carpet.script.value.FormattedTextValue; import carpet.script.value.FunctionValue; import carpet.script.value.LazyListValue; import carpet.script.value.ListValue; @@ -2677,17 +2678,33 @@ public class CarpetExpression { ServerCommandSource s = ((CarpetContext)c).s; Value res = lv.get(0).evalValue(c); - if (s.getEntity() instanceof PlayerEntity) + if (res instanceof FormattedTextValue) { - Messenger.m((PlayerEntity) s.getEntity(), "w "+ res.getString()); + s.sendFeedback(((FormattedTextValue) res).getText(), false); } else { - Messenger.m(s, "w "+ res.getString()); + if (s.getEntity() instanceof PlayerEntity) + { + Messenger.m((PlayerEntity) s.getEntity(), "w " + res.getString()); + } + else + { + Messenger.m(s, "w " + res.getString()); + } } return (_c, _t) -> res; // pass through for variables }); + this.expr.addLazyFunction("format", -1, (c, t, lv) -> { + if (lv.size() == 0 ) throw new InternalExpressionException("'format' requires at least one component"); + List values = lv.stream().map(lazy -> lazy.evalValue(c)).collect(Collectors.toList()); + if (values.get(0) instanceof ListValue && values.size()==1) + values = ((ListValue) values.get(0)).getItems(); + Value ret = new FormattedTextValue(Messenger.c(values.stream().map(Value::getString).toArray())); + return (cc, tt) -> ret; + }); + //"overidden" native call to cancel if on main thread this.expr.addLazyFunction("task_join", 1, (c, t, lv) -> { if (((CarpetContext)c).s.getMinecraftServer().isOnThread()) diff --git a/src/main/java/carpet/script/value/FormattedTextValue.java b/src/main/java/carpet/script/value/FormattedTextValue.java new file mode 100644 index 00000000..501e3181 --- /dev/null +++ b/src/main/java/carpet/script/value/FormattedTextValue.java @@ -0,0 +1,40 @@ +package carpet.script.value; + +import net.minecraft.text.BaseText; + +public class FormattedTextValue extends StringValue +{ + BaseText text; + public FormattedTextValue(BaseText text) + { + super(null); + this.text = text; + } + + @Override + public String getString() { + return text.getString(); + } + + @Override + public boolean getBoolean() { + return text.getSiblings().size() > 0; + } + + @Override + public Value clone() + { + return new FormattedTextValue(text); + } + + @Override + public String getTypeString() + { + return "text"; + } + + public BaseText getText() + { + return text; + } +} diff --git a/src/main/java/carpet/utils/Messenger.java b/src/main/java/carpet/utils/Messenger.java index 7604d13e..953028f8 100644 --- a/src/main/java/carpet/utils/Messenger.java +++ b/src/main/java/carpet/utils/Messenger.java @@ -116,10 +116,14 @@ public class Messenger { message = "w"+message; } - String[] parts = message.split("\\s", 2); - String desc = parts[0]; + int limit = message.indexOf(' '); + String desc = message; String str = ""; - if (parts.length > 1) str = parts[1]; + if (limit >= 0) + { + desc = message.substring(0, limit); + str = message.substring(limit+1); + } if (desc.charAt(0) == '/') // deprecated { if (previous_message != null) From 07439cf648a9c72d2f5f771f7c00d91e3fcd5546 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 29 Apr 2020 00:53:57 -0300 Subject: [PATCH 096/198] detail --- docs/scarpet/api/Auxiliary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/scarpet/api/Auxiliary.md b/docs/scarpet/api/Auxiliary.md index 0a752150..241c2716 100644 --- a/docs/scarpet/api/Auxiliary.md +++ b/docs/scarpet/api/Auxiliary.md @@ -95,7 +95,7 @@ And colors: * `e` - grEEn * `v` - naVy blue * `k` - blaK - * `#FFAACC` - arbitrary RGB color (1.16+), hex notation + * `#FFAACC` - arbitrary RGB color (1.16+), hex notation. Use uppercase for A-F symbols Decorators (listed as extra argument after the component they would affect): * `'^ '` - hover over tooltip text, appearing when hovering with your mouse over the text below. From 434dedc57dcb1cabcaca61f90faa943754b9f129 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 29 Apr 2020 01:03:39 -0300 Subject: [PATCH 097/198] 1.3.21 --- gradle.properties | 2 +- src/main/java/carpet/CarpetSettings.java | 2 +- src/main/resources/fabric.mod.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 98ac82ca..2655bf11 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ org.gradle.jvmargs=-Xmx1G loader_version=0.7.8+build.188 # Mod Properties - mod_version = 1.3.20+v200422 + mod_version = 1.3.21+v200429 maven_group = carpet archives_base_name = fabric-carpet diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index ddb535bb..1d7c7010 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -33,7 +33,7 @@ import static carpet.settings.RuleCategory.CLIENT; @SuppressWarnings("CanBeFinal") public class CarpetSettings { - public static final String carpetVersion = "1.3.20+v200422"; + public static final String carpetVersion = "1.3.21+v200429"; public static final Logger LOG = LogManager.getLogger(); public static boolean skipGenerationChecks = false; public static boolean impendingFillSkipUpdates = false; diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 61d93fb5..249332b6 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,7 +1,7 @@ { "schemaVersion": 1, "id": "carpet", - "version": "1.3.20", + "version": "1.3.21", "name": "Carpet Mod in Fabric", "description": "Carpet made out of fabric", From 94ffd5b9900653f1a2994bf051046790a87e5168 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 29 Apr 2020 01:24:54 -0300 Subject: [PATCH 098/198] rotatorBlock can rotate hoppers, fixes #238 --- src/main/java/carpet/helpers/BlockRotator.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/carpet/helpers/BlockRotator.java b/src/main/java/carpet/helpers/BlockRotator.java index 78dfd716..2d83f824 100644 --- a/src/main/java/carpet/helpers/BlockRotator.java +++ b/src/main/java/carpet/helpers/BlockRotator.java @@ -263,6 +263,15 @@ public class BlockRotator } world.setBlockState(blockpos, iblockstate.with(HorizontalFacingBlock.FACING, face), 3); } + else if(block == Blocks.HOPPER ) + { + Direction face = iblockstate.get(HopperBlock.FACING); + if (face != Direction.DOWN) + { + face = rotateClockwise(face, Direction.Axis.Y); + world.setBlockState(blockpos, iblockstate.with(HopperBlock.FACING, face), 3); + } + } // Send block update to the block that just have been rotated. world.updateNeighbor(blockpos, block, source.getBlockPos()); @@ -270,8 +279,6 @@ public class BlockRotator } - - public static boolean flip_block(BlockState state, World world, PlayerEntity player, Hand hand, BlockHitResult hit) { Block block = state.getBlock(); From 1e9a8726be2a52ff9a5636ab376cf0a85ddd65eb Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 29 Apr 2020 11:32:42 -0300 Subject: [PATCH 099/198] tweaks to entity API code --- docs/scarpet/Full.md | 15 +++---- docs/scarpet/api/Entities.md | 10 +++-- .../carpet/fakes/LivingEntityInterface.java | 7 ++++ .../LivingEntity_scarpetEventsMixin.java | 20 +++++++++- .../java/carpet/script/value/EntityValue.java | 40 +++++++++---------- src/main/java/carpet/utils/MobAI.java | 24 ++++++----- 6 files changed, 72 insertions(+), 44 deletions(-) create mode 100644 src/main/java/carpet/fakes/LivingEntityInterface.java diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index 5f5d5aac..47e2c59c 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -2661,7 +2661,7 @@ Adds a vector to the motion vector. Most realistic way to apply a force to an en ### `modify(e, 'age', number)` -Modifies entity's internal age counter. Fiddling with this will affect directly behaviours of complex +Modifies entity's internal age counter. Fiddling with this will affect directly AI behaviours of complex entities, so use it with caution. ### `modify(e, 'pickup_delay', number)` @@ -2728,13 +2728,17 @@ Modifies gamemode of player to whatever string (case-insensitive) or number you * 2: adventure * 3: spectator -### `modify(e, 'jumping', true/false?)` +### `modify(e, 'jumping', true/false)` Will make the entity constantly jump if set to true, and will stop the entity from jumping if set to false. +Note that jumping parameter can be fully controlled by the entity AI, so don't expect that this will have +a permanent effect. Use `'jump'` to make an entity jump once for sure. + +Requires a living entity as an argument. ### `modify(e, 'jump'))` -Will make the entity jump once only +Will make the entity jump once. ### `modify(e, 'silent', true/false)` @@ -2744,9 +2748,6 @@ Will make the entity jump once only Will set mob on fire for `ticks` ticks. Set to 0 to extinguish. -### `modify(e, 'age', age)` - - ## Entity Events There is a number of events that happen to entities that you can attach your own code to in the form of event handlers. @@ -3090,7 +3091,7 @@ And colors: * `e` - grEEn * `v` - naVy blue * `k` - blaK - * `#FFAACC` - arbitrary RGB color (1.16+), hex notation + * `#FFAACC` - arbitrary RGB color (1.16+), hex notation. Use uppercase for A-F symbols Decorators (listed as extra argument after the component they would affect): * `'^ '` - hover over tooltip text, appearing when hovering with your mouse over the text below. diff --git a/docs/scarpet/api/Entities.md b/docs/scarpet/api/Entities.md index 4da5ddda..a0dec45d 100644 --- a/docs/scarpet/api/Entities.md +++ b/docs/scarpet/api/Entities.md @@ -400,7 +400,7 @@ Adds a vector to the motion vector. Most realistic way to apply a force to an en ### `modify(e, 'age', number)` -Modifies entity's internal age counter. Fiddling with this will affect directly behaviours of complex +Modifies entity's internal age counter. Fiddling with this will affect directly AI behaviours of complex entities, so use it with caution. ### `modify(e, 'pickup_delay', number)` @@ -470,10 +470,14 @@ Modifies gamemode of player to whatever string (case-insensitive) or number you ### `modify(e, 'jumping', true/false)` Will make the entity constantly jump if set to true, and will stop the entity from jumping if set to false. +Note that jumping parameter can be fully controlled by the entity AI, so don't expect that this will have +a permanent effect. Use `'jump'` to make an entity jump once for sure. + +Requires a living entity as an argument. ### `modify(e, 'jump'))` -Will make the entity jump once only +Will make the entity jump once. ### `modify(e, 'silent', true/false)` @@ -483,8 +487,6 @@ Will make the entity jump once only Will set mob on fire for `ticks` ticks. Set to 0 to extinguish. -### `modify(e, 'age', age)` - ## Entity Events There is a number of events that happen to entities that you can attach your own code to in the form of event handlers. diff --git a/src/main/java/carpet/fakes/LivingEntityInterface.java b/src/main/java/carpet/fakes/LivingEntityInterface.java new file mode 100644 index 00000000..2dba302e --- /dev/null +++ b/src/main/java/carpet/fakes/LivingEntityInterface.java @@ -0,0 +1,7 @@ +package carpet.fakes; + +public interface LivingEntityInterface +{ + void doJumpCM(); // added CM suffix to remove potential collisions with other mods + boolean isJumpingCM(); +} diff --git a/src/main/java/carpet/mixins/LivingEntity_scarpetEventsMixin.java b/src/main/java/carpet/mixins/LivingEntity_scarpetEventsMixin.java index 8ca20980..456b9b74 100644 --- a/src/main/java/carpet/mixins/LivingEntity_scarpetEventsMixin.java +++ b/src/main/java/carpet/mixins/LivingEntity_scarpetEventsMixin.java @@ -1,6 +1,7 @@ package carpet.mixins; import carpet.fakes.EntityInterface; +import carpet.fakes.LivingEntityInterface; import carpet.script.EntityEventsGroup; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; @@ -8,14 +9,19 @@ import net.minecraft.entity.LivingEntity; import net.minecraft.entity.damage.DamageSource; import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(LivingEntity.class) -public abstract class LivingEntity_scarpetEventsMixin extends Entity +public abstract class LivingEntity_scarpetEventsMixin extends Entity implements LivingEntityInterface { + @Shadow protected abstract void jump(); + + @Shadow protected boolean jumping; + public LivingEntity_scarpetEventsMixin(EntityType type, World world) { super(type, world); @@ -26,4 +32,16 @@ public abstract class LivingEntity_scarpetEventsMixin extends Entity { ((EntityInterface)this).getEventContainer().onEvent(EntityEventsGroup.EntityEventType.ON_DEATH, this, damageSource_1.name); } + + @Override + public void doJumpCM() + { + jump(); + } + + @Override + public boolean isJumpingCM() + { + return jumping; + } } diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index 9ef48a83..951c7173 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -2,6 +2,7 @@ package carpet.script.value; import carpet.fakes.EntityInterface; import carpet.fakes.ItemEntityInterface; +import carpet.fakes.LivingEntityInterface; import carpet.fakes.MobEntityInterface; import carpet.helpers.Tracer; import carpet.patches.EntityPlayerMPFake; @@ -61,7 +62,7 @@ import java.util.function.Predicate; import java.util.stream.Collectors; import static carpet.script.value.NBTSerializableValue.nameFromRegistryId; -import static carpet.utils.MobAI.jump; +import static carpet.utils.MobAI.genericJump; // TODO: decide whether copy(entity) should duplicate entity in the world. public class EntityValue extends Value @@ -281,13 +282,13 @@ public class EntityValue extends Value put("sneaking", (e, a) -> e.isSneaking()?Value.TRUE:Value.FALSE); put("sprinting", (e, a) -> e.isSprinting()?Value.TRUE:Value.FALSE); put("swimming", (e, a) -> e.isSwimming()?Value.TRUE:Value.FALSE); - /*put("jumping", (e, a) -> { + put("jumping", (e, a) -> { if (e instanceof LivingEntity) { - return ((LivingEntity) e).getJumping()?Value.TRUE:Value.FALSE; + return ((LivingEntityInterface) e).isJumpingCM()?Value.TRUE:Value.FALSE; } return Value.NULL; - });*/ //needs mixing + }); put("gamemode", (e, a) -> { if (e instanceof ServerPlayerEntity) { @@ -376,6 +377,7 @@ public class EntityValue extends Value StatusEffectInstance pe = ((LivingEntity) e).getStatusEffect(potion); return ListValue.of( new NumericValue(pe.getAmplifier()), new NumericValue(pe.getDuration()) ); }); + put("health", (e, a) -> { if (e instanceof LivingEntity) @@ -531,8 +533,6 @@ public class EntityValue extends Value //((ServerWorld)e.getEntityWorld()).method_14178().sendToNearbyPlayers(e, new EntityVelocityUpdateS2CPacket(e)); } - - private static final Map> featureModifiers = new HashMap>() {{ put("remove", (entity, value) -> entity.remove()); put("age", (e, v) -> e.age = Math.abs((int)NumericValue.asNumber(v).getLong()) ); @@ -896,25 +896,27 @@ public class EntityValue extends Value }); put("gamemode", (e,v)->{ - if(!(e instanceof ServerPlayerEntity)){ - return; - } - switch(v.getString().toLowerCase()){ - case "survival": case "0":((ServerPlayerEntity) e).setGameMode(GameMode.SURVIVAL);break; - case "creative": case "1":((ServerPlayerEntity) e).setGameMode(GameMode.CREATIVE);break; - case "adventure": case "2":((ServerPlayerEntity) e).setGameMode(GameMode.ADVENTURE);break; - case "spectator": case "3":((ServerPlayerEntity) e).setGameMode(GameMode.SPECTATOR);break; - } + if(!(e instanceof ServerPlayerEntity)) return; + GameMode toSet = v instanceof NumericValue ? + GameMode.byId(((NumericValue) v).getInt(), null) : + GameMode.byName(v.getString().toLowerCase(Locale.ROOT), null); + if (toSet != null) ((ServerPlayerEntity) e).setGameMode(toSet); }); put("jumping",(e,v)->{ if(!(e instanceof LivingEntity)) return; - ((LivingEntity) e).setJumping(v.getBoolean()); }); put("jump",(e,v)->{ - jump((LivingEntity)e); + if (e instanceof LivingEntity) + { + ((LivingEntityInterface)e).doJumpCM(); + } + else + { + genericJump(e); + } }); put("silent",(e,v)->{ @@ -933,10 +935,6 @@ public class EntityValue extends Value e.setFireTicks((int)NumericValue.asNumber(v).getLong()); }); - put("age",(e,v)->{ - e.age=(int)NumericValue.asNumber(v).getLong(); - }); - // gamemode [check] // spectate [check] // "fire" [check] diff --git a/src/main/java/carpet/utils/MobAI.java b/src/main/java/carpet/utils/MobAI.java index 77c4fd94..dc4b3e03 100644 --- a/src/main/java/carpet/utils/MobAI.java +++ b/src/main/java/carpet/utils/MobAI.java @@ -7,6 +7,7 @@ import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.effect.StatusEffects; import net.minecraft.server.world.ServerWorld; +import net.minecraft.tag.FluidTags; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; @@ -98,23 +99,24 @@ public class MobAI } } - public static void jump(LivingEntity e){//Most *REDACTED* up code in the world + /** + * Not a replacement for living entity jump() - this barely is to allow other entities that can't jump in vanilla to 'jump' + * @param e + */ + public static void genericJump(Entity e) + { + if (!e.onGround && !e.isInFluid(FluidTags.WATER) && !e.isInLava()) return; float m = e.world.getBlockState(new BlockPos(e)).getBlock().getJumpVelocityMultiplier(); float g = e.world.getBlockState(new BlockPos(e.getX(), e.getBoundingBox().y1 - 0.5000001D, e.getZ())).getBlock().getJumpVelocityMultiplier(); - float JumpVelocityMultiplier= (double)m == 1.0D ? g : m; - - float f = (0.42F * JumpVelocityMultiplier); - if (e.hasStatusEffect(StatusEffects.JUMP_BOOST)) { - f += 0.1F * (float)(e.getStatusEffect(StatusEffects.JUMP_BOOST).getAmplifier() + 1); - } - + float jumpVelocityMultiplier = (double) m == 1.0D ? g : m; + float jumpStrength = (0.42F * jumpVelocityMultiplier); Vec3d vec3d = e.getVelocity(); - e.setVelocity(vec3d.x, f, vec3d.z); - if (e.isSprinting()) { + e.setVelocity(vec3d.x, jumpStrength, vec3d.z); + if (e.isSprinting()) + { float u = e.yaw * 0.017453292F; e.setVelocity(e.getVelocity().add((-MathHelper.sin(g) * 0.2F), 0.0D, (MathHelper.cos(u) * 0.2F))); } - e.velocityDirty = true; } From 95d97608c2b75c362f56febb5cc2bb71763fa80c Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 29 Apr 2020 11:37:54 -0300 Subject: [PATCH 100/198] added format to editor support files --- docs/scarpet/resources/editors/idea/2.txt | 1 + docs/scarpet/resources/editors/npp/scarpet.xml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/scarpet/resources/editors/idea/2.txt b/docs/scarpet/resources/editors/idea/2.txt index edcf56fb..f12cde37 100644 --- a/docs/scarpet/resources/editors/idea/2.txt +++ b/docs/scarpet/resources/editors/idea/2.txt @@ -25,6 +25,7 @@ entity_list entity_selector escape_nbt flammable +format game_tick generation_status hardness diff --git a/docs/scarpet/resources/editors/npp/scarpet.xml b/docs/scarpet/resources/editors/npp/scarpet.xml index 8ad6f2ea..33be1144 100644 --- a/docs/scarpet/resources/editors/npp/scarpet.xml +++ b/docs/scarpet/resources/editors/npp/scarpet.xml @@ -65,7 +65,7 @@ scan volume neighbours rect diamond - logger sound particle particle_line particle_rect + format logger sound particle particle_line particle_rect run save tick_time world_time day_time last_tick_times game_tick seed current_dimension in_dimension From 2fe5ed615ef74da39452e8cea75cebe841b175df Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 30 Apr 2020 00:44:46 -0300 Subject: [PATCH 101/198] fog off client command added --- src/main/java/carpet/CarpetSettings.java | 7 ++++++ .../mixins/WorldRenderer_fogOffMixin.java | 23 +++++++++++++++++++ src/main/resources/carpet.mixins.json | 3 ++- 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/main/java/carpet/mixins/WorldRenderer_fogOffMixin.java diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index 1d7c7010..b9fd1f54 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -573,4 +573,11 @@ public class CarpetSettings category = CREATIVE ) public static boolean extremeBehaviours = false; + + @Rule( + desc = "Removes fog from client in the nether and the end", + extra = "Improves visibility, but looks weird", + category = CLIENT + ) + public static boolean fogOff = false; } diff --git a/src/main/java/carpet/mixins/WorldRenderer_fogOffMixin.java b/src/main/java/carpet/mixins/WorldRenderer_fogOffMixin.java new file mode 100644 index 00000000..a620c194 --- /dev/null +++ b/src/main/java/carpet/mixins/WorldRenderer_fogOffMixin.java @@ -0,0 +1,23 @@ +package carpet.mixins; + +import carpet.CarpetSettings; +import net.minecraft.client.render.WorldRenderer; +import net.minecraft.world.dimension.Dimension; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(value = WorldRenderer.class, priority = 69420) +public class WorldRenderer_fogOffMixin +{ + @Redirect(method = "render", require = 0, expect = 0, at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/dimension/Dimension;isFogThick(II)Z" + )) + private boolean isReallyThick(Dimension dimension, int x, int z) + { + if (CarpetSettings.fogOff) return false; + return dimension.isFogThick(x, z); + } + +} diff --git a/src/main/resources/carpet.mixins.json b/src/main/resources/carpet.mixins.json index 80faf7b8..ead13568 100644 --- a/src/main/resources/carpet.mixins.json +++ b/src/main/resources/carpet.mixins.json @@ -168,7 +168,8 @@ "PlayerListHudMixin", "PistonBlockEntityRenderer_movableTEMixin", "ClientPlayNetworkHandler_smoothClientAnimationsMixin", - "ClientPlayerEntity_clientCommandMixin" + "ClientPlayerEntity_clientCommandMixin", + "WorldRenderer_fogOffMixin" ], "server": [ "MinecraftDedicatedServerMixin" From 4e17f2277e203e403f97f79574e525e68fa66322 Mon Sep 17 00:00:00 2001 From: Ghoulboy Date: Thu, 30 Apr 2020 13:26:15 +0200 Subject: [PATCH 102/198] fixed typo (#256) * fixed typo * more typo --- docs/scarpet/Full.md | 2 +- docs/scarpet/api/Entities.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index 47e2c59c..5304d3ff 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -2413,7 +2413,7 @@ Entity that `e` rides. List of entity tags. -### `query(e,'has_tags',tag)` +### `query(e,'has_tag',tag)` Boolean, True if the entity is marked with `tag`. diff --git a/docs/scarpet/api/Entities.md b/docs/scarpet/api/Entities.md index a0dec45d..0f288bfa 100644 --- a/docs/scarpet/api/Entities.md +++ b/docs/scarpet/api/Entities.md @@ -152,7 +152,7 @@ Entity that `e` rides. List of entity tags. -### `query(e,'has_tags',tag)` +### `query(e,'has_tag',tag)` Boolean, True if the entity is marked with `tag`. From dbb29cbeb9b33b1efbec137e87c76b2b8555df66 Mon Sep 17 00:00:00 2001 From: gnembon Date: Sat, 2 May 2020 12:47:07 -0300 Subject: [PATCH 103/198] multiline stings cause tokens to offset incorrectly error messages --- src/main/java/carpet/script/Tokenizer.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/carpet/script/Tokenizer.java b/src/main/java/carpet/script/Tokenizer.java index fa1890c0..f0c1d4eb 100644 --- a/src/main/java/carpet/script/Tokenizer.java +++ b/src/main/java/carpet/script/Tokenizer.java @@ -201,6 +201,11 @@ public class Tokenizer implements Iterator { token.append(input.charAt(pos++)); linepos++; + if (ch=='\n') + { + lineno++; + linepos = 0; + } if (pos == input.length() && expression != null && context != null) throw new ExpressionException(context, this.expression, token, "Program truncated"); } From 300e963b0b3007be1865d3ad468186268bd4b152 Mon Sep 17 00:00:00 2001 From: gnembon Date: Sat, 2 May 2020 14:44:11 -0300 Subject: [PATCH 104/198] biome and structure calls should only request status they need. --- src/main/java/carpet/script/CarpetExpression.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 03e42147..85837f2d 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -1088,7 +1088,7 @@ public class CarpetExpression throw new InternalExpressionException("Unknown biome: "+biomeName); ServerWorld world = cc.s.getWorld(); BlockPos pos = locator.block.getPos(); - Chunk chunk = world.getChunk(pos); + Chunk chunk = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.BIOMES); ((BiomeArrayInterface)chunk.getBiomeArray()).setBiomeAtIndex(pos, world, biome); this.forceChunkUpdate(pos, world); return LazyValue.NULL; @@ -1099,7 +1099,7 @@ public class CarpetExpression BlockArgument locator = BlockArgument.findIn(cc, lv, 0); ServerWorld world = cc.s.getWorld(); BlockPos pos = locator.block.getPos(); - Map references = world.getChunk(pos).getStructureReferences(); + Map references = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.STRUCTURE_REFERENCES).getStructureReferences(); if (lv.size() == locator.offset) { List referenceList = references.entrySet().stream(). @@ -1125,7 +1125,7 @@ public class CarpetExpression ServerWorld world = cc.s.getWorld(); BlockPos pos = locator.block.getPos(); - Map structures = world.getChunk(pos).getStructureStarts(); + Map structures = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.STRUCTURE_STARTS).getStructureStarts(); if (lv.size() == locator.offset) { Map structureList = new HashMap<>(); From 3821af4f82247f3947fd843c24da8183e1663493 Mon Sep 17 00:00:00 2001 From: gnembon Date: Sat, 2 May 2020 19:14:59 -0300 Subject: [PATCH 105/198] structure_eligibility and notes on spawn_potential --- docs/scarpet/Full.md | 19 ++++++ docs/scarpet/api/BlocksAndWorldAccess.md | 19 ++++++ .../java/carpet/helpers/FeatureGenerator.java | 58 ++++++++++++++----- .../java/carpet/script/CarpetExpression.java | 52 +++++++++++++++++ 4 files changed, 133 insertions(+), 15 deletions(-) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index 5304d3ff..ad406637 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -2060,6 +2060,25 @@ if the chunk is not in memory unless called with optional `true`. Returns inhabited time for a chunk. +### `spawn_potential(pos)` + +Returns spawn potential at a location (1.16+ only) + +### `structure_eligibility(pos, ?structure, ?size_needed)` + +Checks wordgen eligibility for a structure in a given chunk. If no structure is given, or `null`, then it will check + for all structures. If bounding box of the structures is also requested, it will compute size of potential + structures. This function, unlike other in the `structure*` category is not using world data nor accesses chunks + making it preferred for scoping ungenerated terrain. + +If structure is specified, it will return `null` if a chunk is not eligible, `true` if the structure should appear, or +a pair of coordinates indicating bounding box of the structure. + +If structure is not specified, it will return a set of structure names that are eligible, or a map with structures +as keys, and pair of bounding box coordinates as values. An empty set or an empty map would indicate that nothing +should be generated there. + + ### `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/BlocksAndWorldAccess.md b/docs/scarpet/api/BlocksAndWorldAccess.md index 0847bbbf..17145b86 100644 --- a/docs/scarpet/api/BlocksAndWorldAccess.md +++ b/docs/scarpet/api/BlocksAndWorldAccess.md @@ -523,6 +523,25 @@ if the chunk is not in memory unless called with optional `true`. Returns inhabited time for a chunk. +### `spawn_potential(pos)` + +Returns spawn potential at a location (1.16+ only) + +### `structure_eligibility(pos, ?structure, ?size_needed)` + +Checks wordgen eligibility for a structure in a given chunk. If no structure is given, or `null`, then it will check + for all structures. If bounding box of the structures is also requested, it will compute size of potential + structures. This function, unlike other in the `structure*` category is not using world data nor accesses chunks + making it preferred for scoping ungenerated terrain. + +If structure is specified, it will return `null` if a chunk is not eligible, `true` if the structure should appear, or +a pair of coordinates indicating bounding box of the structure. + +If structure is not specified, it will return a set of structure names that are eligible, or a map with structures +as keys, and pair of bounding box coordinates as values. An empty set or an empty map would indicate that nothing +should be generated there. + + ### `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/src/main/java/carpet/helpers/FeatureGenerator.java b/src/main/java/carpet/helpers/FeatureGenerator.java index eb8caf20..6aaeea78 100644 --- a/src/main/java/carpet/helpers/FeatureGenerator.java +++ b/src/main/java/carpet/helpers/FeatureGenerator.java @@ -6,13 +6,19 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Sets; import net.minecraft.block.Blocks; import net.minecraft.server.world.ServerWorld; +import net.minecraft.structure.StructureManager; +import net.minecraft.structure.StructureStart; +import net.minecraft.util.math.BlockBox; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.Biomes; import net.minecraft.world.biome.DefaultBiomeFeatures; +import net.minecraft.world.biome.source.BiomeAccess; import net.minecraft.world.biome.source.BiomeSource; import net.minecraft.world.biome.source.VanillaLayeredBiomeSource; import net.minecraft.world.biome.source.VanillaLayeredBiomeSourceConfig; +import net.minecraft.world.gen.ChunkRandom; import net.minecraft.world.gen.chunk.ChunkGenerator; import net.minecraft.world.gen.chunk.OverworldChunkGenerator; import net.minecraft.world.gen.chunk.OverworldChunkGeneratorConfig; @@ -141,26 +147,48 @@ public class FeatureGenerator return null; } + public static BlockBox DEFAULT_BOX = new BlockBox(0,0,0,1,1,1); + public static BlockBox shouldStructureStartAt(ServerWorld world, BlockPos pos, StructureFeature structure, boolean computeBox) + { + ChunkGenerator generator = world.getChunkManager().getChunkGenerator(); + if (!generator.getBiomeSource().hasStructureFeature(structure)) + return null; + BiomeAccess biomeAccess = world.getBiomeAccess().withSource(generator.getBiomeSource()); + ChunkRandom chunkRandom = new ChunkRandom(); + ChunkPos chunkPos = new ChunkPos(pos); + Biome biome = biomeAccess.getBiome(new BlockPos(chunkPos.getStartX() + 9, 0, chunkPos.getStartZ() + 9)); + if (structure.shouldStartAt(biomeAccess, generator, chunkRandom, chunkPos.x, chunkPos.z, biome)) + { + if (!computeBox) return DEFAULT_BOX; + StructureManager manager = world.getSaveHandler().getStructureManager(); + StructureStart structureStart3 = structure.getStructureStartFactory().create(structure, chunkPos.x, chunkPos.z, BlockBox.empty(), 0, generator.getSeed()); + structureStart3.initialize(generator, manager, chunkPos.x, chunkPos.z, biome); + if (!structureStart3.hasChildren()) return null; + return structureStart3.getBoundingBox(); + } + return null; + } + public static final Map> structureToFeature = new HashMap<>(); public static final Map featureToStructure = new HashMap<>(); static { - structureToFeature.put("Monument", Collections.singletonList("monument")); - structureToFeature.put("EndCity", Collections.singletonList("end_city")); - structureToFeature.put("Ocean_Ruin", Arrays.asList("ocean_ruin", "ocean_ruin_warm", "ocean_ruin_small", "ocean_ruin_warm_small", "ocean_ruin_tall", "ocean_ruin_warm_tall")); - structureToFeature.put("Village", Arrays.asList("village", "village_desert", "village_savanna", "village_taiga", "village_snowy")); - structureToFeature.put("Mansion", Collections.singletonList("mansion")); - structureToFeature.put("Buried_Treasure", Collections.singletonList("treasure")); - structureToFeature.put("Swamp_Hut", Collections.singletonList("witch_hut")); - structureToFeature.put("Stronghold", Collections.singletonList("stronghold")); - structureToFeature.put("Desert_Pyramid", Collections.singletonList("desert_temple")); - structureToFeature.put("Jungle_Pyramid", Collections.singletonList("jungle_temple")); - structureToFeature.put("Shipwreck", Arrays.asList("shipwreck", "shipwreck2")); - structureToFeature.put("Pillager_Outpost", Collections.singletonList("pillager_outpost")); - structureToFeature.put("Mineshaft", Arrays.asList("mineshaft", "mineshaft_mesa")); - structureToFeature.put("Igloo", Collections.singletonList("igloo")); - structureToFeature.put("Fortress", Collections.singletonList("fortress")); + structureToFeature.put(Feature.OCEAN_MONUMENT.getName(), Collections.singletonList("monument")); + structureToFeature.put(Feature.END_CITY.getName(), Collections.singletonList("end_city")); + structureToFeature.put(Feature.OCEAN_RUIN.getName(), Arrays.asList("ocean_ruin", "ocean_ruin_warm", "ocean_ruin_small", "ocean_ruin_warm_small", "ocean_ruin_tall", "ocean_ruin_warm_tall")); + structureToFeature.put(Feature.VILLAGE.getName(), Arrays.asList("village", "village_desert", "village_savanna", "village_taiga", "village_snowy")); + structureToFeature.put(Feature.WOODLAND_MANSION.getName(), Collections.singletonList("mansion")); + structureToFeature.put(Feature.BURIED_TREASURE.getName(), Collections.singletonList("treasure")); + structureToFeature.put(Feature.SWAMP_HUT.getName(), Collections.singletonList("witch_hut")); + structureToFeature.put(Feature.STRONGHOLD.getName(), Collections.singletonList("stronghold")); + structureToFeature.put(Feature.DESERT_PYRAMID.getName(), Collections.singletonList("desert_temple")); + structureToFeature.put(Feature.JUNGLE_TEMPLE.getName(), Collections.singletonList("jungle_temple")); + structureToFeature.put(Feature.SHIPWRECK.getName(), Arrays.asList("shipwreck", "shipwreck2")); + structureToFeature.put(Feature.PILLAGER_OUTPOST.getName(), Collections.singletonList("pillager_outpost")); + structureToFeature.put(Feature.MINESHAFT.getName(), Arrays.asList("mineshaft", "mineshaft_mesa")); + structureToFeature.put(Feature.IGLOO.getName(), Collections.singletonList("igloo")); + structureToFeature.put(Feature.NETHER_BRIDGE.getName(), Collections.singletonList("fortress")); structureToFeature.forEach((key, value) -> value.forEach(el -> featureToStructure.put(el, key))); } diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 85837f2d..8af5adf7 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -111,6 +111,8 @@ import net.minecraft.util.math.BlockBox; import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3i; import net.minecraft.util.registry.Registry; +import net.minecraft.world.gen.feature.Feature; +import net.minecraft.world.gen.feature.StructureFeature; import net.minecraft.world.poi.PointOfInterest; import net.minecraft.world.poi.PointOfInterestStorage; import net.minecraft.world.poi.PointOfInterestType; @@ -1119,6 +1121,56 @@ public class CarpetExpression return (_c, _t) -> ret; }); + this.expr.addLazyFunction("structure_eligibility", -1, (c, t, lv) -> + { + CarpetContext cc = (CarpetContext)c; + BlockArgument locator = BlockArgument.findIn(cc, lv, 0); + + ServerWorld world = cc.s.getWorld(); + BlockPos pos = locator.block.getPos(); + StructureFeature structure = null; + boolean needSize = false; + if (lv.size() > locator.offset) + { + Value requested = lv.get(locator.offset+0).evalValue(c); + if (!(requested instanceof NullValue)) + { + String reqString = requested.getString(); + String structureName = FeatureGenerator.featureToStructure.get(reqString); + if (structureName == null) throw new InternalExpressionException("Unknown structure: " + reqString); + structure = Feature.STRUCTURES.get(structureName); + } + if (lv.size() > locator.offset+1) + { + needSize = lv.get(locator.offset+1).evalValue(c).getBoolean(); + } + } + if (structure != null) + { + BlockBox box = FeatureGenerator.shouldStructureStartAt(world, pos, structure, needSize); + if (box == null) return LazyValue.NULL; + if (!needSize) return LazyValue.TRUE; + Value ret = ListValue.of( + ListValue.of(new NumericValue(box.minX), new NumericValue(box.minY), new NumericValue(box.minZ)), + ListValue.of(new NumericValue(box.minX), new NumericValue(box.minY), new NumericValue(box.minZ)) + ); + return (_c, _t) -> ret; + } + Map ret = new HashMap<>(); + for(StructureFeature str : Feature.STRUCTURES.values()) + { + BlockBox box = FeatureGenerator.shouldStructureStartAt(world, pos, str, needSize); + if (box == null) continue; + Value key = new StringValue(FeatureGenerator.structureToFeature.get(str.getName()).get(0)); + ret.put(key, (!needSize)?Value.NULL:ListValue.of( + ListValue.of(new NumericValue(box.minX), new NumericValue(box.minY), new NumericValue(box.minZ)), + ListValue.of(new NumericValue(box.minX), new NumericValue(box.minY), new NumericValue(box.minZ)) + )); + } + Value retMap = MapValue.wrap(ret); + return (_c, _t) -> retMap; + }); + this.expr.addLazyFunction("structures", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; BlockArgument locator = BlockArgument.findIn(cc, lv, 0); From 2ec095a1bfb558c02e667c7ee4c7af054e8ddb73 Mon Sep 17 00:00:00 2001 From: gnembon Date: Sat, 2 May 2020 20:19:19 -0300 Subject: [PATCH 106/198] oupsie --- docs/scarpet/resources/editors/idea/2.txt | 2 ++ docs/scarpet/resources/editors/npp/scarpet.xml | 4 ++-- src/main/java/carpet/script/CarpetExpression.java | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/scarpet/resources/editors/idea/2.txt b/docs/scarpet/resources/editors/idea/2.txt index f12cde37..15f9ee89 100644 --- a/docs/scarpet/resources/editors/idea/2.txt +++ b/docs/scarpet/resources/editors/idea/2.txt @@ -86,10 +86,12 @@ sky_light solid sound spawn +spawn_potential stack_limit statistic store_app_data structures +structure_eligibility structure_references suffocates tick_time diff --git a/docs/scarpet/resources/editors/npp/scarpet.xml b/docs/scarpet/resources/editors/npp/scarpet.xml index 33be1144..3994ced4 100644 --- a/docs/scarpet/resources/editors/npp/scarpet.xml +++ b/docs/scarpet/resources/editors/npp/scarpet.xml @@ -54,8 +54,8 @@ 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 inhabited_time chunk_tickets - structures structure_references set_structure reset_chunk + place_item set_biome biome loaded_status generation_status inhabited_time spawn_potential chunk_tickets + structure_eligibility structures structure_references set_structure reset_chunk scoreboard scoreboard_add scoreboard_remove scoreboard_display diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 8af5adf7..c5e71780 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -1152,7 +1152,7 @@ public class CarpetExpression if (!needSize) return LazyValue.TRUE; Value ret = ListValue.of( ListValue.of(new NumericValue(box.minX), new NumericValue(box.minY), new NumericValue(box.minZ)), - ListValue.of(new NumericValue(box.minX), new NumericValue(box.minY), new NumericValue(box.minZ)) + ListValue.of(new NumericValue(box.maxX), new NumericValue(box.maxY), new NumericValue(box.maxZ)) ); return (_c, _t) -> ret; } @@ -1164,7 +1164,7 @@ public class CarpetExpression Value key = new StringValue(FeatureGenerator.structureToFeature.get(str.getName()).get(0)); ret.put(key, (!needSize)?Value.NULL:ListValue.of( ListValue.of(new NumericValue(box.minX), new NumericValue(box.minY), new NumericValue(box.minZ)), - ListValue.of(new NumericValue(box.minX), new NumericValue(box.minY), new NumericValue(box.minZ)) + ListValue.of(new NumericValue(box.maxX), new NumericValue(box.maxY), new NumericValue(box.maxZ)) )); } Value retMap = MapValue.wrap(ret); From 15ac3edc19fff718ae0b3511c448fcd0076f34de Mon Sep 17 00:00:00 2001 From: gnembon Date: Sun, 3 May 2020 23:10:09 -0300 Subject: [PATCH 107/198] clarifications around 'str' --- docs/scarpet/language/SystemFunctions.md | 13 ++++++++++--- src/main/java/carpet/script/Expression.java | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/scarpet/language/SystemFunctions.md b/docs/scarpet/language/SystemFunctions.md index e25b48ba..611057d2 100644 --- a/docs/scarpet/language/SystemFunctions.md +++ b/docs/scarpet/language/SystemFunctions.md @@ -46,15 +46,22 @@ number('3bar') => null number('2')+number('2') => 4 -### `str(expr, params? ... ), str(expr, param_list)` +### `str(expr)`,`str(expr, params? ... )`, `str(expr, param_list)` -Returns a formatted string representing expression. Accepts formatting style accepted by `String.format`. -Supported types (with `"%?"` syntax): +If called with one argument, returns string representation of such value. + +Otherwise, returns a formatted string representing the expression. Arguments for formatting can either be provided as + each consecutive parameter, or as a list which then would be the only extra parameter. To format one list argument + , you can use `str(list)`, or `str('foo %s', l(list))`. + +Accepts formatting style accepted by `String.format`. +Supported types (with `"%"` syntax): * `d`, `o`, `x`: integers, octal, hex * `a`, `e`, `f`, `g`: floats * `b`: booleans * `s`: strings +* `%%`: '%' character
 str(null) => null
diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java
index daf0a4cf..6d5174c5 100644
--- a/src/main/java/carpet/script/Expression.java
+++ b/src/main/java/carpet/script/Expression.java
@@ -1575,7 +1575,7 @@ public class Expression
             if (lv.size() == 1)
                 return new StringValue(format);
             int argIndex = 1;
-            if (lv.get(1) instanceof ListValue)
+            if (lv.get(1) instanceof ListValue && lv.size() == 2)
             {
                 lv = ((ListValue) lv.get(1)).getItems();
                 argIndex = 0;

From ad43784ad6ddcce862ff637e4748c7acd19c7f99 Mon Sep 17 00:00:00 2001
From: gnembon 
Date: Mon, 4 May 2020 15:48:45 -0300
Subject: [PATCH 108/198] unify structure info.

---
 docs/scarpet/Full.md                          | 26 ++++++--
 docs/scarpet/api/BlocksAndWorldAccess.md      | 13 ++--
 .../java/carpet/helpers/FeatureGenerator.java |  9 ++-
 .../java/carpet/script/CarpetExpression.java  | 66 +++++++++++--------
 .../java/carpet/script/value/ListValue.java   | 12 ++++
 .../assets/carpet/scripts/overlay.sc          |  2 +-
 6 files changed, 83 insertions(+), 45 deletions(-)

diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md
index ad406637..4e0ea027 100644
--- a/docs/scarpet/Full.md
+++ b/docs/scarpet/Full.md
@@ -689,15 +689,22 @@ number('3bar') => null
 number('2')+number('2') => 4
 
-### `str(expr, params? ... ), str(expr, param_list)` +### `str(expr)`,`str(expr, params? ... )`, `str(expr, param_list)` -Returns a formatted string representing expression. Accepts formatting style accepted by `String.format`. -Supported types (with `"%?"` syntax): +If called with one argument, returns string representation of such value. + +Otherwise, returns a formatted string representing the expression. Arguments for formatting can either be provided as + each consecutive parameter, or as a list which then would be the only extra parameter. To format one list argument + , you can use `str(list)`, or `str('foo %s', l(list))`. + +Accepts formatting style accepted by `String.format`. +Supported types (with `"%"` syntax): * `d`, `o`, `x`: integers, octal, hex * `a`, `e`, `f`, `g`: floats * `b`: booleans * `s`: strings +* `%%`: '%' character
 str(null) => null
@@ -2069,13 +2076,17 @@ Returns spawn potential at a location (1.16+ only)
 Checks wordgen eligibility for a structure in a given chunk. If no structure is given, or `null`, then it will check
  for all structures. If bounding box of the structures is also requested, it will compute size of potential
   structures. This function, unlike other in the `structure*` category is not using world data nor accesses chunks
-  making it preferred for scoping ungenerated terrain.
+  making it preferred for scoping ungenerated terrain, but it takes some compute money to calculate the structure.
+  
+  Unlike `'structure'` this will return a tentative structure location. Random factors in world generation may prevent
+  actual structure from forming.
   
 If structure is specified, it will return `null` if a chunk is not eligible, `true` if the structure should appear, or 
-a pair of coordinates indicating bounding box of the structure.
+a map with two values: `'box'` for a pair of coordinates indicating bounding box of the structure, and `'pieces'` for 
+list of elements of the structure (as a tuple), with its name, direction, and box coordinates of the piece.
 
 If structure is not specified, it will return a set of structure names that are eligible, or a map with structures
-as keys, and pair of bounding box coordinates as values. An empty set or an empty map would indicate that nothing
+as keys, and same type of map values as with a single structure call. An empty set or an empty map would indicate that nothing
 should be generated there.
 
 
@@ -2085,7 +2096,8 @@ Returns structure information for a given block position. Note that structure in
 blocks from the same chunk. `structures` function can be called with a block, or a block and a structure name. In 
 the first case it returns a map of structures at a given position, keyed by structure name, with values indicating 
 the bounding box of the structure - a pair of two 3-value coords (see examples). When called with an extra structure 
-name, returns list of components for that structure, with their name, direction and two sets of coordinates 
+name, returns a map with two values, `'box'` for bounding box of the structure, and `'pieces'` for a list of 
+components for that structure, with their name, direction and two sets of coordinates 
 indicating the bounding box of the structure piece.
 
 ### `structure_references(pos), structure_references(pos, structure_name)`
diff --git a/docs/scarpet/api/BlocksAndWorldAccess.md b/docs/scarpet/api/BlocksAndWorldAccess.md
index 17145b86..e6ae9e39 100644
--- a/docs/scarpet/api/BlocksAndWorldAccess.md
+++ b/docs/scarpet/api/BlocksAndWorldAccess.md
@@ -532,13 +532,17 @@ Returns spawn potential at a location (1.16+ only)
 Checks wordgen eligibility for a structure in a given chunk. If no structure is given, or `null`, then it will check
  for all structures. If bounding box of the structures is also requested, it will compute size of potential
   structures. This function, unlike other in the `structure*` category is not using world data nor accesses chunks
-  making it preferred for scoping ungenerated terrain.
+  making it preferred for scoping ungenerated terrain, but it takes some compute money to calculate the structure.
+  
+  Unlike `'structure'` this will return a tentative structure location. Random factors in world generation may prevent
+  actual structure from forming.
   
 If structure is specified, it will return `null` if a chunk is not eligible, `true` if the structure should appear, or 
-a pair of coordinates indicating bounding box of the structure.
+a map with two values: `'box'` for a pair of coordinates indicating bounding box of the structure, and `'pieces'` for 
+list of elements of the structure (as a tuple), with its name, direction, and box coordinates of the piece.
 
 If structure is not specified, it will return a set of structure names that are eligible, or a map with structures
-as keys, and pair of bounding box coordinates as values. An empty set or an empty map would indicate that nothing
+as keys, and same type of map values as with a single structure call. An empty set or an empty map would indicate that nothing
 should be generated there.
 
 
@@ -548,7 +552,8 @@ Returns structure information for a given block position. Note that structure in
 blocks from the same chunk. `structures` function can be called with a block, or a block and a structure name. In 
 the first case it returns a map of structures at a given position, keyed by structure name, with values indicating 
 the bounding box of the structure - a pair of two 3-value coords (see examples). When called with an extra structure 
-name, returns list of components for that structure, with their name, direction and two sets of coordinates 
+name, returns a map with two values, `'box'` for bounding box of the structure, and `'pieces'` for a list of 
+components for that structure, with their name, direction and two sets of coordinates 
 indicating the bounding box of the structure piece.
 
 ### `structure_references(pos), structure_references(pos, structure_name)`
diff --git a/src/main/java/carpet/helpers/FeatureGenerator.java b/src/main/java/carpet/helpers/FeatureGenerator.java
index 6aaeea78..4464ba4c 100644
--- a/src/main/java/carpet/helpers/FeatureGenerator.java
+++ b/src/main/java/carpet/helpers/FeatureGenerator.java
@@ -147,10 +147,9 @@ public class FeatureGenerator
         return null;
     }
 
-    public static BlockBox DEFAULT_BOX = new BlockBox(0,0,0,1,1,1);
-    public static BlockBox shouldStructureStartAt(ServerWorld world, BlockPos pos, StructureFeature structure, boolean computeBox)
+    public static StructureStart shouldStructureStartAt(ServerWorld world, BlockPos pos, StructureFeature structure, boolean computeBox)
     {
-        ChunkGenerator generator = world.getChunkManager().getChunkGenerator();
+        ChunkGenerator generator = world.getChunkManager().getChunkGenerator();
         if (!generator.getBiomeSource().hasStructureFeature(structure))
             return null;
         BiomeAccess biomeAccess = world.getBiomeAccess().withSource(generator.getBiomeSource());
@@ -159,12 +158,12 @@ public class FeatureGenerator
         Biome biome = biomeAccess.getBiome(new BlockPos(chunkPos.getStartX() + 9, 0, chunkPos.getStartZ() + 9));
         if (structure.shouldStartAt(biomeAccess, generator, chunkRandom, chunkPos.x, chunkPos.z, biome))
         {
-            if (!computeBox) return DEFAULT_BOX;
+            if (!computeBox) return StructureStart.DEFAULT;
             StructureManager manager = world.getSaveHandler().getStructureManager();
             StructureStart structureStart3 = structure.getStructureStartFactory().create(structure, chunkPos.x, chunkPos.z, BlockBox.empty(), 0, generator.getSeed());
             structureStart3.initialize(generator, manager, chunkPos.x, chunkPos.z, biome);
             if (!structureStart3.hasChildren()) return null;
-            return structureStart3.getBoundingBox();
+            return structureStart3;
         }
         return null;
     }
diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java
index c5e71780..0b0bd068 100644
--- a/src/main/java/carpet/script/CarpetExpression.java
+++ b/src/main/java/carpet/script/CarpetExpression.java
@@ -397,6 +397,32 @@ public class CarpetExpression
         }
     }
 
+
+
+    private static Value structureToValue(StructureStart structure)
+    {
+        if (structure == null || structure == StructureStart.DEFAULT) return Value.NULL;
+        List pieces = new ArrayList<>();
+        for (StructurePiece piece : structure.getChildren())
+        {
+            BlockBox box = piece.getBoundingBox();
+            pieces.add(ListValue.of(
+                    new StringValue( NBTSerializableValue.nameFromRegistryId(Registry.STRUCTURE_PIECE.getId(piece.getType()))),
+                    (piece.getFacing()== null)?Value.NULL: new StringValue(piece.getFacing().getName()),
+                    ListValue.fromTriple(box.minX, box.minY, box.minZ),
+                    ListValue.fromTriple(box.maxX, box.maxY, box.maxZ)
+            ));
+        };
+        BlockBox boundingBox = structure.getBoundingBox();
+        Map ret = new HashMap<>();
+        ret.put(new StringValue("box"), ListValue.of(
+                ListValue.fromTriple(boundingBox.minX, boundingBox.minY, boundingBox.minZ),
+                ListValue.fromTriple(boundingBox.maxX, boundingBox.maxY, boundingBox.maxZ)
+        ));
+        ret.put(new StringValue("pieces"), ListValue.wrap(pieces));
+        return MapValue.wrap(ret);
+    }
+
     private void API_BlockManipulation()
     {
         this.expr.addLazyFunction("block", -1, (c, t, lv) ->
@@ -1147,25 +1173,20 @@ public class CarpetExpression
             }
             if (structure != null)
             {
-                BlockBox box = FeatureGenerator.shouldStructureStartAt(world, pos, structure, needSize);
-                if (box == null) return LazyValue.NULL;
+                StructureStart start = FeatureGenerator.shouldStructureStartAt(world, pos, structure, needSize);
+                if (start == null) return LazyValue.NULL;
                 if (!needSize) return LazyValue.TRUE;
-                Value ret = ListValue.of(
-                        ListValue.of(new NumericValue(box.minX), new NumericValue(box.minY), new NumericValue(box.minZ)),
-                        ListValue.of(new NumericValue(box.maxX), new NumericValue(box.maxY), new NumericValue(box.maxZ))
-                );
+                Value ret = structureToValue(start);
                 return (_c, _t) -> ret;
             }
             Map ret = new HashMap<>();
             for(StructureFeature str : Feature.STRUCTURES.values())
             {
-                BlockBox box = FeatureGenerator.shouldStructureStartAt(world, pos, str, needSize);
-                if (box == null) continue;
+                StructureStart start = FeatureGenerator.shouldStructureStartAt(world, pos, str, needSize);
+                if (start == null) continue;
+
                 Value key = new StringValue(FeatureGenerator.structureToFeature.get(str.getName()).get(0));
-                ret.put(key, (!needSize)?Value.NULL:ListValue.of(
-                        ListValue.of(new NumericValue(box.minX), new NumericValue(box.minY), new NumericValue(box.minZ)),
-                        ListValue.of(new NumericValue(box.maxX), new NumericValue(box.maxY), new NumericValue(box.maxZ))
-                ));
+                ret.put(key, (!needSize)?Value.NULL:structureToValue(start));
             }
             Value retMap = MapValue.wrap(ret);
             return (_c, _t) -> retMap;
@@ -1187,28 +1208,17 @@ public class CarpetExpression
                     if (start == StructureStart.DEFAULT)
                         continue;
                     BlockBox box = start.getBoundingBox();
-                    ListValue coord1 = ListValue.of(new NumericValue(box.minX), new NumericValue(box.minY), new NumericValue(box.minZ));
-                    ListValue coord2 = ListValue.of(new NumericValue(box.maxX), new NumericValue(box.maxY), new NumericValue(box.maxZ));
-                    structureList.put(new StringValue(FeatureGenerator.structureToFeature.get(entry.getKey()).get(0)), ListValue.of(coord1, coord2));
+                    structureList.put(
+                            new StringValue(FeatureGenerator.structureToFeature.get(entry.getKey()).get(0)),
+                            ListValue.of(ListValue.fromTriple(box.minX, box.minY, box.minZ), ListValue.fromTriple(box.maxX, box.maxY, box.maxZ))
+                    );
                 }
                 Value ret = MapValue.wrap(structureList);
                 return (_c, _t) -> ret;
             }
             String structureName = lv.get(locator.offset).evalValue(c).getString().toLowerCase(Locale.ROOT);
             StructureStart start = structures.get(FeatureGenerator.featureToStructure.get(structureName));
-            if (start == null || start == StructureStart.DEFAULT) return LazyValue.NULL;
-            List pieces = new ArrayList<>();
-            for (StructurePiece piece : start.getChildren())
-            {
-                BlockBox box = piece.getBoundingBox();
-                pieces.add(ListValue.of(
-                        new StringValue( NBTSerializableValue.nameFromRegistryId(Registry.STRUCTURE_PIECE.getId(piece.getType()))),
-                        (piece.getFacing()== null)?Value.NULL: new StringValue(piece.getFacing().getName()),
-                        ListValue.of(new NumericValue(box.minX), new NumericValue(box.minY), new NumericValue(box.minZ)),
-                        ListValue.of(new NumericValue(box.maxX), new NumericValue(box.maxY), new NumericValue(box.maxZ))
-                ));
-            }
-            Value ret = ListValue.wrap(pieces);
+            Value ret = structureToValue(start);
             return (_c, _t) -> ret;
         });
 
diff --git a/src/main/java/carpet/script/value/ListValue.java b/src/main/java/carpet/script/value/ListValue.java
index 2d1ac5dc..e20d32b3 100644
--- a/src/main/java/carpet/script/value/ListValue.java
+++ b/src/main/java/carpet/script/value/ListValue.java
@@ -75,6 +75,18 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
         );
     }
 
+    public static Value fromTriple(double a, double b, double c)
+    {
+        return ListValue.of(new NumericValue(a), new NumericValue(b), new NumericValue(c));
+    }
+
+    public static Value fromTriple(int a, int b, int c)
+    {
+        return fromTriple((double) a, b, c);
+    }
+
+
+
 
     public static ListValue wrap(List list)
     {
diff --git a/src/main/resources/assets/carpet/scripts/overlay.sc b/src/main/resources/assets/carpet/scripts/overlay.sc
index 290a51f1..a2909b04 100644
--- a/src/main/resources/assets/carpet/scripts/overlay.sc
+++ b/src/main/resources/assets/carpet/scripts/overlay.sc
@@ -89,7 +89,7 @@ __structure_renderer(player_name) ->
 		for (starts, l(position, name) = _;
 		    structure_data = structures(position):name;
 		    if (!structure_data, continue()); // messed up references - shouldn't happen
-		    structure_pieces = structures(position, name);
+		    structure_pieces = structures(position, name):'pieces';
 		    if (!structure_pieces, continue()); // messed up references - shouldn't happen
 		    l(from, to) = structure_data;
 		    total_size = _euclidean(from, to);

From 440dc6e2f42fc129200097a95760a5eefc468978 Mon Sep 17 00:00:00 2001
From: gnembon 
Date: Mon, 4 May 2020 19:46:28 -0300
Subject: [PATCH 109/198] creative no clip

---
 src/main/java/carpet/CarpetSettings.java      |  6 ++
 ...PistonBlockEntity_creativeNoClipMixin.java | 29 ++++++++++
 .../PlayerEntity_creativeNoClipMixin.java     | 56 +++++++++++++++++++
 .../WorldRenderer_creativeNoClipMixin.java    | 19 +++++++
 src/main/resources/carpet.mixins.json         |  9 ++-
 5 files changed, 117 insertions(+), 2 deletions(-)
 create mode 100644 src/main/java/carpet/mixins/PistonBlockEntity_creativeNoClipMixin.java
 create mode 100644 src/main/java/carpet/mixins/PlayerEntity_creativeNoClipMixin.java
 create mode 100644 src/main/java/carpet/mixins/WorldRenderer_creativeNoClipMixin.java

diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java
index b9fd1f54..43ac7c1d 100644
--- a/src/main/java/carpet/CarpetSettings.java
+++ b/src/main/java/carpet/CarpetSettings.java
@@ -580,4 +580,10 @@ public class CarpetSettings
             category = CLIENT
     )
     public static boolean fogOff = false;
+
+    @Rule(
+            desc = "Creative No Clip",
+            category = {CREATIVE, CLIENT}
+    )
+    public static boolean creativeNoClip = false;
 }
diff --git a/src/main/java/carpet/mixins/PistonBlockEntity_creativeNoClipMixin.java b/src/main/java/carpet/mixins/PistonBlockEntity_creativeNoClipMixin.java
new file mode 100644
index 00000000..9e81659f
--- /dev/null
+++ b/src/main/java/carpet/mixins/PistonBlockEntity_creativeNoClipMixin.java
@@ -0,0 +1,29 @@
+package carpet.mixins;
+
+import carpet.CarpetSettings;
+import net.minecraft.block.entity.PistonBlockEntity;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.util.math.Direction;
+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.Redirect;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin(PistonBlockEntity.class)
+public class PistonBlockEntity_creativeNoClipMixin
+{
+    @Inject(method = "method_23672", at = @At("HEAD"), cancellable = true)
+    private static void dontPushSpectators(Direction direction, Entity entity, double d, Direction direction2, CallbackInfo ci)
+    {
+        if (CarpetSettings.creativeNoClip && entity instanceof PlayerEntity && (((PlayerEntity) entity).isCreative()) && ((PlayerEntity) entity).abilities.flying) ci.cancel();
+    }
+
+    @Redirect(method = "pushEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;setVelocity(DDD)V"))
+    private void ignoreAccel(Entity entity, double x, double y, double z)
+    {
+        if (CarpetSettings.creativeNoClip && entity instanceof PlayerEntity && (((PlayerEntity) entity).isCreative()) && ((PlayerEntity) entity).abilities.flying) return;
+        entity.setVelocity(x,y,z);
+    }
+}
diff --git a/src/main/java/carpet/mixins/PlayerEntity_creativeNoClipMixin.java b/src/main/java/carpet/mixins/PlayerEntity_creativeNoClipMixin.java
new file mode 100644
index 00000000..ea50dab4
--- /dev/null
+++ b/src/main/java/carpet/mixins/PlayerEntity_creativeNoClipMixin.java
@@ -0,0 +1,56 @@
+package carpet.mixins;
+
+import carpet.CarpetSettings;
+import net.minecraft.entity.EntityType;
+import net.minecraft.entity.LivingEntity;
+import net.minecraft.entity.MovementType;
+import net.minecraft.entity.player.PlayerAbilities;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.util.math.Vec3d;
+import net.minecraft.world.World;
+import org.spongepowered.asm.mixin.Final;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Redirect;
+
+@Mixin(PlayerEntity.class)
+public abstract class PlayerEntity_creativeNoClipMixin extends LivingEntity
+{
+    @Shadow public abstract boolean isCreative();
+
+    @Shadow @Final public PlayerAbilities abilities;
+
+    protected PlayerEntity_creativeNoClipMixin(EntityType type, World world)
+    {
+        super(type, world);
+    }
+
+    @Redirect(method = "tick", at = @At(
+            value = "INVOKE",
+            target = "Lnet/minecraft/entity/player/PlayerEntity;isSpectator()Z")
+    )
+    private boolean canClipTroughWorld(PlayerEntity playerEntity)
+    {
+        return playerEntity.isSpectator() || (CarpetSettings.creativeNoClip && playerEntity.isCreative() && playerEntity.abilities.flying);
+
+    }
+
+    @Redirect(method = "tickMovement", at = @At(
+            value = "INVOKE",
+            target = "Lnet/minecraft/entity/player/PlayerEntity;isSpectator()Z")
+    )
+    private boolean collidesWithEntities(PlayerEntity playerEntity)
+    {
+        return playerEntity.isSpectator() || (CarpetSettings.creativeNoClip && playerEntity.isCreative() && playerEntity.abilities.flying);
+    }
+
+    @Redirect(method = "updateSize", at = @At(
+            value = "INVOKE",
+            target = "Lnet/minecraft/entity/player/PlayerEntity;isSpectator()Z")
+    )
+    private boolean spectatorsDontPose(PlayerEntity playerEntity)
+    {
+        return playerEntity.isSpectator() || (CarpetSettings.creativeNoClip && playerEntity.isCreative() && playerEntity.abilities.flying);
+    }
+}
diff --git a/src/main/java/carpet/mixins/WorldRenderer_creativeNoClipMixin.java b/src/main/java/carpet/mixins/WorldRenderer_creativeNoClipMixin.java
new file mode 100644
index 00000000..4e8a8109
--- /dev/null
+++ b/src/main/java/carpet/mixins/WorldRenderer_creativeNoClipMixin.java
@@ -0,0 +1,19 @@
+package carpet.mixins;
+
+import carpet.CarpetSettings;
+import net.minecraft.client.network.ClientPlayerEntity;
+import net.minecraft.client.render.WorldRenderer;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Redirect;
+
+@Mixin(WorldRenderer.class)
+public class WorldRenderer_creativeNoClipMixin
+{
+    @Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isSpectator()Z"))
+    private boolean canSeeWorld(ClientPlayerEntity clientPlayerEntity)
+    {
+        return clientPlayerEntity.isSpectator() || (CarpetSettings.creativeNoClip && clientPlayerEntity.isCreative());
+    }
+
+}
diff --git a/src/main/resources/carpet.mixins.json b/src/main/resources/carpet.mixins.json
index ead13568..ce36d841 100644
--- a/src/main/resources/carpet.mixins.json
+++ b/src/main/resources/carpet.mixins.json
@@ -156,7 +156,10 @@
     "PistonBlockEntity_movableTEMixin",
     "World_movableTEMixin",
     "WorldChunk_movableTEMixin",
-    "PistonHandler_movableTEMixin"
+    "PistonHandler_movableTEMixin",
+    "PlayerEntity_creativeNoClipMixin",
+    "PistonBlockEntity_creativeNoClipMixin"
+
   ],
   "client": [
     "RenderTickCounter_tickSpeedMixin",
@@ -169,7 +172,9 @@
     "PistonBlockEntityRenderer_movableTEMixin",
     "ClientPlayNetworkHandler_smoothClientAnimationsMixin",
     "ClientPlayerEntity_clientCommandMixin",
-    "WorldRenderer_fogOffMixin"
+    "WorldRenderer_fogOffMixin",
+    "WorldRenderer_creativeNoClipMixin"
+
   ],
   "server": [
     "MinecraftDedicatedServerMixin"

From 771de74a03276a75d7100152b91428d520456108 Mon Sep 17 00:00:00 2001
From: gnembon 
Date: Mon, 4 May 2020 22:07:22 -0300
Subject: [PATCH 110/198] noclip can place blocks intersecting with sefl

---
 .../mixins/BlockItem_creativeNoClipMixin.java | 36 +++++++++++++++++++
 src/main/resources/carpet.mixins.json         |  3 +-
 2 files changed, 38 insertions(+), 1 deletion(-)
 create mode 100644 src/main/java/carpet/mixins/BlockItem_creativeNoClipMixin.java

diff --git a/src/main/java/carpet/mixins/BlockItem_creativeNoClipMixin.java b/src/main/java/carpet/mixins/BlockItem_creativeNoClipMixin.java
new file mode 100644
index 00000000..f8c84c69
--- /dev/null
+++ b/src/main/java/carpet/mixins/BlockItem_creativeNoClipMixin.java
@@ -0,0 +1,36 @@
+package carpet.mixins;
+
+import carpet.CarpetSettings;
+import net.minecraft.block.BlockState;
+import net.minecraft.entity.EntityContext;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.item.BlockItem;
+import net.minecraft.item.ItemPlacementContext;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.util.shape.VoxelShape;
+import net.minecraft.world.World;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Redirect;
+
+@Mixin(BlockItem.class)
+public class BlockItem_creativeNoClipMixin
+{
+    @Redirect(method = "canPlace", at = @At(
+            value = "INVOKE",
+            target = "Lnet/minecraft/world/World;canPlace(Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/entity/EntityContext;)Z"
+    ))
+    private boolean canSpectatingPlace(World world, BlockState state, BlockPos pos, EntityContext context,
+                                       ItemPlacementContext contextOuter, BlockState stateOuter)
+    {
+        PlayerEntity player = contextOuter.getPlayer();
+        if (CarpetSettings.creativeNoClip && player != null && player.isCreative() && player.abilities.flying)
+        {
+            // copy from canPlace
+            VoxelShape voxelShape = state.getCollisionShape(world, pos, context);
+            return voxelShape.isEmpty() || world.intersectsEntities(player, voxelShape.offset(pos.getX(), pos.getY(), pos.getZ()));
+
+        }
+        return world.canPlace(state, pos, context);
+    }
+}
diff --git a/src/main/resources/carpet.mixins.json b/src/main/resources/carpet.mixins.json
index ce36d841..f8e4b733 100644
--- a/src/main/resources/carpet.mixins.json
+++ b/src/main/resources/carpet.mixins.json
@@ -158,7 +158,8 @@
     "WorldChunk_movableTEMixin",
     "PistonHandler_movableTEMixin",
     "PlayerEntity_creativeNoClipMixin",
-    "PistonBlockEntity_creativeNoClipMixin"
+    "PistonBlockEntity_creativeNoClipMixin",
+    "BlockItem_creativeNoClipMixin"
 
   ],
   "client": [

From cfe1a9e729c79eec4fed379d93768a20b70d3bb9 Mon Sep 17 00:00:00 2001
From: gnembon 
Date: Mon, 4 May 2020 23:09:02 -0300
Subject: [PATCH 111/198] fix

---
 src/main/java/carpet/script/CarpetExpression.java | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java
index 0b0bd068..a2f8154a 100644
--- a/src/main/java/carpet/script/CarpetExpression.java
+++ b/src/main/java/carpet/script/CarpetExpression.java
@@ -1164,7 +1164,8 @@ public class CarpetExpression
                     String reqString = requested.getString();
                     String structureName = FeatureGenerator.featureToStructure.get(reqString);
                     if (structureName == null) throw new InternalExpressionException("Unknown structure: " + reqString);
-                    structure = Feature.STRUCTURES.get(structureName);
+                    structure = Feature.STRUCTURES.get(structureName.toLowerCase(Locale.ROOT));
+                    if (structure == null) throw new InternalExpressionException("Unsupported structure: " + structureName);
                 }
                 if (lv.size() > locator.offset+1)
                 {

From aade01a3b39964327cdbc191ac27a7f055769fc9 Mon Sep 17 00:00:00 2001
From: gnembon 
Date: Tue, 5 May 2020 17:18:04 -0300
Subject: [PATCH 112/198] place_item can use non-block items. fixes #260

---
 docs/scarpet/Full.md                          | 11 +++++--
 docs/scarpet/api/BlocksAndWorldAccess.md      | 11 +++++--
 .../java/carpet/script/CarpetExpression.java  | 32 +++++++++++++------
 3 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md
index 4e0ea027..97fccb91 100644
--- a/docs/scarpet/Full.md
+++ b/docs/scarpet/Full.md
@@ -1646,19 +1646,26 @@ __on_chunk_generated(x, z) -> (
 
 ### `place_item(item, pos, facing?, sneak?)`
 
-Places a given item in the world like it was placed by a player. Item names are default minecraft item name, 
+Uses a given item in the world like it was used by a player. Item names are default minecraft item name, 
 less the minecraft prefix. Default facing is 'up', but there are other options: 'down', 'north', 'east', 'south', 
 'west', but also there are other secondary directions important for placement of blocks like stairs, doors, etc. 
 Try experiment with options like 'north-up' which is placed facing north with cursor pointing to the upper part of the 
 block, or 'up-north', which means a block placed facing up (player looking down) and placed smidge away of the block 
 center towards north. Optional sneak is a boolean indicating if a player would be sneaking while placing the 
-block - this option only affects placement of chests and scaffolding at the moment. Returns true if placement was 
+block - this option only affects placement of chests and scaffolding at the moment. 
+
+Works with items that have the right-click effect on the block placed, `'like bone_meal`` on grass or axes on logs,
+but doesn't open chests / containers, so have no effect on interactive blocks, like TNT, comparators, etc.
+
+Returns true if placement/use was 
 successful, false otherwise.
 
 
 place_item('stone',x,y,z) // places a stone block on x,y,z block
 place_item('piston,x,y,z,'down') // places a piston facing down
 place_item('carrot',x,y,z) // attempts to plant a carrot plant. Returns true if could place carrots at that position.
+place_item('bone_meal',x,y,z) // attempts to bonemeal the ground.
+place_item('wooden_axe',x,y,z) // attempts to strip the log.
 
### `set_poi(pos, type, occupancy?)` diff --git a/docs/scarpet/api/BlocksAndWorldAccess.md b/docs/scarpet/api/BlocksAndWorldAccess.md index e6ae9e39..b9a67339 100644 --- a/docs/scarpet/api/BlocksAndWorldAccess.md +++ b/docs/scarpet/api/BlocksAndWorldAccess.md @@ -102,19 +102,26 @@ __on_chunk_generated(x, z) -> ( ### `place_item(item, pos, facing?, sneak?)` -Places a given item in the world like it was placed by a player. Item names are default minecraft item name, +Uses a given item in the world like it was used by a player. Item names are default minecraft item name, less the minecraft prefix. Default facing is 'up', but there are other options: 'down', 'north', 'east', 'south', 'west', but also there are other secondary directions important for placement of blocks like stairs, doors, etc. Try experiment with options like 'north-up' which is placed facing north with cursor pointing to the upper part of the block, or 'up-north', which means a block placed facing up (player looking down) and placed smidge away of the block center towards north. Optional sneak is a boolean indicating if a player would be sneaking while placing the -block - this option only affects placement of chests and scaffolding at the moment. Returns true if placement was +block - this option only affects placement of chests and scaffolding at the moment. + +Works with items that have the right-click effect on the block placed, `'like bone_meal`` on grass or axes on logs, +but doesn't open chests / containers, so have no effect on interactive blocks, like TNT, comparators, etc. + +Returns true if placement/use was successful, false otherwise.
 place_item('stone',x,y,z) // places a stone block on x,y,z block
 place_item('piston,x,y,z,'down') // places a piston facing down
 place_item('carrot',x,y,z) // attempts to plant a carrot plant. Returns true if could place carrots at that position.
+place_item('bone_meal',x,y,z) // attempts to bonemeal the ground.
+place_item('wooden_axe',x,y,z) // attempts to strip the log.
 
### `set_poi(pos, type, occupancy?)` diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index a2f8154a..99dd9628 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -98,6 +98,7 @@ import net.minecraft.state.property.Property; import net.minecraft.structure.StructurePiece; import net.minecraft.structure.StructureStart; import net.minecraft.text.LiteralText; +import net.minecraft.util.ActionResult; import net.minecraft.util.Clearable; import net.minecraft.util.Identifier; import net.minecraft.util.InvalidIdentifierException; @@ -1008,6 +1009,7 @@ public class CarpetExpression return success ? LazyValue.TRUE : LazyValue.FALSE; }); + // TODO rename to use_item this.expr.addLazyFunction("place_item", -1, (c, t, lv) -> { if (lv.size()<2) @@ -1023,18 +1025,28 @@ public class CarpetExpression boolean sneakPlace = false; if (lv.size() > locator.offset+1) sneakPlace = lv.get(locator.offset+1).evalValue(c).getBoolean(); - if (stackArg.getItem() instanceof BlockItem) + + BlockValue.PlacementContext ctx; + try { + ctx = BlockValue.PlacementContext.from(cc.s.getWorld(), where, facing, sneakPlace, stackArg.createStack(1, false)); + } + catch (CommandSyntaxException e) + { + throw new InternalExpressionException(e.getMessage()); + } + + if (!(stackArg.getItem() instanceof BlockItem)) + { + ActionResult useResult = ctx.getStack().useOnBlock(ctx); + if (useResult == ActionResult.CONSUME || useResult == ActionResult.SUCCESS) + { + return LazyValue.TRUE; + } + } + else + { // not sure we need special case for block items, since useOnBlock can do that as well BlockItem blockItem = (BlockItem) stackArg.getItem(); - BlockValue.PlacementContext ctx; - try - { - ctx = BlockValue.PlacementContext.from(cc.s.getWorld(), where, facing, sneakPlace, stackArg.createStack(1, false)); - } - catch (CommandSyntaxException e) - { - throw new InternalExpressionException(e.getMessage()); - } if (!ctx.canPlace()) return (_c, _t) -> Value.FALSE; BlockState placementState = blockItem.getBlock().getPlacementState(ctx); From 983f24a87d4b1935a9faaf56be28a85120c15d27 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 6 May 2020 14:34:04 -0300 Subject: [PATCH 113/198] 1.3.22 --- gradle.properties | 2 +- src/main/java/carpet/CarpetSettings.java | 2 +- src/main/resources/fabric.mod.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 2655bf11..8864d07e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ org.gradle.jvmargs=-Xmx1G loader_version=0.7.8+build.188 # Mod Properties - mod_version = 1.3.21+v200429 + mod_version = 1.3.22+v200506 maven_group = carpet archives_base_name = fabric-carpet diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index 43ac7c1d..c8c82b04 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -33,7 +33,7 @@ import static carpet.settings.RuleCategory.CLIENT; @SuppressWarnings("CanBeFinal") public class CarpetSettings { - public static final String carpetVersion = "1.3.21+v200429"; + public static final String carpetVersion = "1.3.22+v200506"; public static final Logger LOG = LogManager.getLogger(); public static boolean skipGenerationChecks = false; public static boolean impendingFillSkipUpdates = false; diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 249332b6..5c50b3d1 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,7 +1,7 @@ { "schemaVersion": 1, "id": "carpet", - "version": "1.3.21", + "version": "1.3.22", "name": "Carpet Mod in Fabric", "description": "Carpet made out of fabric", From 0ad542236cc7cb09d87fafe39859f64d0475e120 Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 7 May 2020 19:16:04 -0300 Subject: [PATCH 114/198] untested - creativeFlySpeed, creativeFlyDrag --- src/main/java/carpet/CarpetSettings.java | 14 ++++++++ .../LivingEntity_scarpetEventsMixin.java | 33 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index c8c82b04..e7c7a5f6 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -69,6 +69,7 @@ public class CarpetSettings ) public static int portalSurvivalDelay = 80; + private static class OneHourMaxDelayLimit extends Validator { @Override public Integer validate(ServerCommandSource source, ParsedRule currentRule, Integer newValue, String string) { return (newValue > 0 && newValue <= 72000) ? newValue : null; @@ -586,4 +587,17 @@ public class CarpetSettings category = {CREATIVE, CLIENT} ) public static boolean creativeNoClip = false; + + + @Rule( + desc = "Creative flying speed multiplier", + category = {CREATIVE, CLIENT} + ) + public static double creativeFlySpeed = 1.0f; + + @Rule( + desc = "Creative air drag", + category = {CREATIVE, CLIENT} + ) + public static double creativeFlyDrag = 0.91f; } diff --git a/src/main/java/carpet/mixins/LivingEntity_scarpetEventsMixin.java b/src/main/java/carpet/mixins/LivingEntity_scarpetEventsMixin.java index 456b9b74..5d30edac 100644 --- a/src/main/java/carpet/mixins/LivingEntity_scarpetEventsMixin.java +++ b/src/main/java/carpet/mixins/LivingEntity_scarpetEventsMixin.java @@ -1,5 +1,6 @@ package carpet.mixins; +import carpet.CarpetSettings; import carpet.fakes.EntityInterface; import carpet.fakes.LivingEntityInterface; import carpet.script.EntityEventsGroup; @@ -7,12 +8,17 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.damage.DamageSource; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Constant; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyConstant; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(LivingEntity.class) public abstract class LivingEntity_scarpetEventsMixin extends Entity implements LivingEntityInterface @@ -22,6 +28,8 @@ public abstract class LivingEntity_scarpetEventsMixin extends Entity implements @Shadow protected boolean jumping; + @Shadow public float flyingSpeed; + public LivingEntity_scarpetEventsMixin(EntityType type, World world) { super(type, world); @@ -44,4 +52,29 @@ public abstract class LivingEntity_scarpetEventsMixin extends Entity implements { return jumping; } + + + @ModifyConstant(method = "travel", constant = @Constant(floatValue = 0.91F), expect = 2) + private float drag(float original) + { + if ((Object)this instanceof PlayerEntity) + { + PlayerEntity self = (PlayerEntity)(Object)(this); + if (self.abilities.flying && !onGround) + return (float)CarpetSettings.creativeFlyDrag; + } + return original; + } + + + @Inject(method = "getMovementSpeed(F)F", at = @At("HEAD"), cancellable = true) + private void flyingAltSpeed(float slipperiness, CallbackInfoReturnable cir) + { + if ((Object)this instanceof PlayerEntity) + { + PlayerEntity self = (PlayerEntity)(Object)(this); + if (self.abilities.flying && !onGround) + cir.setReturnValue(flyingSpeed* (float)CarpetSettings.creativeFlySpeed); + } + } } From d35769a3658cd37515ee84ff21e6e56495bec56e Mon Sep 17 00:00:00 2001 From: gnembon Date: Sun, 10 May 2020 00:50:02 -0300 Subject: [PATCH 115/198] specified conditions for creative fly controls --- src/main/java/carpet/CarpetSettings.java | 19 +++++++ .../mixins/LivingEntity_creativeFlyMixin.java | 50 +++++++++++++++++++ .../LivingEntity_scarpetEventsMixin.java | 27 ---------- src/main/resources/carpet.mixins.json | 3 +- 4 files changed, 71 insertions(+), 28 deletions(-) create mode 100644 src/main/java/carpet/mixins/LivingEntity_creativeFlyMixin.java diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index e7c7a5f6..fe099c00 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -584,6 +584,15 @@ public class CarpetSettings @Rule( desc = "Creative No Clip", + extra = { + "On servers it needs to be set on both ", + "client and server to function properly.", + "Has no effect when set on the server only", + "Can allow to phase through walls", + "if only set on the carpet client side", + "but requires some trapdoor magic to", + "allow the player to enter blocks" + }, category = {CREATIVE, CLIENT} ) public static boolean creativeNoClip = false; @@ -591,12 +600,22 @@ public class CarpetSettings @Rule( desc = "Creative flying speed multiplier", + extra = { + "Purely client side setting, meaning that", + "having it set on the decicated server has no effect", + "but this also means it will work on vanilla servers as well" + }, category = {CREATIVE, CLIENT} ) public static double creativeFlySpeed = 1.0f; @Rule( desc = "Creative air drag", + extra = { + "Purely client side setting, meaning that", + "having it set on the decicated server has no effect", + "but this also means it will work on vanilla servers as well" + }, category = {CREATIVE, CLIENT} ) public static double creativeFlyDrag = 0.91f; diff --git a/src/main/java/carpet/mixins/LivingEntity_creativeFlyMixin.java b/src/main/java/carpet/mixins/LivingEntity_creativeFlyMixin.java new file mode 100644 index 00000000..4d1410df --- /dev/null +++ b/src/main/java/carpet/mixins/LivingEntity_creativeFlyMixin.java @@ -0,0 +1,50 @@ +package carpet.mixins; + +import carpet.CarpetSettings; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Constant; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyConstant; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(LivingEntity.class) +public abstract class LivingEntity_creativeFlyMixin extends Entity +{ + @Shadow public float flyingSpeed; + + public LivingEntity_creativeFlyMixin(EntityType type, World world) + { + super(type, world); + } + + @ModifyConstant(method = "travel", constant = @Constant(floatValue = 0.91F), expect = 2) + private float drag(float original) + { + if (CarpetSettings.creativeFlyDrag != 0.91D && (Object)this instanceof PlayerEntity) + { + PlayerEntity self = (PlayerEntity)(Object)(this); + if (self.abilities.flying && ! onGround ) + return (float)CarpetSettings.creativeFlyDrag; + } + return original; + } + + + @Inject(method = "getMovementSpeed(F)F", at = @At("HEAD"), cancellable = true) + private void flyingAltSpeed(float slipperiness, CallbackInfoReturnable cir) + { + if (CarpetSettings.creativeFlySpeed != 1.0D && (Object)this instanceof PlayerEntity) + { + PlayerEntity self = (PlayerEntity)(Object)(this); + if (self.abilities.flying && !onGround) + cir.setReturnValue(flyingSpeed* (float)CarpetSettings.creativeFlySpeed); + } + } +} diff --git a/src/main/java/carpet/mixins/LivingEntity_scarpetEventsMixin.java b/src/main/java/carpet/mixins/LivingEntity_scarpetEventsMixin.java index 5d30edac..57eeaa7a 100644 --- a/src/main/java/carpet/mixins/LivingEntity_scarpetEventsMixin.java +++ b/src/main/java/carpet/mixins/LivingEntity_scarpetEventsMixin.java @@ -28,8 +28,6 @@ public abstract class LivingEntity_scarpetEventsMixin extends Entity implements @Shadow protected boolean jumping; - @Shadow public float flyingSpeed; - public LivingEntity_scarpetEventsMixin(EntityType type, World world) { super(type, world); @@ -52,29 +50,4 @@ public abstract class LivingEntity_scarpetEventsMixin extends Entity implements { return jumping; } - - - @ModifyConstant(method = "travel", constant = @Constant(floatValue = 0.91F), expect = 2) - private float drag(float original) - { - if ((Object)this instanceof PlayerEntity) - { - PlayerEntity self = (PlayerEntity)(Object)(this); - if (self.abilities.flying && !onGround) - return (float)CarpetSettings.creativeFlyDrag; - } - return original; - } - - - @Inject(method = "getMovementSpeed(F)F", at = @At("HEAD"), cancellable = true) - private void flyingAltSpeed(float slipperiness, CallbackInfoReturnable cir) - { - if ((Object)this instanceof PlayerEntity) - { - PlayerEntity self = (PlayerEntity)(Object)(this); - if (self.abilities.flying && !onGround) - cir.setReturnValue(flyingSpeed* (float)CarpetSettings.creativeFlySpeed); - } - } } diff --git a/src/main/resources/carpet.mixins.json b/src/main/resources/carpet.mixins.json index f8e4b733..46ccfed2 100644 --- a/src/main/resources/carpet.mixins.json +++ b/src/main/resources/carpet.mixins.json @@ -159,7 +159,8 @@ "PistonHandler_movableTEMixin", "PlayerEntity_creativeNoClipMixin", "PistonBlockEntity_creativeNoClipMixin", - "BlockItem_creativeNoClipMixin" + "BlockItem_creativeNoClipMixin", + "LivingEntity_creativeFlyMixin" ], "client": [ From 56f8f17aaae0f89cd01258961af11706f9c88cea Mon Sep 17 00:00:00 2001 From: gnembon Date: Sun, 10 May 2020 13:11:58 -0300 Subject: [PATCH 116/198] tighten up function args for non-linear calls --- .../java/carpet/script/CarpetExpression.java | 2 +- src/main/java/carpet/script/Expression.java | 4 ++-- .../script/argument/FunctionArgument.java | 18 +++++++++++------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 99dd9628..76c19de9 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -2967,7 +2967,7 @@ public class CarpetExpression throw new InternalExpressionException("'schedule' should have at least 2 arguments, delay and call name"); long delay = NumericValue.asNumber(lv.get(0).evalValue(c)).getLong(); - FunctionArgument functionArgument = FunctionArgument.findIn(c, this.expr.module, lv, 1, true); + FunctionArgument functionArgument = FunctionArgument.findIn(c, this.expr.module, lv, 1, true, true); CarpetServer.scriptServer.events.scheduleCall( (CarpetContext) c, diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index 6d5174c5..17e5d331 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -440,7 +440,7 @@ public class Expression //lv.remove(lv.size()-1); // aint gonna cut it // maybe it will because of the eager eval changes if (t != Context.SIGNATURE) // just call the function { - FunctionArgument functionArgument = FunctionArgument.findIn(c, module, lv, 0, true); + FunctionArgument functionArgument = FunctionArgument.findIn(c, module, lv, 0, false, true); FunctionValue fun = functionArgument.function; Value retval = fun.callInContext(expr, c, t, fun.getExpression(), fun.getToken(), functionArgument.args).evalValue(c); return (cc, tt) -> retval; ///!!!! dono might need to store expr and token in statics? (e? t?) @@ -1878,7 +1878,7 @@ public class Expression addLazyFunctionWithDelegation("task", -1, (c, t, expr, tok, lv) -> { if (lv.size() == 0) throw new InternalExpressionException("'task' requires at least function to call as a parameter"); - FunctionArgument functionArgument = FunctionArgument.findIn(c, module, lv, 0); + FunctionArgument functionArgument = FunctionArgument.findIn(c, module, lv, 0, true, false); Value queue = Value.NULL; if (lv.size() > functionArgument.offset) queue = lv.get(functionArgument.offset).evalValue(c); ThreadValue thread = new ThreadValue(queue, functionArgument.function, expr, tok, c, functionArgument.args); diff --git a/src/main/java/carpet/script/argument/FunctionArgument.java b/src/main/java/carpet/script/argument/FunctionArgument.java index 4f3ba735..7838a518 100644 --- a/src/main/java/carpet/script/argument/FunctionArgument.java +++ b/src/main/java/carpet/script/argument/FunctionArgument.java @@ -22,11 +22,7 @@ public class FunctionArgument extends Argument this.function = function; this.args = args; } - public static FunctionArgument findIn(Context c, Module module, List params, int offset) - { - return findIn(c, module, params, offset, false); - } - public static FunctionArgument findIn(Context c, Module module, List params, int offset, boolean strict) + public static FunctionArgument findIn(Context c, Module module, List params, int offset, boolean prematureEvaluation, boolean strict) { Value functionValue = params.get(offset).evalValue(c); if (!(functionValue instanceof FunctionValue)) @@ -40,9 +36,17 @@ public class FunctionArgument extends Argument if (extraargs < 0 || (extraargs > 0 && strict)) throw new InternalExpressionException("Function "+fun.getPrettyString()+" requires "+fun.getArguments().size()+" arguments"); List lvargs = new ArrayList<>(); - for (int i=0; i< argsize; i++) + if (prematureEvaluation) { - lvargs.add(params.get(offset+1+i)); + for (int i = 0; i < argsize; i++) + { + Value arg = params.get(offset + 1 + i).evalValue(c); + lvargs.add((cc, tt) -> arg); + } + } + else + { + for (int i = 0; i < argsize; i++) lvargs.add(params.get(offset + 1 + i)); } return new FunctionArgument(fun, offset+1+argsize, lvargs); } From 52cf599375c83217ab9168baef6aca654cce8087 Mon Sep 17 00:00:00 2001 From: gnembon Date: Sun, 10 May 2020 17:24:35 -0300 Subject: [PATCH 117/198] added task_dock --- docs/scarpet/Full.md | 12 +++++ docs/scarpet/language/SystemFunctions.md | 12 +++++ docs/scarpet/resources/editors/idea/1.txt | 1 + .../scarpet/resources/editors/npp/scarpet.xml | 2 +- .../java/carpet/script/CarpetExpression.java | 35 +++++--------- src/main/java/carpet/script/Expression.java | 46 +++---------------- 6 files changed, 44 insertions(+), 64 deletions(-) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index 97fccb91..c07aaba4 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -790,6 +790,18 @@ Returns true if task has completed, or false otherwise. Evaluates `expression` synchronized with respect to the lock `lock`. Returns the value of the expression. +### `task_dock(expr)` + +In a not-task (running regular code on the main game thread) it is a pass-through command. In tasks - it docks +the current thread on the main server thread and executes expression as one server offline server task. +This is especially helpful in case a task has several docking operations to perform, such as setting a block, and +it would be much more efficient to do them all at once rather then packing each block access in each own call. + +Be mindful, that docking the task means that the tick execution will be delayed until the expression is evaluated. +This will synchronize your task with other tasks using `task_dock`, but if you should be using `synchronize` to +synchronize tasks without locking the main thread. + + * * * ## Auxiliary functions diff --git a/docs/scarpet/language/SystemFunctions.md b/docs/scarpet/language/SystemFunctions.md index 611057d2..7c506921 100644 --- a/docs/scarpet/language/SystemFunctions.md +++ b/docs/scarpet/language/SystemFunctions.md @@ -147,6 +147,18 @@ Returns true if task has completed, or false otherwise. Evaluates `expression` synchronized with respect to the lock `lock`. Returns the value of the expression. +### `task_dock(expr)` + +In a not-task (running regular code on the main game thread) it is a pass-through command. In tasks - it docks +the current thread on the main server thread and executes expression as one server offline server task. +This is especially helpful in case a task has several docking operations to perform, such as setting a block, and +it would be much more efficient to do them all at once rather then packing each block access in each own call. + +Be mindful, that docking the task means that the tick execution will be delayed until the expression is evaluated. +This will synchronize your task with other tasks using `task_dock`, but if you should be using `synchronize` to +synchronize tasks without locking the main thread. + + * * * ## Auxiliary functions diff --git a/docs/scarpet/resources/editors/idea/1.txt b/docs/scarpet/resources/editors/idea/1.txt index fcab9dfb..8780d3f9 100644 --- a/docs/scarpet/resources/editors/idea/1.txt +++ b/docs/scarpet/resources/editors/idea/1.txt @@ -85,6 +85,7 @@ tanh task task_completed task_count +task_dock task_join task_value throw diff --git a/docs/scarpet/resources/editors/npp/scarpet.xml b/docs/scarpet/resources/editors/npp/scarpet.xml index 3994ced4..cfcde776 100644 --- a/docs/scarpet/resources/editors/npp/scarpet.xml +++ b/docs/scarpet/resources/editors/npp/scarpet.xml @@ -36,7 +36,7 @@ print return exit throw try - task task_count task_value task_join task_completed synchronize + task task_count task_value task_join task_completed synchronize task_dock system_variable_get system_variable_set diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 76c19de9..06bded9a 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -2791,6 +2791,18 @@ public class CarpetExpression return (_c, _t) -> ret; }); + this.expr.addLazyFunction("task_dock", 1, (c, t, lv) -> { + CarpetContext cc = (CarpetContext)c; + MinecraftServer server = cc.s.getMinecraftServer(); + if (server.isOnThread()) return lv.get(1); // pass through for on thread tasks + Value[] result = new Value[]{Value.NULL}; + ((CarpetContext) c).s.getMinecraftServer().submitAndJoin(() -> result[0] = lv.get(0).evalValue(c, t)); + Value ret = result[0]; // preventing from lazy evaluating of the result in case a future completes later + return (_c, _t) -> ret; + // pass through placeholder + // implmenetation should dock the task on the main thread. + }); + this.expr.addLazyFunction("logger", 1, (c, t, lv) -> { Value res = lv.get(0).evalValue(c); @@ -2976,29 +2988,6 @@ public class CarpetExpression delay ); return (c_, t_) -> Value.TRUE; - /* - Value functionValue = lv.get(1).evalValue(c); - if (!(functionValue instanceof FunctionValue)) - { - String name = functionValue.getString(); - functionValue = c.host.getAssertFunction(this.expr.module, name); - } - FunctionValue function = (FunctionValue)functionValue; - - CarpetContext cc = (CarpetContext)c; - List args = new ArrayList<>(); - for (int i=2; i < lv.size(); i++) - { - Value arg = lv.get(i).evalValue(cc); - args.add(arg); - } - if (function.getArguments().size() != args.size()) - throw new InternalExpressionException("Function "+function.getString()+" takes "+ - function.getArguments().size()+" arguments, "+args.size()+" provided."); - CarpetServer.scriptServer.events.scheduleCall(cc, function, args, delay); - return (c_, t_) -> Value.TRUE; - */ - }); this.expr.addLazyFunction("load_app_data", -1, (c, t, lv) -> diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index 17e5d331..83e607fe 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -444,23 +444,6 @@ public class Expression FunctionValue fun = functionArgument.function; Value retval = fun.callInContext(expr, c, t, fun.getExpression(), fun.getToken(), functionArgument.args).evalValue(c); return (cc, tt) -> retval; ///!!!! dono might need to store expr and token in statics? (e? t?) - - /* - Value functionValue = lv.get(0).evalValue(c); - if (!(functionValue instanceof FunctionValue)) - { - String name = functionValue.getString(); - functionValue = c.host.getAssertFunction(module, name); - } - List lvargs = new ArrayList<>(lv.size()-1); - for (int i=1; i< lv.size(); i++) - { - lvargs.add(lv.get(i)); - } - FunctionValue fun = (FunctionValue)functionValue; - Value retval = fun.callInContext(expr, c, t, fun.getExpression(), fun.getToken(), lvargs).evalValue(c); - return (cc, tt) -> retval; ///!!!! dono might need to store expr and token in statics? (e? t?) - */ } // gimme signature String name = lv.get(0).evalValue(c).getString(); @@ -1884,29 +1867,6 @@ public class Expression ThreadValue thread = new ThreadValue(queue, functionArgument.function, expr, tok, c, functionArgument.args); Thread.yield(); return (cc, tt) -> thread; - /* - Value funcDesc = lv.get(0).evalValue(c); - if (!(funcDesc instanceof FunctionValue)) - { - String name = funcDesc.getString(); - funcDesc = c.host.getAssertFunction(module, name); - } - FunctionValue fun = (FunctionValue)funcDesc; - int extraargs = lv.size() - fun.getArguments().size(); - if (extraargs != 1 && extraargs != 2) - { - throw new InternalExpressionException("Function takes "+fun.getArguments().size()+" arguments."); - } - List lvargs = new ArrayList<>(); - for (int i=0; i< fun.getArguments().size(); i++) - { - lvargs.add(lv.get(i+1)); - } - Value queue = Value.NULL; - if (extraargs == 2) queue = lv.get(lv.size()-1).evalValue(c); - ThreadValue thread = new ThreadValue(queue, fun, expr, tok, c, lvargs); - Thread.yield(); - return (cc, tt) -> thread;*/ }); addFunction("task_count", (lv) -> @@ -1930,6 +1890,12 @@ public class Expression return ((ThreadValue) v).join(); }); + addLazyFunction("task_dock", 1, (c, t, lv) -> { + // pass through placeholder + // implmenetation should dock the task on the main thread. + return lv.get(0); + }); + addUnaryFunction("task_completed", (v) -> { if (!(v instanceof ThreadValue)) throw new InternalExpressionException("'task_completed' could only be used with a task value"); From b631f7b62e68fa9f5eb998dcb41b292b82eecec6 Mon Sep 17 00:00:00 2001 From: gnembon Date: Sun, 10 May 2020 18:44:49 -0300 Subject: [PATCH 118/198] fixed notation of ranges --- src/main/java/carpet/script/value/LazyListValue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/carpet/script/value/LazyListValue.java b/src/main/java/carpet/script/value/LazyListValue.java index 55df4ae5..e57d7110 100644 --- a/src/main/java/carpet/script/value/LazyListValue.java +++ b/src/main/java/carpet/script/value/LazyListValue.java @@ -48,7 +48,7 @@ public abstract class LazyListValue extends AbstractListValue implements Iterato @Override public String getString() { - return String.format(Locale.ROOT, "[%d, %d, ..., %d]",start, start+stepp, limit); + return String.format(Locale.ROOT, "[%d, %d, ..., %d)",start, start+stepp, limit); } }; } From f7cfcb41580e73fc4ad826f40b091802f4479666 Mon Sep 17 00:00:00 2001 From: gnembon Date: Mon, 11 May 2020 01:01:36 -0300 Subject: [PATCH 119/198] oupsie --- src/main/java/carpet/script/CarpetExpression.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 06bded9a..65e1dba5 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -2794,7 +2794,7 @@ public class CarpetExpression this.expr.addLazyFunction("task_dock", 1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; MinecraftServer server = cc.s.getMinecraftServer(); - if (server.isOnThread()) return lv.get(1); // pass through for on thread tasks + if (server.isOnThread()) return lv.get(0); // pass through for on thread tasks Value[] result = new Value[]{Value.NULL}; ((CarpetContext) c).s.getMinecraftServer().submitAndJoin(() -> result[0] = lv.get(0).evalValue(c, t)); Value ret = result[0]; // preventing from lazy evaluating of the result in case a future completes later From 955eb361f4b8db2a3c3c89d5d38a390e5ba82d29 Mon Sep 17 00:00:00 2001 From: gnembon Date: Tue, 12 May 2020 17:00:02 -0300 Subject: [PATCH 120/198] added 'all' options to spawn entites and fixed definition of mobcappable --- .../java/carpet/commands/SpawnCommand.java | 7 ++--- src/main/java/carpet/utils/SpawnReporter.java | 26 ++++++++++--------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/main/java/carpet/commands/SpawnCommand.java b/src/main/java/carpet/commands/SpawnCommand.java index d141b291..f50e858b 100644 --- a/src/main/java/carpet/commands/SpawnCommand.java +++ b/src/main/java/carpet/commands/SpawnCommand.java @@ -98,7 +98,8 @@ public class SpawnCommand executes( (c) -> generalMobcaps(c.getSource()) ). then(argument("type", string()). suggests( (c, b)->suggestMatching(Arrays.stream(EntityCategory.values()).map(EntityCategory::getName), b)). - executes( (c) -> listEntitiesOfType(c.getSource(), getString(c, "type"))))); + executes( (c) -> listEntitiesOfType(c.getSource(), getString(c, "type"), false)). + then(literal("all").executes( (c) -> listEntitiesOfType(c.getSource(), getString(c, "type"), true))))); dispatcher.register(literalargumentbuilder); } @@ -262,10 +263,10 @@ public class SpawnCommand return 1; } - private static int listEntitiesOfType(ServerCommandSource source, String mobtype) throws CommandSyntaxException + private static int listEntitiesOfType(ServerCommandSource source, String mobtype, boolean all) throws CommandSyntaxException { EntityCategory cat = getCategory(mobtype); - Messenger.send(source, SpawnReporter.printEntitiesByType(cat, source.getWorld())); + Messenger.send(source, SpawnReporter.printEntitiesByType(cat, source.getWorld(), all)); return 1; } } diff --git a/src/main/java/carpet/utils/SpawnReporter.java b/src/main/java/carpet/utils/SpawnReporter.java index defd6071..4e6cd8a5 100644 --- a/src/main/java/carpet/utils/SpawnReporter.java +++ b/src/main/java/carpet/utils/SpawnReporter.java @@ -186,7 +186,7 @@ public class SpawnReporter } else { - return printEntitiesByType(creature_type, worldIn); + return printEntitiesByType(creature_type, worldIn, true); } @@ -250,22 +250,24 @@ public class SpawnReporter return get_type_string(get_creature_type_from_code(str)); } - public static List printEntitiesByType(EntityCategory cat, World worldIn) //Class entityType) + public static List printEntitiesByType(EntityCategory cat, World worldIn, boolean all) //Class entityType) { List lst = new ArrayList<>(); lst.add( Messenger.s(String.format("Loaded entities for %s class:", get_type_string(cat)))); for (Entity entity : ((ServerWorld)worldIn).getEntities(null, (e) -> e.getType().getCategory()==cat)) { - if (!(entity instanceof MobEntity) || !((MobEntity)entity).isPersistent()) - { - EntityType type = entity.getType(); - BlockPos pos = entity.getBlockPos(); - lst.add( Messenger.c( - "w - ", - Messenger.tp("wb",pos), - String.format("w : %s", type.getName().getString()) - )); - } + boolean persistent = entity instanceof MobEntity && ( ((MobEntity) entity).isPersistent() || ((MobEntity) entity).cannotDespawn()); + if (!all && persistent) + continue; + + EntityType type = entity.getType(); + BlockPos pos = entity.getBlockPos(); + lst.add( Messenger.c( + "w - ", + Messenger.tp(persistent?"gb":"wb",pos), + String.format(persistent?"g : %s":"w : %s", type.getName().getString()) + )); + } if (lst.size()==1) { From 72ed5020c6f0c26840eba453625db9310f19be22 Mon Sep 17 00:00:00 2001 From: James103 <37945304+James103@users.noreply.github.com> Date: Tue, 12 May 2020 13:12:56 -0500 Subject: [PATCH 121/198] Fix: typos in first half of ..\docs\scarpet\api (#275) * Fix: typos in Auxiliary.md * Fix: typos in BlockIterations.md * Fix: typos in BlocksAndWorldAccess.md * Fix: typos in Entities.md * Fix: more typos in Entities.md * If you pause at ... while saying this sentence it makes sense. Most ppl think there is only one kind of air in mc. * redstone ticking * Update docs/scarpet/api/BlocksAndWorldAccess.md Co-authored-by: gnembon <41132274+gnembon@users.noreply.github.com> --- docs/scarpet/api/Auxiliary.md | 12 +- docs/scarpet/api/BlockIterations.md | 6 +- docs/scarpet/api/BlocksAndWorldAccess.md | 100 +++++----- docs/scarpet/api/Entities.md | 234 ++++++++++++----------- 4 files changed, 181 insertions(+), 171 deletions(-) diff --git a/docs/scarpet/api/Auxiliary.md b/docs/scarpet/api/Auxiliary.md index 241c2716..a3ea3296 100644 --- a/docs/scarpet/api/Auxiliary.md +++ b/docs/scarpet/api/Auxiliary.md @@ -28,7 +28,7 @@ apart you would want particles to appear, so `0.1` means one every 10cm. ### `particle_rect(name, pos, pos2, density?)` -Renders a cuboid of particles between point `pos` to `pos2` with supplied density. +Renders a cuboid of particles between points `pos` and `pos2` with supplied density. ## Markers @@ -36,7 +36,7 @@ Renders a cuboid of particles between point `pos` to `pos2` with supplied densit Spawns a (permanent) marker entity with text or block at position. Returns that entity for further manipulations. Unloading the app that spawned them will cause all the markers from the loaded portion of the world to be removed. -Also - if the game loads that marker in the future and the app is not loaded, it will be removed as well. +Also, if the game loads that marker in the future and the app is not loaded, it will be removed as well. ### `remove_all_markers()` @@ -124,7 +124,7 @@ Prints the message to system logs, and not to chat. Runs a vanilla command from the string result of the `expr` and returns its success count
-run('fill 1 1 1 10 10 10 air') -> 123 // 123 block were filled, this operation was successful 123 times out of a possible 1000 blocks volume
+run('fill 1 1 1 10 10 10 air') -> 123 // 123 block were filled, this operation was successful 123 times out of a possible 1000 block volume
 run('give @s stone 4') -> 1 // this operation was successful once
 
@@ -136,7 +136,7 @@ performance reasons and saves the world only on demand. ### `load_app_data(), load_app_data(file), load_app_data(file, shared?)` Loads the app data associated with the app from the world /scripts folder. Without argument returns the memory -managed and buffered / throttled NBT tag. With a file name - reads explicitly a file with that name from the +managed and buffered / throttled NBT tag. With a file name, reads explicitly a file with that name from the scripts folder that belongs exclusively to the app. if `shared` is true, the file location is not exclusive to the app anymore, but located in a shared app space. @@ -235,7 +235,7 @@ Queries in-game statistics for certain values. Categories include: For the options of `entry`, consult your statistics page, or give it a guess. -The call will return `null` if the statistics options are incorrect, or player didn't get these in their history. +The call will return `null` if the statistics options are incorrect, or player doesn't have them in their history. If the player encountered the statistic, or game created for him empty one, it will return a number. Scarpet will not affect the entries of the statistics, even if it is just creating empty ones. With `null` response -it could either mean your input is wrong, or statistic has effectively a value of `0`. +it could either mean your input is wrong, or statistic effectively has a value of `0`. diff --git a/docs/scarpet/api/BlockIterations.md b/docs/scarpet/api/BlockIterations.md index 6aebfbc8..f60375c8 100644 --- a/docs/scarpet/api/BlockIterations.md +++ b/docs/scarpet/api/BlockIterations.md @@ -7,7 +7,7 @@ These functions help scan larger areas of blocks without using generic loop func Evaluates expression over area of blocks defined by its center `center = (cx, cy, cz)`, expanded in all directions by `range = (dx, dy, dz)` blocks, or optionally in negative with `range` coords, and `upper_range` coords in positive values. -`center` can be defined either as a three coordinates, list of three coords, or block value. +`center` can be defined either as three coordinates, a list of three coords, or a block value. `range` and `lower_range` can have the same representations, just if its a block, it computes the distance to the center as range instead of taking the values as is. `expr` receives `_x, _y, _z` as coords of current analyzed block and `_`, which represents the block itself. @@ -20,7 +20,7 @@ return value. `break` return value has no effect. ### `volume(x1, y1, z1, x2, y2, z2, expr)` -Evaluates expression for each block in the area, the same as the `scan`function, but using two opposite corners of +Evaluates expression for each block in the area, the same as the `scan` function, but using two opposite corners of the rectangular cuboid. Any corners can be specified, its like you would do with `/fill` command. For return value and handling `break` and `continue` statements, see `scan` function above. @@ -36,7 +36,7 @@ for(neighbours(x,y,z),air(_)) => 4 // number of air blocks around a block ### `rect(cx, cy, cz, dx?, dy?, dz?, px?, py?, pz?)` returns an iterator, just like `range` function that iterates over rectangular cubarea of blocks. If only center -point is specified, it iterates over 27 blocks. If `d` arguments are specified, expands selection of respective +point is specified, it iterates over 27 blocks. If `d` arguments are specified, expands selection by the respective number of blocks in each direction. If `p` arguments are specified, it uses `d` for negative offset, and `p` for positive. ### `diamond(cx, cy, cz, radius?, height?)` diff --git a/docs/scarpet/api/BlocksAndWorldAccess.md b/docs/scarpet/api/BlocksAndWorldAccess.md index b9a67339..9750cf1a 100644 --- a/docs/scarpet/api/BlocksAndWorldAccess.md +++ b/docs/scarpet/api/BlocksAndWorldAccess.md @@ -70,8 +70,8 @@ set(x,y,z,'hopper[facing=north]{Items:[{Slot:1b,id:"minecraft:slime_ball",Count: Evaluates subexpression without causing updates when blocks change in the world -Consider following scenario: We would like to generate a bunch of terrain in a flat world following a perling noise -generator. The following code causes cascading effect as blocks placed on chunk borders will cause other chunks to get +Consider following scenario: We would like to generate a bunch of terrain in a flat world following a perlin noise +generator. The following code causes a cascading effect as blocks placed on chunk borders will cause other chunks to get loaded to full, thus generated:
@@ -85,7 +85,7 @@ __on_chunk_generated(x, z) -> (
 )
 
-The following addition resolves this issue, by not allowing block updates pass chunk borders: +The following addition resolves this issue, by not allowing block updates past chunk borders:
 __config() -> m(l('scope', 'global'));
@@ -110,7 +110,7 @@ block, or 'up-north', which means a block placed facing up (player looking down)
 center towards north. Optional sneak is a boolean indicating if a player would be sneaking while placing the 
 block - this option only affects placement of chests and scaffolding at the moment. 
 
-Works with items that have the right-click effect on the block placed, `'like bone_meal`` on grass or axes on logs,
+Works with items that have the right-click effect on the block placed, like `bone_meal` on grass or axes on logs,
 but doesn't open chests / containers, so have no effect on interactive blocks, like TNT, comparators, etc.
 
 Returns true if placement/use was 
@@ -136,7 +136,7 @@ markers for scarpet apps. `meeting` is the only one with increased max occupancy
 
 ### `set_biome(pos, biome_name)`
 
-changes biome at that block position.
+Changes the biome at that block position.
 
 ### `update(pos)`
 
@@ -152,7 +152,7 @@ Causes a random tick at position.
 
 ### `destroy(pos), destroy(pos, -1), destroy(pos, ), destroy(pos, tool, nbt?)`
 
-Destroys the block like it was mined by a player. Add -1 for silk touch, and positive number for fortune level. 
+Destroys the block like it was mined by a player. Add -1 for silk touch, and a positive number for fortune level. 
 If tool is specified, and optionally its nbt, it will use that tool and will attempt to mine the block with this tool. 
 If called without item context, this function, unlike harvest, will affect all kinds of blocks. If called with item 
 in context, it will fail to break blocks that cannot be broken by a survival player.
@@ -168,28 +168,28 @@ for mining. Obviously, in this case the use of `harvest` would be much more appl
 
 mine(x,y,z) ->
 (
-   p = player();
-   slot = p~'selected_slot';
-   item_tuple = inventory_get(p, slot);
-   if (!item_tuple, destroy(x,y,z,'air'); return()); // empty hand, just break with 'air'
-   l(item, count, tag) = item_tuple;
-   tag_back = destroy(x,y,z, item, tag);
-   if (tag_back == false, // failed to break the item
-	     return(tag_back)
-   );
-   if (tag_back == true, // block broke, tool has no tag
-	     return(tag_back)
-   );
-   if (tag_back == null, //item broke
-	     delete(tag:'Damage');
-	     inventory_set(p, slot, count-1, item, tag);
-	     return(tag_back)
-   );
-   if (type(tag_back) == 'nbt', // item didn't break, here is the effective nbt
-	     inventory_set(p, slot, count, item, tag_back);
-	     return(tag_back)
-   );
-   print('How did we get here?');
+  p = player();
+  slot = p~'selected_slot';
+  item_tuple = inventory_get(p, slot);
+  if (!item_tuple, destroy(x,y,z,'air'); return()); // empty hand, just break with 'air'
+  l(item, count, tag) = item_tuple;
+  tag_back = destroy(x,y,z, item, tag);
+  if (tag_back == false, // failed to break the item
+    return(tag_back)
+  );
+  if (tag_back == true, // block broke, tool has no tag
+    return(tag_back)
+  );
+  if (tag_back == null, //item broke
+    delete(tag:'Damage');
+    inventory_set(p, slot, count-1, item, tag);
+    return(tag_back)
+  );
+  if (type(tag_back) == 'nbt', // item didn't break, here is the effective nbt
+    inventory_set(p, slot, count, item, tag_back);
+    return(tag_back)
+  );
+  print('How did we get here?');
 )
 
@@ -207,9 +207,9 @@ Returns a triple of coordinates of a specified block or entity. Technically enti and the same can be achieved with `query(entity,'pos')`, but for simplicity `pos` allows to pass all positional objects.
-pos(block(0,5,0))  => l(0,5,0)
+pos(block(0,5,0)) => l(0,5,0)
 pos(players()) => l(12.3, 45.6, 32.05)
-pos(block('stone'))  => Error: Cannot fetch position of an unrealized block
+pos(block('stone')) => Error: Cannot fetch position of an unrealized block
 
### `pos_offset(pos, direction, amount?)` @@ -267,51 +267,51 @@ poi(x,y,z,5) => [['nether_portal',0,[7,8,9]],['nether_portal',0,[7,9,9]]] // two ### `biome(pos)` -returns biome at that block position. +Returns the biome at that block position. ### `solid(pos)` -Boolean function, true if the block is solid +Boolean function, true if the block is solid. ### `air(pos)` -Boolean function, true if a block is air.... or cave air... or void air.... or any other air they come up with. +Boolean function, true if a block is air... or cave air... or void air... or any other air they come up with. ### `liquid(pos)` -Boolean function, true if the block is liquid, or liquidlogged +Boolean function, true if the block is liquid, or waterlogged (with any liquid). ### `flammable(pos)` -Boolean function, true if the block is flammable +Boolean function, true if the block is flammable. ### `transparent(pos)` -Boolean function, true if the block is transparent +Boolean function, true if the block is transparent. ### `opacity(pos)` -Numeric, returning opacity level of a block +Numeric function, returning the opacity level of a block. ### `blocks_daylight(pos)` -Boolean function, true if the block blocks daylight +Boolean function, true if the block blocks daylight. ### `emitted_light(pos)` -Numeric, returning light level emitted from block +Numeric function, returning the light level emitted from the block. ### `light(pos)` -Integer function, returning total light level at position +Numeric function, returning the total light level at position. ### `block_light(pos)` -Integer function, returning block light at position. From torches and other light sources. +Numeric function, returning the block light at position (from torches and other light sources). ### `sky_light(pos)` -Numeric function, returning sky light at position. From the sky access. +Numeric function, returning the sky light at position (from sky access). ### `see_sky(pos)` @@ -359,7 +359,7 @@ Boolean function, true if the block ticks randomly. ### `blocks_movement(pos)` -Boolean function, true if block at position blocks movement. +Boolean function, true if the block at position blocks movement. ### `block_sound(pos)` @@ -485,11 +485,11 @@ Returns the map colour of a block at position. One of: ### `loaded(pos)` Boolean function, true if the block is accessible for the game mechanics. Normally `scarpet` doesn't check if operates -on loaded area - the game will automatically load missing blocks. We see this as advantage. Vanilla `fill/clone` +on loaded area - the game will automatically load missing blocks. We see this as an advantage. Vanilla `fill/clone` commands only check the specified corners for loadness. -To check if block is truly loaded, I mean in memory, use `generation_status(x) != null`, as chunks can still be loaded -outside of the playable area, just are not used any of the game mechanics processes. +To check if a block is truly loaded, I mean in memory, use `generation_status(x) != null`, as chunks can still be loaded +outside of the playable area, just are not used by any of the game mechanic processes.
 loaded(pos(players()))  => 1
@@ -504,7 +504,7 @@ Deprecated as of scarpet 1.6, use `loaded_status(x) > 0`, or just `loaded(x)` wi
 
 ### `loaded_status(pos)`
 
-Returns loaded status as per new 1.14 chunk ticket system, 0 for inaccessible, 1 for border chunk, 2 for ticking, 
+Returns loaded status as per new 1.14 chunk ticket system, 0 for inaccessible, 1 for border chunk, 2 for redstone ticking, 
 3 for entity ticking
 
 ### `is_chunk_generated(pos)`, `is_chunk_generated(pos, force)`
@@ -539,10 +539,10 @@ Returns spawn potential at a location (1.16+ only)
 Checks wordgen eligibility for a structure in a given chunk. If no structure is given, or `null`, then it will check
  for all structures. If bounding box of the structures is also requested, it will compute size of potential
   structures. This function, unlike other in the `structure*` category is not using world data nor accesses chunks
-  making it preferred for scoping ungenerated terrain, but it takes some compute money to calculate the structure.
+  making it preferred for scoping ungenerated terrain, but it takes some compute resources to calculate the structure.
   
   Unlike `'structure'` this will return a tentative structure location. Random factors in world generation may prevent
-  actual structure from forming.
+  the actual structure from forming.
   
 If structure is specified, it will return `null` if a chunk is not eligible, `true` if the structure should appear, or 
 a map with two values: `'box'` for a pair of coordinates indicating bounding box of the structure, and `'pieces'` for 
@@ -575,7 +575,7 @@ then to get its bounding boxes.
 
 Creates or removes structure information of a structure associated with a chunk of `pos`. Unlike `plop`, blocks are 
 not placed in the world, only structure information is set. For the game this is a fully functional structure even 
-if blocks are not set. To remove structure a given point is in, use `structure_references` to find where current 
+if blocks are not set. To remove the structure a given point is in, use `structure_references` to find where current 
 structure starts.
 
 ### `plop(pos, what)`
diff --git a/docs/scarpet/api/Entities.md b/docs/scarpet/api/Entities.md
index 0f288bfa..b41bbde0 100644
--- a/docs/scarpet/api/Entities.md
+++ b/docs/scarpet/api/Entities.md
@@ -3,23 +3,23 @@
 ## Entity Selection
 
 Entities have to be fetched before using them. Entities can also change their state between calls to the script if 
-game happens either in between separate calls to the programs, or if the program calls `game_tick` on its own. 
-In this case - entities would need to be re-fetched, or the code should account for entities getting dead.
+game ticks occur either in between separate calls to the programs, or if the program calls `game_tick` on its own. 
+In this case - entities would need to be re-fetched, or the code should account for entities dying.
 
 ### `player(), player(type), player(name)`
 
 With no arguments, it returns the calling player or the player closest to the caller. Note that the main context 
-will receive `p` variable pointing to this player. With `type` or `name` specified it will try first to match a type, 
+will receive `p` variable pointing to this player. With `type` or `name` specified, it will try first to match a type, 
 returning a list of players matching a type, and if this fails, will assume its player name query retuning player with 
 that name, or `null` if no player was found. With `'all'`, list of all players in the game, in all dimensions, so end 
 user needs to be cautious, that you might be referring to wrong blocks and entities around the player in question. 
 With `type = '*'` it returns all players in caller dimension, `'survival'` returns all survival and adventure players,
 `'creative'` returns all creative players, `'spectating'` returns all spectating players, and `'!spectating'`, 
-all not-spectating players. If all fails, with `name`, the player in question, if is logged in.
+all not-spectating players. If all fails, with `name`, the player in question, if he/she is logged in.
 
 ### `entity_id(uuid), entity_id(id)`
 
-Fetching entities wither by their ID obtained via `entity ~ 'id'`, which is unique for a dimension and current world 
+Fetching entities either by their ID obtained via `entity ~ 'id'`, which is unique for a dimension and current world 
 run, or by UUID, obtained via `entity ~ 'uuid'`. It returns null if no such entity is found. Safer way to 'store' 
 entities between calls, as missing entities will be returning `null`. Both calls using UUID or numerical ID are `O(1)`, 
 but obviously using UUIDs takes more memory and compute.
@@ -38,12 +38,12 @@ selectors are available:
 ### `entity_area(type, cx, cy, cz, dx, dy, dz)`
 
 Returns entities of a specified type in an area centered on `cx, cy, cz` and at most `dx, dy, dz` blocks away from 
-the center point. Uses same selectors as `entities_list`
+the center point. Uses the same selectors as `entities_list`.
 
 ### `entity_selector(selector)`
 
-Returns entities satisfying given vanilla entity selector. Most complex among all the methods of selecting entities, 
-but the most capable. Selectors are cached so should be as fast as other methods of selecting entities.
+Returns entities satisifying given vanilla entity selector. Most complex among all the methods of selecting entities, 
+but the most capable. Selectors are cached so it should be as fast as other methods of selecting entities.
 
 ### `spawn(name, pos, nbt?)`
 
@@ -53,67 +53,67 @@ you get the entity back as a return value, which is swell.
 
 ## Entity Manipulation
 
-Unlike with blocks, that use plethora of vastly different querying functions, entities are queried with `query` 
-function and altered via `modify` function. Type of information needed or values to be modified are different for 
+Unlike with blocks, that use a plethora of vastly different querying functions, entities are queried with the `query` 
+function and altered via the `modify` function. Type of information needed or values to be modified are different for 
 each call.
 
 Using `~` (in) operator is an alias for `query`. Especially useful if a statement has no arguments, 
-which in this case can be radically simplified
+which in this case can be radically simplified:
 
 
 query(p, 'name') <=> p ~ 'name'     // much shorter and cleaner
 query(p, 'holds', 'offhand') <=> p ~ l('holds', 'offhand')    // not really but can be done
 
-### `query(e,'removed')` +### `query(e, 'removed')` -Boolean. True if the entity is removed +Boolean. True if the entity is removed. -### `query(e,'id')` +### `query(e, 'id')` Returns numerical id of the entity. Most efficient way to keep track of entites in a script. Ids are only unique within current game session (ids are not preserved between restarts), -and dimension (each dimension has its own ids which can overlap. +and dimension (each dimension has its own ids which can overlap). -### `query(e,'uuid')` +### `query(e, 'uuid')` -Returns UUID (unique id) of the entity. Can be used to access entities with the other vanilla commands and +Returns the UUID (unique id) of the entity. Can be used to access entities with the other vanilla commands and remains unique regardless of the dimension, and is preserved between game restarts. Apparently players cannot be -accessed via UUID, but name instead. +accessed via UUID, but should be accessed with their name instead.
 map(entities_area('*',x,y,z,30,30,30),run('kill '+query(_,'id'))) // doesn't kill the player
 
-### `query(e,'pos')` +### `query(e, 'pos')` -Triple of entity position +Triple of the entity's position -### `query(e,'location')` +### `query(e, 'location')` -Quin-tuple of entity position (x, y, and z coords), and rotation (yaw, pitch) +Quin-tuple of the entity's position (x, y, and z coords), and rotation (yaw, pitch) -### `query(e,'x'), query(e,'y'), query(e,'z')` +### `query(e, 'x'), query(e, 'y'), query(e, 'z')` -Respective entity coordinate +Respective component of entity's coordinates -### `query(e,'pitch'), query(e,'yaw')` +### `query(e, 'pitch'), query(e, 'yaw')` Pitch and Yaw or where entity is looking. -### `query(e,'look')` +### `query(e, 'look')` Returns a 3d vector where the entity is looking. -### `query(e,'motion')` +### `query(e, 'motion')` -Triple of entity motion vector, `l(motion_x, motion_y, motion_z)` +Triple of entity's motion vector, `l(motion_x, motion_y, motion_z)` -### `query(e,'motion_x'), query(e,'motion_y'), query(e,'motion_z')` +### `query(e, 'motion_x'), query(e, 'motion_y'), query(e, 'motion_z')` -Respective component of the motion vector +Respective component of the entity's motion vector -### `query(e,'name'), query(e,'display_name'), query(e,'custom_name'), query(e,'type')` +### `query(e, 'name'), query(e, 'display_name'), query(e, 'custom_name'), query(e, 'type')` String of entity name @@ -132,99 +132,99 @@ player, where its their name. run('/kill ' + e~'command_name');
-### `query(e,'is_riding')` +### `query(e, 'is_riding')` -Boolean. True if riding another entity. +Boolean, true if the entity is riding another entity. -### `query(e,'is_ridden')` +### `query(e, 'is_ridden')` -Boolean. True if another entity is riding it. +Boolean, true if another entity is riding it. -### `query(e,'passengers')` +### `query(e, 'passengers')` List of entities riding the entity. -### `query(e,'mount')` +### `query(e, 'mount')` Entity that `e` rides. -### `query(e,'tags')` +### `query(e, 'tags')` -List of entity tags. +List of entity's tags. -### `query(e,'has_tag',tag)` +### `query(e, 'has_tag',tag)` -Boolean, True if the entity is marked with `tag`. +Boolean, true if the entity is marked with `tag`. -### `query(e,'is_burning')` +### `query(e, 'is_burning')` -Boolean, True if the entity is burning. +Boolean, true if the entity is burning. -### `query(e,'fire')` +### `query(e, 'fire')` Number of remaining ticks of being on fire. -### `query(e,'silent')` +### `query(e, 'silent')` -Boolean, True if the entity is silent. +Boolean, true if the entity is silent. -### `query(e,'gravity')` +### `query(e, 'gravity')` -Boolean, True if the entity is affected by gravity, like most entities do. +Boolean, true if the entity is affected by gravity, like most entities are. -### `query(e,'immune_to_fire')` +### `query(e, 'immune_to_fire')` -Boolean, True if the entity is immune to fire. +Boolean, true if the entity is immune to fire. -### `query(e,'dimension')` +### `query(e, 'dimension')` -Name of the dimension entity is in. +Name of the dimension the entity is in. -### `query(e,'height')` +### `query(e, 'height')` -Height of the entity. +Height of the entity in blocks. -### `query(e,'width')` +### `query(e, 'width')` -Width of the entity. +Width of the entity in blocks. -### `query(e,'eye_height')` +### `query(e, 'eye_height')` -Eye height of the entity. +Eye height of the entity in blocks. -### `query(e,'age')` +### `query(e, 'age')` -Age, in ticks, of the entity, i.e. how long it existed. +Age of the entity in ticks, i.e. how long it existed. -### `query(e,'breeding_age')` +### `query(e, 'breeding_age')` -Breeding age of passive entity, in ticks. If negative it it time to adulthood, if positive, breeding cooldown +Breeding age of passive entity, in ticks. If negative, time to adulthood, if positive, breeding cooldown -### `query(e,'despawn_timer')` +### `query(e, 'despawn_timer')` -For living entities - the number of ticks they fall outside of immediate player presence. +For living entities, the number of ticks they fall outside of immediate player presence. -### `query(e,'item')` +### `query(e, 'item')` The item triple (name, count, nbt) if its an item entity, `null` otherwise -### `query(e,'count')` +### `query(e, 'count')` Number of items in a stack from item entity, `null` otherwise -### `query(e,'pickup_delay')` +### `query(e, 'pickup_delay')` Retrieves pickup delay timeout for an item entity, `null` otherwise -### `query(e,'is_baby')` +### `query(e, 'is_baby')` Boolean, true if its a baby. -### `query(e,'target')` +### `query(e, 'target')` Returns mob's attack target or null if none or not applicable. -### `query(e,'home')` +### `query(e, 'home')` Returns creature's home position or null if none or not applicable. @@ -239,31 +239,31 @@ Returns a pose of an entity, one of the following options * `'crouching'` * `'dying'` -### `query(e,'sneaking')` +### `query(e, 'sneaking')` -Boolean, true if entity is sneaking. +Boolean, true if the entity is sneaking. -### `query(e,'sprinting')` +### `query(e, 'sprinting')` -Boolean, true if entity is sprinting. +Boolean, true if the entity is sprinting. -### `query(e,'swimming')` +### `query(e, 'swimming')` -Boolean, true if entity is swimming. +Boolean, true if the entity is swimming. -### `query(e,'jumping')` +### `query(e, 'jumping')` -Boolean, true if entity is jumping. +Boolean, true if the entity is jumping. -### `query(e,'gamemode')` +### `query(e, 'gamemode')` String with gamemode, or `null` if not a player. -### `query(e,'gamemode_id')` +### `query(e, 'gamemode_id')` Good'ol gamemode id, or null if not a player. -### `query(e,'player_type')` +### `query(e, 'player_type')` Returns `null` if the argument is not a player, otherwise: @@ -282,18 +282,18 @@ Returns a lowercase string containing the category of the entity (hostile, passi Team name for entity, or `null` if no team is assigned. -### `query(e,'ping')` +### `query(e, 'ping')` Player's ping in milliseconds, or `null` if its not a player. -### `query(e,'permission_level')` +### `query(e, 'permission_level')` Player's permission level, or `null` if not applicable for this entity. -### `query(e,'effect',name?)` +### `query(e, 'effect', name?)` Without extra arguments, it returns list of effect active on a living entity. Each entry is a triple of short -effect name, amplifier, and remaining duration. With an argument, if the living entity has not that potion active, +effect name, amplifier, and remaining duration in ticks. With an argument, if the living entity has not that potion active, returns `null`, otherwise return a tuple of amplifier and remaining duration.
@@ -302,13 +302,13 @@ query(p,'effect','haste')  => [0, 177]
 query(p,'effect','resistance')  => null
 
-### `query(e,'health')` +### `query(e, 'health')` Number indicating remaining entity health, or `null` if not applicable. -### `query(e,'holds',slot?)` +### `query(e, 'holds', slot?)` -Returns triple of short name, stack count, and NBT of item held in `slot`. Available options for `slot` are: +Returns triple of short name, stack count, and NBT of item held in `slot`, or `null` if nothing or not applicable. Available options for `slot` are: * `mainhand` * `offhand` @@ -319,16 +319,16 @@ Returns triple of short name, stack count, and NBT of item held in `slot`. Avail If `slot` is not specified, it defaults to the main hand. -### `query(e,'selected_slot')` +### `query(e, 'selected_slot')` -Number indicating the selected slot of entity inventory. Currently only applicable to players. +Number indicating the selected slot of entity's inventory. Currently only applicable to players. -### `query(e,'facing', order?)` +### `query(e, 'facing', order?)` Returns where the entity is facing. optional order (number from 0 to 5, and negative), indicating primary directions where entity is looking at. From most prominent (order 0) to opposite (order 5, or -1) -### `query(e,'trace', reach?, options?...)` +### `query(e, 'trace', reach?, options?...)` Returns the result of ray tracing from entity perspective, indicating what it is looking at. Default reach is 4.5 blocks (5 for creative players), and by default it traces for blocks and entities, identical to player attack tracing @@ -340,9 +340,9 @@ entities and blocks, blocks will take over the priority even if transparent or n Regardless of the options selected, the result could be `null` if nothing is in reach, entity, if look targets an entity, and block value if block is in reach. -### `query(e,'nbt',path?)` +### `query(e, 'nbt', path?)` -Returns full NBT of the entity. If path is specified, it fetches only that portion of the NBT, that corresponds to the +Returns full NBT of the entity. If path is specified, it fetches only the portion of the NBT that corresponds to the path. For specification of `path` attribute, consult vanilla `/data get entity` command. Note that calls to `nbt` are considerably more expensive comparing to other calls in Minecraft API, and should only @@ -354,13 +354,13 @@ type objects via `get, put, has, delete`, so try to use API calls first for that Like with entity querying, entity modifications happen through one function. Most position and movements modifications don't work currently on players as their position is controlled by clients. -Currently there is no ability to modify NBT directly, but you could always use `run('data modify entity` +Currently there is no ability to modify NBT directly, but you could always use `run('data modify entity ...')` -### `modify(e,'remove')` +### `modify(e, 'remove')` Removes (not kills) entity from the game. -### `modify(e,'kill')` +### `modify(e, 'kill')` Kills the entity. @@ -374,7 +374,7 @@ Changes full location vector all at once. ### `modify(e, 'x', x), modify(e, 'y', y), modify(e, 'z', z)` -Moves the entity in.... one direction. +Moves the entity in one direction. ### `modify(e, 'pitch', pitch), modify(e, 'yaw', yaw)` @@ -396,7 +396,9 @@ Sets the corresponding component of the motion vector. Adds a vector to the motion vector. Most realistic way to apply a force to an entity. -### `modify(e, 'custom_name'), modify(e, 'custom_name', name )` +### `modify(e, 'custom_name'), modify(e, 'custom_name', name)` + +Sets the custom name of the entity. ### `modify(e, 'age', number)` @@ -405,8 +407,12 @@ entities, so use it with caution. ### `modify(e, 'pickup_delay', number)` +Sets the pickup delay for the item entity. + ### `modify(e, 'breeding_age', number)` +Sets the breeding age for the animal. + ### `modify(e, 'despawn_timer', number)` Sets a custom despawn timer value. @@ -429,11 +435,11 @@ Mounts on all listed entities on `e`. ### `modify(e, 'tag', tag, ? ...), modify(e, 'tag', l(tags) )` -Adds tag / tags to the entity. +Adds tag(s) to the entity. ### `modify(e, 'clear_tag', tag, ? ...), modify(e, 'clear_tag', l(tags) )` -Removes tag from entity. +Removes tag(s) from the entity. ### `modify(e, 'talk')` @@ -446,19 +452,19 @@ If called with `false` value, it will disable AI in the mob. `true` will enable ### `modify(e, 'no_clip', boolean)` Sets if the entity obeys any collisions, including collisions with the terrain and basic physics. Not affecting -players, since they are controlled client side +players, since they are controlled client side. ### `modify(e, 'effect', name, duration?, amplifier?, show_particles?, show_icon?)` Applies status effect to the living entity. Takes several optional parameters, which default to `0`, `true` -and `true`. If no duration is specified, or it is null or 0, the effect is removed. +and `true`. If no duration is specified, or if it's null or 0, the effect is removed. ### `modify(e, 'home', null), modify(e, 'home', block, distance?), modify(e, 'home', x, y, z, distance?)` Sets AI to stay around the home position, within `distance` blocks from it. `distance` defaults to 16 blocks. `null` removes it. _May_ not work fully with mobs that have this AI built in, like Villagers. -### `modify(e, 'gamemode', gamemode?), modify(e, 'gamemode',gamemode_id?)` +### `modify(e, 'gamemode', gamemode?), modify(e, 'gamemode', gamemode_id?)` Modifies gamemode of player to whatever string (case-insensitive) or number you put in. @@ -467,7 +473,7 @@ Modifies gamemode of player to whatever string (case-insensitive) or number you * 2: adventure * 3: spectator -### `modify(e, 'jumping', true/false)` +### `modify(e, 'jumping', boolean)` Will make the entity constantly jump if set to true, and will stop the entity from jumping if set to false. Note that jumping parameter can be fully controlled by the entity AI, so don't expect that this will have @@ -479,13 +485,17 @@ Requires a living entity as an argument. Will make the entity jump once. -### `modify(e, 'silent', true/false)` +### `modify(e, 'silent', boolean)` -### `modify(e, 'gravity', true/false)` +Silences or unsilences the entity. + +### `modify(e, 'gravity', boolean)` + +Toggles gravity for the entity. ### `modify(e, 'fire', ticks)` -Will set mob on fire for `ticks` ticks. Set to 0 to extinguish. +Will set entity on fire for `ticks` ticks. Set to 0 to extinguish. ## Entity Events @@ -497,19 +507,19 @@ defining the callback with `entity_event` The following events can be handled by entities. -* `'on_tick'`: executes every tick right before entity is ticked in the game. Required arguments: `entity` +* `'on_tick'`: executes every tick right before the entity is ticked in the game. Required arguments: `entity` * `'on_death'`: executes once when a living entity dies. Required arguments: `entity, reason` * `'on_removed'`: execute once when an entity is removed. Required arguments: `entity` * `'on_damaged'`: executed every time a living entity is about to receive damage. Required arguments: `entity, amount, source, attacking_entity` It doesn't mean that all entity types will have a chance to execute a given event, but entities will not error -when you will attach inapplicable event to it. +when you attach inapplicable event to it. ### `entity_event(e, event, call_name, args...)` -Attaches specific function from the current package to be called upon the `event`, with extra `args` curried to the -original required arguments for the event handler +Attaches specific function from the current package to be called upon the `event`, with extra `args` carried to the +original required arguments for the event handler.
 protect_villager(entity, amount, source, source_entity, healing_player) ->

From d0bd956bbd0362c809349fb2075c46121ca27812 Mon Sep 17 00:00:00 2001
From: gnembon 
Date: Tue, 12 May 2020 15:26:20 -0300
Subject: [PATCH 122/198] double evaluation, fixes #271

---
 src/main/java/carpet/script/CarpetExpression.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java
index 65e1dba5..22020af1 100644
--- a/src/main/java/carpet/script/CarpetExpression.java
+++ b/src/main/java/carpet/script/CarpetExpression.java
@@ -1996,7 +1996,7 @@ public class CarpetExpression
                 ((EntityValue) v).set(what, lv.get(2).evalValue(c));
             else
                 ((EntityValue) v).set(what, ListValue.wrap(lv.subList(2, lv.size()).stream().map((vv) -> vv.evalValue(c)).collect(Collectors.toList())));
-            return lv.get(0);
+            return (cc, tt) -> v;
         });
 
         // or update

From 849a7b8eeb24dcbb223a5eab5a515826fad7dbd7 Mon Sep 17 00:00:00 2001
From: gnembon 
Date: Tue, 12 May 2020 15:29:36 -0300
Subject: [PATCH 123/198] merge changes to full.md

---
 docs/scarpet/Full.md | 352 ++++++++++++++++++++++---------------------
 1 file changed, 181 insertions(+), 171 deletions(-)

diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md
index c07aaba4..dba29bf2 100644
--- a/docs/scarpet/Full.md
+++ b/docs/scarpet/Full.md
@@ -1626,8 +1626,8 @@ set(x,y,z,'hopper[facing=north]{Items:[{Slot:1b,id:"minecraft:slime_ball",Count:
 
 Evaluates subexpression without causing updates when blocks change in the world
 
-Consider following scenario: We would like to generate a bunch of terrain in a flat world following a perling noise 
-generator. The following code causes cascading effect as blocks placed on chunk borders will cause other chunks to get 
+Consider following scenario: We would like to generate a bunch of terrain in a flat world following a perlin noise 
+generator. The following code causes a cascading effect as blocks placed on chunk borders will cause other chunks to get 
 loaded to full, thus generated:
 
 
@@ -1641,7 +1641,7 @@ __on_chunk_generated(x, z) -> (
 )
 
-The following addition resolves this issue, by not allowing block updates pass chunk borders: +The following addition resolves this issue, by not allowing block updates past chunk borders:
 __config() -> m(l('scope', 'global'));
@@ -1666,7 +1666,7 @@ block, or 'up-north', which means a block placed facing up (player looking down)
 center towards north. Optional sneak is a boolean indicating if a player would be sneaking while placing the 
 block - this option only affects placement of chests and scaffolding at the moment. 
 
-Works with items that have the right-click effect on the block placed, `'like bone_meal`` on grass or axes on logs,
+Works with items that have the right-click effect on the block placed, like `bone_meal` on grass or axes on logs,
 but doesn't open chests / containers, so have no effect on interactive blocks, like TNT, comparators, etc.
 
 Returns true if placement/use was 
@@ -1692,7 +1692,7 @@ markers for scarpet apps. `meeting` is the only one with increased max occupancy
 
 ### `set_biome(pos, biome_name)`
 
-changes biome at that block position.
+Changes the biome at that block position.
 
 ### `update(pos)`
 
@@ -1708,7 +1708,7 @@ Causes a random tick at position.
 
 ### `destroy(pos), destroy(pos, -1), destroy(pos, ), destroy(pos, tool, nbt?)`
 
-Destroys the block like it was mined by a player. Add -1 for silk touch, and positive number for fortune level. 
+Destroys the block like it was mined by a player. Add -1 for silk touch, and a positive number for fortune level. 
 If tool is specified, and optionally its nbt, it will use that tool and will attempt to mine the block with this tool. 
 If called without item context, this function, unlike harvest, will affect all kinds of blocks. If called with item 
 in context, it will fail to break blocks that cannot be broken by a survival player.
@@ -1724,28 +1724,28 @@ for mining. Obviously, in this case the use of `harvest` would be much more appl
 
 mine(x,y,z) ->
 (
-   p = player();
-   slot = p~'selected_slot';
-   item_tuple = inventory_get(p, slot);
-   if (!item_tuple, destroy(x,y,z,'air'); return()); // empty hand, just break with 'air'
-   l(item, count, tag) = item_tuple;
-   tag_back = destroy(x,y,z, item, tag);
-   if (tag_back == false, // failed to break the item
-	     return(tag_back)
-   );
-   if (tag_back == true, // block broke, tool has no tag
-	     return(tag_back)
-   );
-   if (tag_back == null, //item broke
-	     delete(tag:'Damage');
-	     inventory_set(p, slot, count-1, item, tag);
-	     return(tag_back)
-   );
-   if (type(tag_back) == 'nbt', // item didn't break, here is the effective nbt
-	     inventory_set(p, slot, count, item, tag_back);
-	     return(tag_back)
-   );
-   print('How did we get here?');
+  p = player();
+  slot = p~'selected_slot';
+  item_tuple = inventory_get(p, slot);
+  if (!item_tuple, destroy(x,y,z,'air'); return()); // empty hand, just break with 'air'
+  l(item, count, tag) = item_tuple;
+  tag_back = destroy(x,y,z, item, tag);
+  if (tag_back == false, // failed to break the item
+    return(tag_back)
+  );
+  if (tag_back == true, // block broke, tool has no tag
+    return(tag_back)
+  );
+  if (tag_back == null, //item broke
+    delete(tag:'Damage');
+    inventory_set(p, slot, count-1, item, tag);
+    return(tag_back)
+  );
+  if (type(tag_back) == 'nbt', // item didn't break, here is the effective nbt
+    inventory_set(p, slot, count, item, tag_back);
+    return(tag_back)
+  );
+  print('How did we get here?');
 )
 
@@ -1763,9 +1763,9 @@ Returns a triple of coordinates of a specified block or entity. Technically enti and the same can be achieved with `query(entity,'pos')`, but for simplicity `pos` allows to pass all positional objects.
-pos(block(0,5,0))  => l(0,5,0)
+pos(block(0,5,0)) => l(0,5,0)
 pos(players()) => l(12.3, 45.6, 32.05)
-pos(block('stone'))  => Error: Cannot fetch position of an unrealized block
+pos(block('stone')) => Error: Cannot fetch position of an unrealized block
 
### `pos_offset(pos, direction, amount?)` @@ -1823,51 +1823,51 @@ poi(x,y,z,5) => [['nether_portal',0,[7,8,9]],['nether_portal',0,[7,9,9]]] // two ### `biome(pos)` -returns biome at that block position. +Returns the biome at that block position. ### `solid(pos)` -Boolean function, true if the block is solid +Boolean function, true if the block is solid. ### `air(pos)` -Boolean function, true if a block is air.... or cave air... or void air.... or any other air they come up with. +Boolean function, true if a block is air... or cave air... or void air... or any other air they come up with. ### `liquid(pos)` -Boolean function, true if the block is liquid, or liquidlogged +Boolean function, true if the block is liquid, or waterlogged (with any liquid). ### `flammable(pos)` -Boolean function, true if the block is flammable +Boolean function, true if the block is flammable. ### `transparent(pos)` -Boolean function, true if the block is transparent +Boolean function, true if the block is transparent. ### `opacity(pos)` -Numeric, returning opacity level of a block +Numeric function, returning the opacity level of a block. ### `blocks_daylight(pos)` -Boolean function, true if the block blocks daylight +Boolean function, true if the block blocks daylight. ### `emitted_light(pos)` -Numeric, returning light level emitted from block +Numeric function, returning the light level emitted from the block. ### `light(pos)` -Integer function, returning total light level at position +Numeric function, returning the total light level at position. ### `block_light(pos)` -Integer function, returning block light at position. From torches and other light sources. +Numeric function, returning the block light at position (from torches and other light sources). ### `sky_light(pos)` -Numeric function, returning sky light at position. From the sky access. +Numeric function, returning the sky light at position (from sky access). ### `see_sky(pos)` @@ -1915,7 +1915,7 @@ Boolean function, true if the block ticks randomly. ### `blocks_movement(pos)` -Boolean function, true if block at position blocks movement. +Boolean function, true if the block at position blocks movement. ### `block_sound(pos)` @@ -2041,11 +2041,11 @@ Returns the map colour of a block at position. One of: ### `loaded(pos)` Boolean function, true if the block is accessible for the game mechanics. Normally `scarpet` doesn't check if operates -on loaded area - the game will automatically load missing blocks. We see this as advantage. Vanilla `fill/clone` +on loaded area - the game will automatically load missing blocks. We see this as an advantage. Vanilla `fill/clone` commands only check the specified corners for loadness. -To check if block is truly loaded, I mean in memory, use `generation_status(x) != null`, as chunks can still be loaded -outside of the playable area, just are not used any of the game mechanics processes. +To check if a block is truly loaded, I mean in memory, use `generation_status(x) != null`, as chunks can still be loaded +outside of the playable area, just are not used by any of the game mechanic processes.
 loaded(pos(players()))  => 1
@@ -2060,7 +2060,7 @@ Deprecated as of scarpet 1.6, use `loaded_status(x) > 0`, or just `loaded(x)` wi
 
 ### `loaded_status(pos)`
 
-Returns loaded status as per new 1.14 chunk ticket system, 0 for inaccessible, 1 for border chunk, 2 for ticking, 
+Returns loaded status as per new 1.14 chunk ticket system, 0 for inaccessible, 1 for border chunk, 2 for redstone ticking, 
 3 for entity ticking
 
 ### `is_chunk_generated(pos)`, `is_chunk_generated(pos, force)`
@@ -2095,10 +2095,10 @@ Returns spawn potential at a location (1.16+ only)
 Checks wordgen eligibility for a structure in a given chunk. If no structure is given, or `null`, then it will check
  for all structures. If bounding box of the structures is also requested, it will compute size of potential
   structures. This function, unlike other in the `structure*` category is not using world data nor accesses chunks
-  making it preferred for scoping ungenerated terrain, but it takes some compute money to calculate the structure.
+  making it preferred for scoping ungenerated terrain, but it takes some compute resources to calculate the structure.
   
   Unlike `'structure'` this will return a tentative structure location. Random factors in world generation may prevent
-  actual structure from forming.
+  the actual structure from forming.
   
 If structure is specified, it will return `null` if a chunk is not eligible, `true` if the structure should appear, or 
 a map with two values: `'box'` for a pair of coordinates indicating bounding box of the structure, and `'pieces'` for 
@@ -2131,7 +2131,7 @@ then to get its bounding boxes.
 
 Creates or removes structure information of a structure associated with a chunk of `pos`. Unlike `plop`, blocks are 
 not placed in the world, only structure information is set. For the game this is a fully functional structure even 
-if blocks are not set. To remove structure a given point is in, use `structure_references` to find where current 
+if blocks are not set. To remove the structure a given point is in, use `structure_references` to find where current 
 structure starts.
 
 ### `plop(pos, what)`
@@ -2272,7 +2272,7 @@ These functions help scan larger areas of blocks without using generic loop func
 Evaluates expression over area of blocks defined by its center `center = (cx, cy, cz)`, expanded in all directions 
 by `range = (dx, dy, dz)` blocks, or optionally in negative with `range` coords, and `upper_range` coords in 
 positive values.
-`center` can be defined either as a three coordinates, list of three coords, or block value.
+`center` can be defined either as three coordinates, a list of three coords, or a block value.
 `range` and `lower_range` can have the same representations, just if its a block, it computes the distance to the center
 as range instead of taking the values as is.
 `expr` receives `_x, _y, _z` as coords of current analyzed block and `_`, which represents the block itself.
@@ -2285,7 +2285,7 @@ return value. `break` return value has no effect.
 
 ### `volume(x1, y1, z1, x2, y2, z2, expr)`
 
-Evaluates expression for each block in the area, the same as the `scan`function, but using two opposite corners of 
+Evaluates expression for each block in the area, the same as the `scan` function, but using two opposite corners of 
 the rectangular cuboid. Any corners can be specified, its like you would do with `/fill` command.
 
 For return value and handling `break` and `continue` statements, see `scan` function above.
@@ -2301,7 +2301,7 @@ for(neighbours(x,y,z),air(_)) => 4 // number of air blocks around a block
 ### `rect(cx, cy, cz, dx?, dy?, dz?, px?, py?, pz?)`
 
 returns an iterator, just like `range` function that iterates over rectangular cubarea of blocks. If only center 
-point is specified, it iterates over 27 blocks. If `d` arguments are specified, expands selection of respective 
+point is specified, it iterates over 27 blocks. If `d` arguments are specified, expands selection by the  respective 
 number of blocks in each direction. If `p` arguments are specified, it uses `d` for negative offset, and `p` for positive.
 
 ### `diamond(cx, cy, cz, radius?, height?)`
@@ -2314,23 +2314,23 @@ Any of these can be zero as well. radius of 0 makes a stick, height of 0 makes a
 ## Entity Selection
 
 Entities have to be fetched before using them. Entities can also change their state between calls to the script if 
-game happens either in between separate calls to the programs, or if the program calls `game_tick` on its own. 
-In this case - entities would need to be re-fetched, or the code should account for entities getting dead.
+game ticks occur either in between separate calls to the programs, or if the program calls `game_tick` on its own. 
+In this case - entities would need to be re-fetched, or the code should account for entities dying.
 
 ### `player(), player(type), player(name)`
 
 With no arguments, it returns the calling player or the player closest to the caller. Note that the main context 
-will receive `p` variable pointing to this player. With `type` or `name` specified it will try first to match a type, 
+will receive `p` variable pointing to this player. With `type` or `name` specified, it will try first to match a type, 
 returning a list of players matching a type, and if this fails, will assume its player name query retuning player with 
 that name, or `null` if no player was found. With `'all'`, list of all players in the game, in all dimensions, so end 
 user needs to be cautious, that you might be referring to wrong blocks and entities around the player in question. 
 With `type = '*'` it returns all players in caller dimension, `'survival'` returns all survival and adventure players,
 `'creative'` returns all creative players, `'spectating'` returns all spectating players, and `'!spectating'`, 
-all not-spectating players. If all fails, with `name`, the player in question, if is logged in.
+all not-spectating players. If all fails, with `name`, the player in question, if he/she is logged in.
 
 ### `entity_id(uuid), entity_id(id)`
 
-Fetching entities wither by their ID obtained via `entity ~ 'id'`, which is unique for a dimension and current world 
+Fetching entities either by their ID obtained via `entity ~ 'id'`, which is unique for a dimension and current world 
 run, or by UUID, obtained via `entity ~ 'uuid'`. It returns null if no such entity is found. Safer way to 'store' 
 entities between calls, as missing entities will be returning `null`. Both calls using UUID or numerical ID are `O(1)`, 
 but obviously using UUIDs takes more memory and compute.
@@ -2349,12 +2349,12 @@ selectors are available:
 ### `entity_area(type, cx, cy, cz, dx, dy, dz)`
 
 Returns entities of a specified type in an area centered on `cx, cy, cz` and at most `dx, dy, dz` blocks away from 
-the center point. Uses same selectors as `entities_list`
+the center point. Uses the same selectors as `entities_list`.
 
 ### `entity_selector(selector)`
 
-Returns entities satisfying given vanilla entity selector. Most complex among all the methods of selecting entities, 
-but the most capable. Selectors are cached so should be as fast as other methods of selecting entities.
+Returns entities satisifying given vanilla entity selector. Most complex among all the methods of selecting entities, 
+but the most capable. Selectors are cached so it should be as fast as other methods of selecting entities.
 
 ### `spawn(name, pos, nbt?)`
 
@@ -2364,67 +2364,67 @@ you get the entity back as a return value, which is swell.
 
 ## Entity Manipulation
 
-Unlike with blocks, that use plethora of vastly different querying functions, entities are queried with `query` 
-function and altered via `modify` function. Type of information needed or values to be modified are different for 
+Unlike with blocks, that use a plethora of vastly different querying functions, entities are queried with the `query` 
+function and altered via the `modify` function. Type of information needed or values to be modified are different for 
 each call.
 
 Using `~` (in) operator is an alias for `query`. Especially useful if a statement has no arguments, 
-which in this case can be radically simplified
+which in this case can be radically simplified:
 
 
 query(p, 'name') <=> p ~ 'name'     // much shorter and cleaner
 query(p, 'holds', 'offhand') <=> p ~ l('holds', 'offhand')    // not really but can be done
 
-### `query(e,'removed')` +### `query(e, 'removed')` -Boolean. True if the entity is removed +Boolean. True if the entity is removed. -### `query(e,'id')` +### `query(e, 'id')` Returns numerical id of the entity. Most efficient way to keep track of entites in a script. Ids are only unique within current game session (ids are not preserved between restarts), -and dimension (each dimension has its own ids which can overlap. +and dimension (each dimension has its own ids which can overlap). -### `query(e,'uuid')` +### `query(e, 'uuid')` -Returns UUID (unique id) of the entity. Can be used to access entities with the other vanilla commands and +Returns the UUID (unique id) of the entity. Can be used to access entities with the other vanilla commands and remains unique regardless of the dimension, and is preserved between game restarts. Apparently players cannot be -accessed via UUID, but name instead. +accessed via UUID, but should be accessed with their name instead.
 map(entities_area('*',x,y,z,30,30,30),run('kill '+query(_,'id'))) // doesn't kill the player
 
-### `query(e,'pos')` +### `query(e, 'pos')` -Triple of entity position +Triple of the entity's position -### `query(e,'location')` +### `query(e, 'location')` -Quin-tuple of entity position (x, y, and z coords), and rotation (yaw, pitch) +Quin-tuple of the entity's position (x, y, and z coords), and rotation (yaw, pitch) -### `query(e,'x'), query(e,'y'), query(e,'z')` +### `query(e, 'x'), query(e, 'y'), query(e, 'z')` -Respective entity coordinate +Respective component of entity's coordinates -### `query(e,'pitch'), query(e,'yaw')` +### `query(e, 'pitch'), query(e, 'yaw')` Pitch and Yaw or where entity is looking. -### `query(e,'look')` +### `query(e, 'look')` Returns a 3d vector where the entity is looking. -### `query(e,'motion')` +### `query(e, 'motion')` -Triple of entity motion vector, `l(motion_x, motion_y, motion_z)` +Triple of entity's motion vector, `l(motion_x, motion_y, motion_z)` -### `query(e,'motion_x'), query(e,'motion_y'), query(e,'motion_z')` +### `query(e, 'motion_x'), query(e, 'motion_y'), query(e, 'motion_z')` -Respective component of the motion vector +Respective component of the entity's motion vector -### `query(e,'name'), query(e,'display_name'), query(e,'custom_name'), query(e,'type')` +### `query(e, 'name'), query(e, 'display_name'), query(e, 'custom_name'), query(e, 'type')` String of entity name @@ -2443,99 +2443,99 @@ player, where its their name. run('/kill ' + e~'command_name');
-### `query(e,'is_riding')` +### `query(e, 'is_riding')` -Boolean. True if riding another entity. +Boolean, true if the entity is riding another entity. -### `query(e,'is_ridden')` +### `query(e, 'is_ridden')` -Boolean. True if another entity is riding it. +Boolean, true if another entity is riding it. -### `query(e,'passengers')` +### `query(e, 'passengers')` List of entities riding the entity. -### `query(e,'mount')` +### `query(e, 'mount')` Entity that `e` rides. -### `query(e,'tags')` +### `query(e, 'tags')` -List of entity tags. +List of entity's tags. -### `query(e,'has_tag',tag)` +### `query(e, 'has_tag',tag)` -Boolean, True if the entity is marked with `tag`. +Boolean, true if the entity is marked with `tag`. -### `query(e,'is_burning')` +### `query(e, 'is_burning')` -Boolean, True if the entity is burning. +Boolean, true if the entity is burning. -### `query(e,'fire')` +### `query(e, 'fire')` Number of remaining ticks of being on fire. -### `query(e,'silent')` +### `query(e, 'silent')` -Boolean, True if the entity is silent. +Boolean, true if the entity is silent. -### `query(e,'gravity')` +### `query(e, 'gravity')` -Boolean, True if the entity is affected by gravity, like most entities do. +Boolean, true if the entity is affected by gravity, like most entities are. -### `query(e,'immune_to_fire')` +### `query(e, 'immune_to_fire')` -Boolean, True if the entity is immune to fire. +Boolean, true if the entity is immune to fire. -### `query(e,'dimension')` +### `query(e, 'dimension')` -Name of the dimension entity is in. +Name of the dimension the entity is in. -### `query(e,'height')` +### `query(e, 'height')` -Height of the entity. +Height of the entity in blocks. -### `query(e,'width')` +### `query(e, 'width')` -Width of the entity. +Width of the entity in blocks. -### `query(e,'eye_height')` +### `query(e, 'eye_height')` -Eye height of the entity. +Eye height of the entity in blocks. -### `query(e,'age')` +### `query(e, 'age')` -Age, in ticks, of the entity, i.e. how long it existed. +Age of the entity in ticks, i.e. how long it existed. -### `query(e,'breeding_age')` +### `query(e, 'breeding_age')` -Breeding age of passive entity, in ticks. If negative it it time to adulthood, if positive, breeding cooldown +Breeding age of passive entity, in ticks. If negative, time to adulthood, if positive, breeding cooldown -### `query(e,'despawn_timer')` +### `query(e, 'despawn_timer')` -For living entities - the number of ticks they fall outside of immediate player presence. +For living entities, the number of ticks they fall outside of immediate player presence. -### `query(e,'item')` +### `query(e, 'item')` The item triple (name, count, nbt) if its an item entity, `null` otherwise -### `query(e,'count')` +### `query(e, 'count')` Number of items in a stack from item entity, `null` otherwise -### `query(e,'pickup_delay')` +### `query(e, 'pickup_delay')` Retrieves pickup delay timeout for an item entity, `null` otherwise -### `query(e,'is_baby')` +### `query(e, 'is_baby')` Boolean, true if its a baby. -### `query(e,'target')` +### `query(e, 'target')` Returns mob's attack target or null if none or not applicable. -### `query(e,'home')` +### `query(e, 'home')` Returns creature's home position or null if none or not applicable. @@ -2550,31 +2550,31 @@ Returns a pose of an entity, one of the following options * `'crouching'` * `'dying'` -### `query(e,'sneaking')` +### `query(e, 'sneaking')` -Boolean, true if entity is sneaking. +Boolean, true if the entity is sneaking. -### `query(e,'sprinting')` +### `query(e, 'sprinting')` -Boolean, true if entity is sprinting. +Boolean, true if the entity is sprinting. -### `query(e,'swimming')` +### `query(e, 'swimming')` -Boolean, true if entity is swimming. +Boolean, true if the entity is swimming. -### `query(e,'jumping')` +### `query(e, 'jumping')` -Boolean, true if entity is jumping. +Boolean, true if the entity is jumping. -### `query(e,'gamemode')` +### `query(e, 'gamemode')` String with gamemode, or `null` if not a player. -### `query(e,'gamemode_id')` +### `query(e, 'gamemode_id')` Good'ol gamemode id, or null if not a player. -### `query(e,'player_type')` +### `query(e, 'player_type')` Returns `null` if the argument is not a player, otherwise: @@ -2593,18 +2593,18 @@ Returns a lowercase string containing the category of the entity (hostile, passi Team name for entity, or `null` if no team is assigned. -### `query(e,'ping')` +### `query(e, 'ping')` Player's ping in milliseconds, or `null` if its not a player. -### `query(e,'permission_level')` +### `query(e, 'permission_level')` Player's permission level, or `null` if not applicable for this entity. -### `query(e,'effect',name?)` +### `query(e, 'effect', name?)` Without extra arguments, it returns list of effect active on a living entity. Each entry is a triple of short -effect name, amplifier, and remaining duration. With an argument, if the living entity has not that potion active, +effect name, amplifier, and remaining duration in ticks. With an argument, if the living entity has not that potion active, returns `null`, otherwise return a tuple of amplifier and remaining duration.
@@ -2613,13 +2613,13 @@ query(p,'effect','haste')  => [0, 177]
 query(p,'effect','resistance')  => null
 
-### `query(e,'health')` +### `query(e, 'health')` Number indicating remaining entity health, or `null` if not applicable. -### `query(e,'holds',slot?)` +### `query(e, 'holds', slot?)` -Returns triple of short name, stack count, and NBT of item held in `slot`. Available options for `slot` are: +Returns triple of short name, stack count, and NBT of item held in `slot`, or `null` if nothing or not applicable. Available options for `slot` are: * `mainhand` * `offhand` @@ -2630,16 +2630,16 @@ Returns triple of short name, stack count, and NBT of item held in `slot`. Avail If `slot` is not specified, it defaults to the main hand. -### `query(e,'selected_slot')` +### `query(e, 'selected_slot')` -Number indicating the selected slot of entity inventory. Currently only applicable to players. +Number indicating the selected slot of entity's inventory. Currently only applicable to players. -### `query(e,'facing', order?)` +### `query(e, 'facing', order?)` Returns where the entity is facing. optional order (number from 0 to 5, and negative), indicating primary directions where entity is looking at. From most prominent (order 0) to opposite (order 5, or -1) -### `query(e,'trace', reach?, options?...)` +### `query(e, 'trace', reach?, options?...)` Returns the result of ray tracing from entity perspective, indicating what it is looking at. Default reach is 4.5 blocks (5 for creative players), and by default it traces for blocks and entities, identical to player attack tracing @@ -2651,9 +2651,9 @@ entities and blocks, blocks will take over the priority even if transparent or n Regardless of the options selected, the result could be `null` if nothing is in reach, entity, if look targets an entity, and block value if block is in reach. -### `query(e,'nbt',path?)` +### `query(e, 'nbt', path?)` -Returns full NBT of the entity. If path is specified, it fetches only that portion of the NBT, that corresponds to the +Returns full NBT of the entity. If path is specified, it fetches only the portion of the NBT that corresponds to the path. For specification of `path` attribute, consult vanilla `/data get entity` command. Note that calls to `nbt` are considerably more expensive comparing to other calls in Minecraft API, and should only @@ -2665,13 +2665,13 @@ type objects via `get, put, has, delete`, so try to use API calls first for that Like with entity querying, entity modifications happen through one function. Most position and movements modifications don't work currently on players as their position is controlled by clients. -Currently there is no ability to modify NBT directly, but you could always use `run('data modify entity` +Currently there is no ability to modify NBT directly, but you could always use `run('data modify entity ...')` -### `modify(e,'remove')` +### `modify(e, 'remove')` Removes (not kills) entity from the game. -### `modify(e,'kill')` +### `modify(e, 'kill')` Kills the entity. @@ -2685,7 +2685,7 @@ Changes full location vector all at once. ### `modify(e, 'x', x), modify(e, 'y', y), modify(e, 'z', z)` -Moves the entity in.... one direction. +Moves the entity in one direction. ### `modify(e, 'pitch', pitch), modify(e, 'yaw', yaw)` @@ -2707,7 +2707,9 @@ Sets the corresponding component of the motion vector. Adds a vector to the motion vector. Most realistic way to apply a force to an entity. -### `modify(e, 'custom_name'), modify(e, 'custom_name', name )` +### `modify(e, 'custom_name'), modify(e, 'custom_name', name)` + +Sets the custom name of the entity. ### `modify(e, 'age', number)` @@ -2716,8 +2718,12 @@ entities, so use it with caution. ### `modify(e, 'pickup_delay', number)` +Sets the pickup delay for the item entity. + ### `modify(e, 'breeding_age', number)` +Sets the breeding age for the animal. + ### `modify(e, 'despawn_timer', number)` Sets a custom despawn timer value. @@ -2740,11 +2746,11 @@ Mounts on all listed entities on `e`. ### `modify(e, 'tag', tag, ? ...), modify(e, 'tag', l(tags) )` -Adds tag / tags to the entity. +Adds tag(s) to the entity. ### `modify(e, 'clear_tag', tag, ? ...), modify(e, 'clear_tag', l(tags) )` -Removes tag from entity. +Removes tag(s) from the entity. ### `modify(e, 'talk')` @@ -2757,19 +2763,19 @@ If called with `false` value, it will disable AI in the mob. `true` will enable ### `modify(e, 'no_clip', boolean)` Sets if the entity obeys any collisions, including collisions with the terrain and basic physics. Not affecting -players, since they are controlled client side +players, since they are controlled client side. ### `modify(e, 'effect', name, duration?, amplifier?, show_particles?, show_icon?)` Applies status effect to the living entity. Takes several optional parameters, which default to `0`, `true` -and `true`. If no duration is specified, or it is null or 0, the effect is removed. +and `true`. If no duration is specified, or if it's null or 0, the effect is removed. ### `modify(e, 'home', null), modify(e, 'home', block, distance?), modify(e, 'home', x, y, z, distance?)` Sets AI to stay around the home position, within `distance` blocks from it. `distance` defaults to 16 blocks. `null` removes it. _May_ not work fully with mobs that have this AI built in, like Villagers. -### `modify(e, 'gamemode', gamemode?), modify(e, 'gamemode',gamemode_id?)` +### `modify(e, 'gamemode', gamemode?), modify(e, 'gamemode', gamemode_id?)` Modifies gamemode of player to whatever string (case-insensitive) or number you put in. @@ -2778,7 +2784,7 @@ Modifies gamemode of player to whatever string (case-insensitive) or number you * 2: adventure * 3: spectator -### `modify(e, 'jumping', true/false)` +### `modify(e, 'jumping', boolean)` Will make the entity constantly jump if set to true, and will stop the entity from jumping if set to false. Note that jumping parameter can be fully controlled by the entity AI, so don't expect that this will have @@ -2790,13 +2796,17 @@ Requires a living entity as an argument. Will make the entity jump once. -### `modify(e, 'silent', true/false)` +### `modify(e, 'silent', boolean)` -### `modify(e, 'gravity', true/false)` +Silences or unsilences the entity. + +### `modify(e, 'gravity', boolean)` + +Toggles gravity for the entity. ### `modify(e, 'fire', ticks)` -Will set mob on fire for `ticks` ticks. Set to 0 to extinguish. +Will set entity on fire for `ticks` ticks. Set to 0 to extinguish. ## Entity Events @@ -2808,19 +2818,19 @@ defining the callback with `entity_event` The following events can be handled by entities. -* `'on_tick'`: executes every tick right before entity is ticked in the game. Required arguments: `entity` +* `'on_tick'`: executes every tick right before the entity is ticked in the game. Required arguments: `entity` * `'on_death'`: executes once when a living entity dies. Required arguments: `entity, reason` * `'on_removed'`: execute once when an entity is removed. Required arguments: `entity` * `'on_damaged'`: executed every time a living entity is about to receive damage. Required arguments: `entity, amount, source, attacking_entity` It doesn't mean that all entity types will have a chance to execute a given event, but entities will not error -when you will attach inapplicable event to it. +when you attach inapplicable event to it. ### `entity_event(e, event, call_name, args...)` -Attaches specific function from the current package to be called upon the `event`, with extra `args` curried to the -original required arguments for the event handler +Attaches specific function from the current package to be called upon the `event`, with extra `args` carried to the +original required arguments for the event handler.
 protect_villager(entity, amount, source, source_entity, healing_player) ->
@@ -3074,7 +3084,7 @@ apart you would want particles to appear, so `0.1` means one every 10cm.
 
 ### `particle_rect(name, pos, pos2, density?)`
 
-Renders a cuboid of particles between point `pos` to `pos2` with supplied density.
+Renders a cuboid of particles between points `pos` and `pos2` with supplied density.
 
 ## Markers
 
@@ -3082,7 +3092,7 @@ Renders a cuboid of particles between point `pos` to `pos2` with supplied densit
 
 Spawns a (permanent) marker entity with text or block at position. Returns that entity for further manipulations. 
 Unloading the app that spawned them will cause all the markers from the loaded portion of the world to be removed. 
-Also - if the game loads that marker in the future and the app is not loaded, it will be removed as well.
+Also, if the game loads that marker in the future and the app is not loaded, it will be removed as well.
 
 ### `remove_all_markers()`
 
@@ -3170,7 +3180,7 @@ Prints the message to system logs, and not to chat.
 Runs a vanilla command from the string result of the `expr` and returns its success count
 
 
-run('fill 1 1 1 10 10 10 air') -> 123 // 123 block were filled, this operation was successful 123 times out of a possible 1000 blocks volume
+run('fill 1 1 1 10 10 10 air') -> 123 // 123 block were filled, this operation was successful 123 times out of a possible 1000 block volume
 run('give @s stone 4') -> 1 // this operation was successful once
 
@@ -3182,7 +3192,7 @@ performance reasons and saves the world only on demand. ### `load_app_data(), load_app_data(file), load_app_data(file, shared?)` Loads the app data associated with the app from the world /scripts folder. Without argument returns the memory -managed and buffered / throttled NBT tag. With a file name - reads explicitly a file with that name from the +managed and buffered / throttled NBT tag. With a file name, reads explicitly a file with that name from the scripts folder that belongs exclusively to the app. if `shared` is true, the file location is not exclusive to the app anymore, but located in a shared app space. @@ -3281,10 +3291,10 @@ Queries in-game statistics for certain values. Categories include: For the options of `entry`, consult your statistics page, or give it a guess. -The call will return `null` if the statistics options are incorrect, or player didn't get these in their history. +The call will return `null` if the statistics options are incorrect, or player doesn't have them in their history. If the player encountered the statistic, or game created for him empty one, it will return a number. Scarpet will not affect the entries of the statistics, even if it is just creating empty ones. With `null` response -it could either mean your input is wrong, or statistic has effectively a value of `0`. +it could either mean your input is wrong, or statistic effectively has a value of `0`. # `/script run` command Primary way to input commands. The command executes in the context, position, and dimension of the executing player, From a4750f72386a1b2865d849dd164680dcdf856267 Mon Sep 17 00:00:00 2001 From: gnembon Date: Tue, 12 May 2020 23:28:34 -0300 Subject: [PATCH 124/198] fixed entity 'home' arguments --- .../script/argument/Vector3Argument.java | 47 +++++++++++++++++++ .../java/carpet/script/value/EntityValue.java | 23 ++------- 2 files changed, 52 insertions(+), 18 deletions(-) diff --git a/src/main/java/carpet/script/argument/Vector3Argument.java b/src/main/java/carpet/script/argument/Vector3Argument.java index 54dc21c6..66471aa8 100644 --- a/src/main/java/carpet/script/argument/Vector3Argument.java +++ b/src/main/java/carpet/script/argument/Vector3Argument.java @@ -90,4 +90,51 @@ public class Vector3Argument extends Argument throw new InternalExpressionException("Position argument should be defined either by three coordinates (a triple or by three arguments), or a positioned block value"); } } + + public static Vector3Argument findIn(List params, int offset, boolean optionalDirection) + { + try + { + Value v1 = params.get(0 + offset); + if (v1 instanceof BlockValue) + { + return (new Vector3Argument(new Vec3d(((BlockValue) v1).getPos()).add(0.5,0.5,0.5), 1+offset)).fromBlock(); + } + if (v1 instanceof ListValue) + { + List args = ((ListValue) v1).getItems(); + Vec3d pos = new Vec3d( + NumericValue.asNumber(args.get(0)).getDouble(), + NumericValue.asNumber(args.get(1)).getDouble(), + NumericValue.asNumber(args.get(2)).getDouble()); + double yaw = 0.0D; + double pitch = 0.0D; + if (args.size()>3 && optionalDirection) + { + yaw = NumericValue.asNumber(args.get(3)).getDouble(); + pitch = NumericValue.asNumber(args.get(4)).getDouble(); + } + return new Vector3Argument(pos,offset+1, yaw, pitch); + } + Vec3d pos = new Vec3d( + NumericValue.asNumber(v1).getDouble(), + NumericValue.asNumber(params.get(1 + offset)).getDouble(), + NumericValue.asNumber(params.get(2 + offset)).getDouble()); + double yaw = 0.0D; + double pitch = 0.0D; + int eatenLength = 3; + if (params.size()>3+offset && optionalDirection) + { + yaw = NumericValue.asNumber(params.get(3 + offset)).getDouble(); + pitch = NumericValue.asNumber(params.get(4 + offset)).getDouble(); + eatenLength = 5; + } + + return new Vector3Argument(pos,offset+eatenLength, yaw, pitch); + } + catch (IndexOutOfBoundsException e) + { + throw new InternalExpressionException("Position argument should be defined either by three coordinates (a triple or by three arguments), or a positioned block value"); + } + } } diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index 951c7173..d6948451 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -8,6 +8,7 @@ import carpet.helpers.Tracer; import carpet.patches.EntityPlayerMPFake; import carpet.script.CarpetContext; import carpet.script.EntityEventsGroup; +import carpet.script.argument.Vector3Argument; import carpet.script.exception.InternalExpressionException; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; @@ -789,26 +790,12 @@ public class EntityValue extends Value else if (v instanceof ListValue) { List lv = ((ListValue) v).getItems(); - if (lv.get(0) instanceof BlockValue) + Vector3Argument locator = Vector3Argument.findIn(lv, 0, false); + pos = new BlockPos(locator.vec.x, locator.vec.y, locator.vec.z); + if (lv.size() > locator.offset) { - pos = ((BlockValue) lv.get(0)).getPos(); - if (lv.size()>1) - { - distance = (int) NumericValue.asNumber(lv.get(1)).getLong(); - } + distance = (int) NumericValue.asNumber(lv.get(locator.offset)).getLong(); } - else if (lv.size()>=3) - { - pos = new BlockPos(NumericValue.asNumber(lv.get(0)).getLong(), - NumericValue.asNumber(lv.get(1)).getLong(), - NumericValue.asNumber(lv.get(2)).getLong()); - if (lv.size()>3) - { - distance = (int) NumericValue.asNumber(lv.get(4)).getLong(); - } - } - else throw new InternalExpressionException("'home' requires at least one position argument, and optional distance"); - } else throw new InternalExpressionException("'home' requires at least one position argument, and optional distance"); From 9afd1f3211de440a0e5368fd66636948a1f6018a Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 13 May 2020 10:33:43 -0300 Subject: [PATCH 125/198] validators to creative movement controls --- src/main/java/carpet/CarpetSettings.java | 13 +++++++---- .../mixins/LivingEntity_creativeFlyMixin.java | 4 ++-- src/main/java/carpet/settings/Validator.java | 22 +++++++++---------- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index fe099c00..d37f3f13 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -605,18 +605,23 @@ public class CarpetSettings "having it set on the decicated server has no effect", "but this also means it will work on vanilla servers as well" }, - category = {CREATIVE, CLIENT} + category = {CREATIVE, CLIENT}, + validate = Validator.NONNEGATIVE_NUMBER.class ) - public static double creativeFlySpeed = 1.0f; + public static double creativeFlySpeed = 1.0; @Rule( desc = "Creative air drag", extra = { + "Increased drag will slow down your flight", + "So need to adjust speed accordingly", + "With 1.0 drag, using speed of 11 seems to matching vanilla speeds.", "Purely client side setting, meaning that", "having it set on the decicated server has no effect", "but this also means it will work on vanilla servers as well" }, - category = {CREATIVE, CLIENT} + category = {CREATIVE, CLIENT}, + validate = Validator.PROBABILITY.class ) - public static double creativeFlyDrag = 0.91f; + public static double creativeFlyDrag = 0.09; } diff --git a/src/main/java/carpet/mixins/LivingEntity_creativeFlyMixin.java b/src/main/java/carpet/mixins/LivingEntity_creativeFlyMixin.java index 4d1410df..c50a364c 100644 --- a/src/main/java/carpet/mixins/LivingEntity_creativeFlyMixin.java +++ b/src/main/java/carpet/mixins/LivingEntity_creativeFlyMixin.java @@ -27,11 +27,11 @@ public abstract class LivingEntity_creativeFlyMixin extends Entity @ModifyConstant(method = "travel", constant = @Constant(floatValue = 0.91F), expect = 2) private float drag(float original) { - if (CarpetSettings.creativeFlyDrag != 0.91D && (Object)this instanceof PlayerEntity) + if (CarpetSettings.creativeFlyDrag != 0.09 && (Object)this instanceof PlayerEntity) { PlayerEntity self = (PlayerEntity)(Object)(this); if (self.abilities.flying && ! onGround ) - return (float)CarpetSettings.creativeFlyDrag; + return (float)(1.0-CarpetSettings.creativeFlyDrag); } return original; } diff --git a/src/main/java/carpet/settings/Validator.java b/src/main/java/carpet/settings/Validator.java index 56bf64a0..8b561ff6 100644 --- a/src/main/java/carpet/settings/Validator.java +++ b/src/main/java/carpet/settings/Validator.java @@ -17,17 +17,6 @@ public abstract class Validator public abstract T validate(ServerCommandSource source, ParsedRule currentRule, T newValue, String string); public String description() {return null;} - public static class POSITIVE_NUMBER extends Validator - { - @Override - public T validate(ServerCommandSource source, ParsedRule currentRule, T newValue, String string) - { - return newValue.doubleValue() > 0 ? newValue : null; - } - @Override - public String description() { return "Must be a positive number"; } - } - public static class _COMMAND extends Validator { @Override @@ -119,4 +108,15 @@ public abstract class Validator @Override public String description() { return "Must be a positive number";} } + + public static class PROBABILITY extends Validator + { + @Override + public T validate(ServerCommandSource source, ParsedRule currentRule, T newValue, String string) + { + return (newValue.doubleValue() >= 0 && newValue.doubleValue() <= 1 )? newValue : null; + } + @Override + public String description() { return "Must be between 0 and 1";} + } } From 743a57de90465e19f543fc3489f863f9eef4f410 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 13 May 2020 10:36:10 -0300 Subject: [PATCH 126/198] 1.3.23 --- gradle.properties | 2 +- src/main/java/carpet/CarpetSettings.java | 2 +- src/main/resources/fabric.mod.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 8864d07e..00547151 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ org.gradle.jvmargs=-Xmx1G loader_version=0.7.8+build.188 # Mod Properties - mod_version = 1.3.22+v200506 + mod_version = 1.3.23+v200513 maven_group = carpet archives_base_name = fabric-carpet diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index d37f3f13..2d83b9c3 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -33,7 +33,7 @@ import static carpet.settings.RuleCategory.CLIENT; @SuppressWarnings("CanBeFinal") public class CarpetSettings { - public static final String carpetVersion = "1.3.22+v200506"; + public static final String carpetVersion = "1.3.23+v200513"; public static final Logger LOG = LogManager.getLogger(); public static boolean skipGenerationChecks = false; public static boolean impendingFillSkipUpdates = false; diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 5c50b3d1..4ff9c1ff 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,7 +1,7 @@ { "schemaVersion": 1, "id": "carpet", - "version": "1.3.22", + "version": "1.3.23", "name": "Carpet Mod in Fabric", "description": "Carpet made out of fabric", From 2265d87db222e3778b30dbfde1c1706efea3d2d1 Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 14 May 2020 12:45:22 -0300 Subject: [PATCH 127/198] loader verbump --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 00547151..5a75063c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,8 +5,8 @@ org.gradle.jvmargs=-Xmx1G # check these on https://fabricmc.net/use # or better: https://modmuss50.me/fabric.html minecraft_version=1.15.2 - yarn_mappings=1.15.2+build.14 - loader_version=0.7.8+build.188 + yarn_mappings=1.15.2+build.15 + loader_version=0.8.3+build.196 # Mod Properties mod_version = 1.3.23+v200513 From 7447129d923094c32cc81fffc4f10d972ff86025 Mon Sep 17 00:00:00 2001 From: gnembon Date: Fri, 15 May 2020 01:43:11 -0300 Subject: [PATCH 128/198] added reload_chunk and added option for set_biome not to send chunk --- docs/scarpet/Full.md | 9 +++++++-- docs/scarpet/api/BlocksAndWorldAccess.md | 9 +++++++-- docs/scarpet/resources/editors/idea/2.txt | 1 + docs/scarpet/resources/editors/npp/scarpet.xml | 2 +- src/main/java/carpet/script/CarpetExpression.java | 15 +++++++++++++-- 5 files changed, 29 insertions(+), 7 deletions(-) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index dba29bf2..e73d99ad 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -1690,9 +1690,10 @@ If type is `null`, POI at position is removed. In any case, previous POI is also Interestingly, `unemployed`, and `nitwit` are not used in the game, meaning, they could be used as permanent spatial markers for scarpet apps. `meeting` is the only one with increased max occupancy of 32. -### `set_biome(pos, biome_name)` +### `set_biome(pos, biome_name, update=true)` -Changes the biome at that block position. +Changes the biome at that block position. if update is specified and false, then chunk will not be refreshed +on the clients. Biome changes can only be send to clients with the entire data from the chunk. ### `update(pos)` @@ -2249,6 +2250,10 @@ Feature list: * `twisting_vines` (1.16) * `basalt_pillar` (1.16) +### `reload_chunk(pos)` + +Sends full chunk data to clients. Useful when lots stuff happened and you want to refresh it on the clients. + ### `reset_chunk(pos)`, `reset_chunk(from_pos, to_pos)`, `reset_chunk(l(pos, ...))` Removes and resets the chunk, all chunks in the specified area or all chunks in a list at once, removing all previous blocks and entities, and replacing it with a new generation. For all currently loaded chunks, they will be brought diff --git a/docs/scarpet/api/BlocksAndWorldAccess.md b/docs/scarpet/api/BlocksAndWorldAccess.md index 9750cf1a..17f16470 100644 --- a/docs/scarpet/api/BlocksAndWorldAccess.md +++ b/docs/scarpet/api/BlocksAndWorldAccess.md @@ -134,9 +134,10 @@ If type is `null`, POI at position is removed. In any case, previous POI is also Interestingly, `unemployed`, and `nitwit` are not used in the game, meaning, they could be used as permanent spatial markers for scarpet apps. `meeting` is the only one with increased max occupancy of 32. -### `set_biome(pos, biome_name)` +### `set_biome(pos, biome_name, update=true)` -Changes the biome at that block position. +Changes the biome at that block position. if update is specified and false, then chunk will not be refreshed +on the clients. Biome changes can only be send to clients with the entire data from the chunk. ### `update(pos)` @@ -693,6 +694,10 @@ Feature list: * `twisting_vines` (1.16) * `basalt_pillar` (1.16) +### `reload_chunk(pos)` + +Sends full chunk data to clients. Useful when lots stuff happened and you want to refresh it on the clients. + ### `reset_chunk(pos)`, `reset_chunk(from_pos, to_pos)`, `reset_chunk(l(pos, ...))` Removes and resets the chunk, all chunks in the specified area or all chunks in a list at once, removing all previous blocks and entities, and replacing it with a new generation. For all currently loaded chunks, they will be brought diff --git a/docs/scarpet/resources/editors/idea/2.txt b/docs/scarpet/resources/editors/idea/2.txt index 15f9ee89..e62bf3e0 100644 --- a/docs/scarpet/resources/editors/idea/2.txt +++ b/docs/scarpet/resources/editors/idea/2.txt @@ -66,6 +66,7 @@ property query random_tick rect +reload_chunk remove_all_markers reset_chunk run diff --git a/docs/scarpet/resources/editors/npp/scarpet.xml b/docs/scarpet/resources/editors/npp/scarpet.xml index cfcde776..8491a743 100644 --- a/docs/scarpet/resources/editors/npp/scarpet.xml +++ b/docs/scarpet/resources/editors/npp/scarpet.xml @@ -55,7 +55,7 @@ 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 inhabited_time spawn_potential chunk_tickets - structure_eligibility structures structure_references set_structure reset_chunk + structure_eligibility structures structure_references set_structure reset_chunk reload_chunk scoreboard scoreboard_add scoreboard_remove scoreboard_display diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 22020af1..6a3dd8db 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -1126,12 +1126,23 @@ public class CarpetExpression Biome biome = Registry.BIOME.get(new Identifier(biomeName)); if (biome == null) throw new InternalExpressionException("Unknown biome: "+biomeName); + boolean doImmediateUpdate = true; + if (lv.size() > locator.offset+1) + { + doImmediateUpdate = lv.get(locator.offset+1).evalValue(c).getBoolean(); + } ServerWorld world = cc.s.getWorld(); BlockPos pos = locator.block.getPos(); Chunk chunk = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.BIOMES); ((BiomeArrayInterface)chunk.getBiomeArray()).setBiomeAtIndex(pos, world, biome); - this.forceChunkUpdate(pos, world); - return LazyValue.NULL; + if (doImmediateUpdate) this.forceChunkUpdate(pos, world); + return LazyValue.TRUE; + }); + + this.expr.addLazyFunction("reload_chunk", -1, (c, t, lv) -> { + CarpetContext cc = (CarpetContext)c; + this.forceChunkUpdate(BlockArgument.findIn(cc, lv, 0).block.getPos(), cc.s.getWorld()); + return LazyValue.TRUE; }); this.expr.addLazyFunction("structure_references", -1, (c, t, lv) -> { From 524cb62803b76a3898c41fe7ff86c5ec00471084 Mon Sep 17 00:00:00 2001 From: gnembon Date: Fri, 15 May 2020 02:01:07 -0300 Subject: [PATCH 129/198] fix --- src/main/java/carpet/script/CarpetExpression.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 6a3dd8db..370b5faf 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -344,7 +344,7 @@ public class CarpetExpression return pcount; } - private void forceChunkUpdate(BlockPos pos, ServerWorld world) + private static void forceChunkUpdate(BlockPos pos, ServerWorld world) { Chunk chunk = world.getChunk(pos); chunk.setShouldSave(true); @@ -1135,13 +1135,15 @@ public class CarpetExpression BlockPos pos = locator.block.getPos(); Chunk chunk = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.BIOMES); ((BiomeArrayInterface)chunk.getBiomeArray()).setBiomeAtIndex(pos, world, biome); - if (doImmediateUpdate) this.forceChunkUpdate(pos, world); + if (doImmediateUpdate) forceChunkUpdate(pos, world); return LazyValue.TRUE; }); this.expr.addLazyFunction("reload_chunk", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; - this.forceChunkUpdate(BlockArgument.findIn(cc, lv, 0).block.getPos(), cc.s.getWorld()); + BlockPos pos = BlockArgument.findIn(cc, lv, 0).block.getPos(); + ServerWorld world = cc.s.getWorld(); + cc.s.getMinecraftServer().submitAndJoin( () -> forceChunkUpdate(pos, world)); return LazyValue.TRUE; }); @@ -1361,7 +1363,7 @@ public class CarpetExpression { if (world.getChunk(chpos.x, chpos.z, ChunkStatus.FULL, false) != null) { - this.forceChunkUpdate(chpos.getCenterBlockPos(), world); + forceChunkUpdate(chpos.getCenterBlockPos(), world); } } result[0] = MapValue.wrap(report.entrySet().stream().collect(Collectors.toMap( @@ -2978,7 +2980,7 @@ public class CarpetExpression if (res == null) return; if (what.equalsIgnoreCase("boulder")) // there might be more of those - this.forceChunkUpdate(locator.block.getPos(), ((CarpetContext) c).s.getWorld()); + forceChunkUpdate(locator.block.getPos(), ((CarpetContext) c).s.getWorld()); result[0] = new NumericValue(res); }); Value ret = result[0]; // preventing from lazy evaluating of the result in case a future completes later From 1f5b06daa242c30f5b561b8e60f4cc3a08d0b9dd Mon Sep 17 00:00:00 2001 From: X-Green <35984104+X-Green@users.noreply.github.com> Date: Sat, 16 May 2020 01:58:50 +0800 Subject: [PATCH 130/198] Add Language Support For Carpet Settings (#267) * Added language supports for carpet settings use /set-carpet-language to set your language. * Added zh_cn.json - in progress Not accomplished yet, only translations for testing the language support. * Create model_for_new_language.jsons.txt * Rename model_for_new_language.jsons.txt to model_for_new_language.json * Update model_for_new_language.json * Update model_for_new_language.json * Update and rename model_for_new_language.json to en_us.json * Added setting CarpetLanguage * Delete SetLanguageCommand.java * Add files via upload * Update SettingsManager.java * Add files via upload * Update LanguageUtils.java * Update SettingsManager.java --- src/main/java/carpet/CarpetSettings.java | 8 ++ .../java/carpet/settings/SettingsManager.java | 63 +++++++---- src/main/java/carpet/utils/LanguageUtils.java | 106 ++++++++++++++++++ .../resources/assets/carpet/lang/en_us.json | 49 ++++++++ .../resources/assets/carpet/lang/zh_cn.json | 41 +++++++ 5 files changed, 243 insertions(+), 24 deletions(-) create mode 100644 src/main/java/carpet/utils/LanguageUtils.java create mode 100644 src/main/resources/assets/carpet/lang/en_us.json create mode 100644 src/main/resources/assets/carpet/lang/zh_cn.json diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index 2d83b9c3..e2b6b843 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -41,6 +41,14 @@ public class CarpetSettings public static Vec3d fixedPosition = null; public static int runPermissionLevel = 2; + @Rule( + desc = "sets the language of CarpetMod", + category = {CREATIVE, SURVIVAL}, + options = {"none"}, + strict = false + ) + public static String carpetLanguage = "none"; + @Rule( desc = "Nether portals correctly place entities going through", extra = "Entities shouldn't suffocate in obsidian", diff --git a/src/main/java/carpet/settings/SettingsManager.java b/src/main/java/carpet/settings/SettingsManager.java index 675df7b8..bb1fd66f 100644 --- a/src/main/java/carpet/settings/SettingsManager.java +++ b/src/main/java/carpet/settings/SettingsManager.java @@ -2,6 +2,7 @@ package carpet.settings; import carpet.CarpetServer; import carpet.CarpetSettings; +import carpet.utils.LanguageUtils; import carpet.utils.Messenger; import com.google.common.collect.ImmutableList; import com.google.common.collect.Sets; @@ -350,7 +351,7 @@ public class SettingsManager String ruleName = StringArgumentType.getString(ctx, "rule"); ParsedRule rule = getRule(ruleName); if (rule == null) - throw new SimpleCommandExceptionType(Messenger.c("rb Unknown rule: "+ruleName)).create(); + throw new SimpleCommandExceptionType(Messenger.c("rb "+ LanguageUtils.translateOrDefault("carpet.ui.statement.unknown_rule","Unknown rule")+": "+ruleName)).create(); return rule; } @@ -366,18 +367,22 @@ public class SettingsManager LiteralArgumentBuilder literalargumentbuilder = literal(identifier).requires((player) -> player.hasPermissionLevel(2) && !locked); - literalargumentbuilder.executes((context)->listAllSettings(context.getSource())). + literalargumentbuilder.executes((context)-> + { + LanguageUtils.setLanguage(CarpetSettings.carpetLanguage); + return listAllSettings(context.getSource()); + }). then(literal("list"). - executes( (c) -> listSettings(c.getSource(), "All "+fancyName+" Settings", + executes( (c) -> listSettings(c.getSource(), String.format(LanguageUtils.translateOrDefault("carpet.ui.statement.all_%s_settings","All %s Settings"), fancyName), getRules())). then(literal("defaults"). executes( (c)-> listSettings(c.getSource(), - "Current "+fancyName+" Startup Settings from "+identifier+".conf", + String.format(LanguageUtils.translateOrDefault("carpet.ui.statement.current_%s_startup_settings_from_%s","Current %s Startup Settings from %s"), fancyName, (identifier+".conf")), findStartupOverrides()))). then(argument("tag",StringArgumentType.word()). suggests( (c, b)->suggestMatching(getCategories(), b)). executes( (c) -> listSettings(c.getSource(), - String.format(fancyName+" Settings matching \"%s\"", StringArgumentType.getString(c, "tag")), + String.format(LanguageUtils.translateOrDefault("carpet.ui.statement.%s_settings_matching_'%s'","%s Settings matching \"%s\""), fancyName, LanguageUtils.translateOrDefault("carpet.ui.category." + StringArgumentType.getString(c, "tag"),StringArgumentType.getString(c, "tag"))), getRulesMatching(StringArgumentType.getString(c, "tag")))))). then(literal("removeDefault"). requires(s -> !locked). @@ -405,33 +410,36 @@ public class SettingsManager private int displayRuleMenu(ServerCommandSource source, ParsedRule rule) { PlayerEntity player; + String translatedPlusName = LanguageUtils.translatePlusDefault(LanguageUtils.getRuleNameKey(rule.name), rule.name); try { player = source.getPlayer(); } catch (CommandSyntaxException e) { - Messenger.m(source, "w "+rule.name +" is set to: ","wb "+rule.getAsString()); + Messenger.m(source, "w "+ translatedPlusName +" "+LanguageUtils.translateOrDefault( "carpet.ui.statement.is_set_to","is set to")+": ","wb "+rule.getAsString()); return 1; } Messenger.m(player, ""); - Messenger.m(player, "wb "+rule.name,"!/"+identifier+" "+rule.name,"^g refresh"); - Messenger.m(player, "w "+rule.description); + Messenger.m(player, "wb "+ translatedPlusName ,"!/"+identifier+" "+rule.name,"^g refresh"); + Messenger.m(player, "w "+ LanguageUtils.translateOrDefault(LanguageUtils.getRuleDescKey(rule.name), rule.description)); - rule.extraInfo.forEach(s -> Messenger.m(player, "g "+s)); + ImmutableList translatedExtraInfo = LanguageUtils.getRuleExtras(rule.name, rule.extraInfo); + translatedExtraInfo.forEach(s -> Messenger.m(player, "g "+s)); List tags = new ArrayList<>(); - tags.add(Messenger.c("w Tags: ")); + tags.add(Messenger.c("w "+LanguageUtils.translateOrDefault("carpet.ui.statement.tags", "Tags")+": ")); for (String t: rule.categories) { - tags.add(Messenger.c("c ["+t+"]", "^g list all "+t+" settings","!/"+identifier+" list "+t)); + String translated = LanguageUtils.translateOrDefault("carpet.ui.category." + t, t); + tags.add(Messenger.c("c ["+ translated +"]", "^g "+ String.format(LanguageUtils.translateOrDefault("list_all_%s_settings","list all %s settings"), translated),"!/"+identifier+" list "+t)); tags.add(Messenger.c("w , ")); } tags.remove(tags.size()-1); Messenger.m(player, tags.toArray(new Object[0])); - Messenger.m(player, "w Current value: ",String.format("%s %s (%s value)",rule.getBoolValue()?"lb":"nb", rule.getAsString(),rule.isDefault()?"default":"modified")); + Messenger.m(player, "w "+LanguageUtils.translateOrDefault("carpet.ui.statement.current_value", "Current value")+": ",String.format("%s %s (%s value)",rule.getBoolValue()?"lb":"nb", rule.getAsString(),rule.isDefault()?"default":"modified")); List options = new ArrayList<>(); options.add(Messenger.c("w Options: ", "y [ ")); for (String o: rule.options) @@ -449,8 +457,8 @@ public class SettingsManager private int setRule(ServerCommandSource source, ParsedRule rule, String newValue) { if (rule.set(source, newValue) != null) - Messenger.m(source, "w "+rule.toString()+", ", "c [change permanently?]", - "^w Click to keep the settings in "+identifier+".conf to save across restarts", + Messenger.m(source, "w "+rule.toString()+", ", "c ["+LanguageUtils.translateOrDefault("carpet.ui.statement.change_permanently","change permanently")+"?]", + "^w "+String.format(LanguageUtils.translateOrDefault("carpet.ui.statement.click_to_keep_the_settings_in_%s_to_save_across_restarts","Click to keep the settings in %s to save across restarts"), identifier+".conf"), "?/"+identifier+" setDefault "+rule.name+" "+rule.getAsString()); return 1; } @@ -465,7 +473,7 @@ public class SettingsManager writeSettingsToConf(conf.getLeft()); // this may feels weird, but if conf // is locked, it will never reach this point. rule.set(source,stringValue); - Messenger.m(source ,"gi rule "+ rule.name+" will now default to "+ stringValue); + Messenger.m(source ,"gi "+String.format(LanguageUtils.translateOrDefault("carpet.ui.statement.rule_%s_will_now_default_to_%s","rule %s will now default to %s"), LanguageUtils.translateOrDefault(LanguageUtils.getRuleNameKey(rule.name), rule.name), stringValue)); return 1; } // removes overrides of the default values in the file @@ -482,10 +490,11 @@ public class SettingsManager private BaseText displayInteractiveSetting(ParsedRule rule) { + String translatedPlusName = LanguageUtils.translatePlusDefault(LanguageUtils.getRuleNameKey(rule.name), rule.name); List args = new ArrayList<>(); - args.add("w - "+rule.name+" "); + args.add("w - "+ translatedPlusName +" "); args.add("!/"+identifier+" "+rule.name); - args.add("^y "+rule.description); + args.add("^y "+LanguageUtils.translateOrDefault(LanguageUtils.getRuleDescKey(rule.name), rule.description)); for (String option: rule.options) { args.add(makeSetRuleButton(rule, option, true)); @@ -511,10 +520,10 @@ public class SettingsManager } String baseText = style + (brackets ? " [" : " ") + option + (brackets ? "]" : ""); if (locked) - return Messenger.c(baseText, "^g "+fancyName+" settings are locked"); + return Messenger.c(baseText, "^g "+fancyName+" " + LanguageUtils.translateOrDefault("carpet.ui.statement.settings_are_locked","settings are locked")); if (option.equalsIgnoreCase(rule.getAsString())) return Messenger.c(baseText); - return Messenger.c(baseText, "^g Switch to " + option+(option.equalsIgnoreCase(rule.defaultAsString)?" (default)":""), "?/"+identifier+" " + rule.name + " " + option); + return Messenger.c(baseText, "^g "+ LanguageUtils.translateOrDefault("carpet.ui.statement.switch_to","Switch to") +" " + option+(option.equalsIgnoreCase(rule.defaultAsString)?" (default)":""), "?/"+identifier+" " + rule.name + " " + option); } private int listSettings(ServerCommandSource source, String title, Collection> settings_list) @@ -535,19 +544,25 @@ public class SettingsManager } private int listAllSettings(ServerCommandSource source) { - listSettings(source, "Current "+fancyName+" Settings", getNonDefault()); + //listSettings(source, "Current "+fancyName+" Settings", getNonDefault()); + listSettings(source, String.format(LanguageUtils.translateOrDefault("carpet.ui.statement.current_%s_settings","Current %s Settings"), fancyName), getNonDefault()); if (version != null) - Messenger.m(source, "g "+fancyName+" version: "+ version); + //Messenger.m(source, "g "+fancyName+" version: "+ version); + Messenger.m(source, "g "+fancyName+" "+ LanguageUtils.translateOrDefault("carpet.ui.statement.version", "version") + ": "+ version); try { PlayerEntity player = source.getPlayer(); List tags = new ArrayList<>(); - tags.add("w Browse Categories:\n"); + //tags.add("w Browse Categories:\n"); + tags.add("w " + LanguageUtils.translateOrDefault("carpet.ui.statement.browse_categories", "Browse Categories") + ":\n"); for (String t : getCategories()) { - tags.add("c [" + t+"]"); - tags.add("^g list all " + t + " settings"); + String translated = LanguageUtils.translateOrDefault("carpet.ui.category." + t, t); + String translatedPlus = LanguageUtils.translatePlusDefault("carpet.ui.category." + t, t); + tags.add("c [" + translated +"]"); + //tags.add("^g list all " + translated + " settings"); + tags.add("^g " + String.format(LanguageUtils.translateOrDefault("carpet.ui.statement.list_all_%s_settings","list all %s settings"), translatedPlus)); tags.add("!/"+identifier+" list " + t); tags.add("w "); } diff --git a/src/main/java/carpet/utils/LanguageUtils.java b/src/main/java/carpet/utils/LanguageUtils.java new file mode 100644 index 00000000..65e3015b --- /dev/null +++ b/src/main/java/carpet/utils/LanguageUtils.java @@ -0,0 +1,106 @@ +package carpet.utils; + +import com.google.common.collect.ImmutableList; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; +import org.apache.commons.io.IOUtils; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +public class LanguageUtils +{ + private static Map translationMap; + + public static String currentLanguage; + + public static String translate(String translationKey) + { + if (translationMap == null) + { + return translationKey; + } + return translationMap.getOrDefault(translationKey, translationKey); + } + + public static String translateOrDefault(String translationKey, String defaultValue) + { + if (translationMap == null) + { + return defaultValue; + } + return translationMap.getOrDefault(translationKey, defaultValue); + } + + public static String translatePlusDefault(String translationKey, String defaultValue){ + return translationMap.containsKey(translationKey) ? translateOrDefault(translationKey, defaultValue) + String.format(" (%s)", defaultValue): defaultValue; + } + + public static String getRuleNameKey(String rule) + { + return String.format("carpet.rule.%s.name", rule); + } + + public static String getRuleDescKey(String rule) + { + return String.format("carpet.rule.%s.desc", rule); + } + + public static ImmutableList getRuleExtras(String rule, ImmutableList defaultList) + { + if (translationMap == null) return defaultList; + String keyBase = String.format("carpet.rule.%s.extra.", rule); + List extras = new ArrayList<>(); + int i = 0; + do { + String keyExtra = keyBase + i; + String value = translationMap.get(keyExtra); + System.out.println(keyExtra); + System.out.println(value); + if (value != null && !value.equals("")) + { + extras.add(value); + } + i++; + } + while (translationMap.containsKey(keyBase + (i - 1))); + return (extras.isEmpty()) ? defaultList : ImmutableList.copyOf(extras); + } + + public static void setLanguage(String language) + { + if (language.equals("none")) + { + currentLanguage = language; + translationMap = null; + return; + } + + String langJs; + try{ + langJs = IOUtils.toString( + Objects.requireNonNull(LanguageUtils.class.getClassLoader().getResourceAsStream(String.format("assets/carpet/lang/%s.json", language))), + StandardCharsets.UTF_8); + } catch (NullPointerException | IOException e) { + return; + } + Gson gson = new GsonBuilder().enableComplexMapKeySerialization().create(); + Type type = new TypeToken>() {}.getType(); + Map map1 = gson.fromJson(langJs, type); + currentLanguage = language; + translationMap = map1; + } + + public static void loadConfiguration() + { + + } + + +} diff --git a/src/main/resources/assets/carpet/lang/en_us.json b/src/main/resources/assets/carpet/lang/en_us.json new file mode 100644 index 00000000..ad516a4a --- /dev/null +++ b/src/main/resources/assets/carpet/lang/en_us.json @@ -0,0 +1,49 @@ +// This file isn't necessary at all, because the language module would use the strings coded in the source if language "none" is selected. +// So en_us is the default language and probably no change will be made after loading this file. +// But it could be a good example for writing the language file for other languages. + +{ + "carpet.rule.portalSuffocationFix.name": "", + "// the key is genetated as:" : "String.format('carpet.rule.%s.name', rule.name)", + + + "carpet.rule.portalSuffocationFix.desc": "", + "// the key is genetated as:" : "String.format('carpet.rule.%s.desc', rule.name)", + + + "carpet.rule.portalSuffocationFix.extra.0": "", + "carpet.rule.portalSuffocationFix.extra.1": "", + "// the key is genetated as:" : "String.format('carpet.rule.%s.extra.%i', rule.name, index)", + + + "carpet.ui.category.bugfix": "bugfix", + "carpet.ui.category.survival": "survival", + "carpet.ui.category.creative": "creative", + "carpet.ui.category.experimental": "experimental", + "carpet.ui.category.optimization": "optimization", + "carpet.ui.category.feature": "feature", + "carpet.ui.category.command": "command", + "carpet.ui.category.tnt": "TNT", + "carpet.ui.category.dispenser": "dispenser", + "carpet.ui.category.scarpet": "scarpet", + "carpet.ui.category.client": "client", + + + "carpet.ui.statement.browse_categories": "Brouse categories", + "carpet.ui.statement.list_all_%s_settings": "list all %s settings", + "carpet.ui.statement.version": "Version", + "carpet.ui.statement.current_%s_settings": "Current %s settings", + "carpet.ui.statement.switch_to": "Switch to", + "carpet.ui.statement.settings_are_locked": "settings are locked", + "carpet.ui.statement.is_set_to": "is set to", + "carpet.ui.statement.unknown_rule": "Unknown ruls", + "carpet.ui.statement.current_%s_startup_settings_from_%s": "current %s startup settings from %s", + "carpet.ui.statement.%s_settings_matching_'%s'": "%s settings matching \"%s\" ", + "carpet.ui.statement.all_%s_settings": "all %s settings", + "carpet.ui.statement.tags": "Tags", + "carpet.ui.statement.change_permanently": "Change permanently", + "carpet.ui.statement.click_to_keep_the_settings_in_%s_to_save_across_restarts": "click to keep the settings in %s to save across restarts", + "carpet.ui.statement.rule_%s_will_now_default_to_%s": "rule %s will now default to %s", + "carpet.ui.statement.current_value": "current value" + +} diff --git a/src/main/resources/assets/carpet/lang/zh_cn.json b/src/main/resources/assets/carpet/lang/zh_cn.json new file mode 100644 index 00000000..0ff8835f --- /dev/null +++ b/src/main/resources/assets/carpet/lang/zh_cn.json @@ -0,0 +1,41 @@ +{ + "carpet.rule.portalSuffocationFix.name": "传送门窒息修复", + + + "carpet.rule.portalSuffocationFix.desc": "使下界传送门正确地传送实体", + + + "carpet.rule.portalSuffocationFix.extra.0": "0000000", + "carpet.rule.portalSuffocationFix.extra.1": "1111111", + + + "carpet.ui.category.bugfix": "BUG修复", + "carpet.ui.category.survival": "生存", + "carpet.ui.category.creative": "创造", + "carpet.ui.category.experimental": "试验性", + "carpet.ui.category.optimization": "优化", + "carpet.ui.category.feature": "特性", + "carpet.ui.category.command": "指令", + "carpet.ui.category.tnt": "TNT", + "carpet.ui.category.dispenser": "发射器", + "carpet.ui.category.scarpet": "SCarpet脚本语言", + "carpet.ui.category.client": "客户端", + + "carpet.ui.statement.browse_categories": "浏览分类", + "carpet.ui.statement.list_all_%s_settings": "列出所有 %s 选项", + "carpet.ui.statement.version": "版本", + "carpet.ui.statement.current_%s_settings": "目前启用的 %s 选项", + "carpet.ui.statement.switch_to": "切换至", + "carpet.ui.statement.settings_are_locked": "选项被锁定", + "carpet.ui.statement.is_set_to": "被设置为", + "carpet.ui.statement.unknown_rule": "未知的规则选项", + "carpet.ui.statement.current_%s_startup_settings_from_%s": "目前启用的%s选项,从%s中读取得", + "carpet.ui.statement.%s_settings_matching_'%s'": "%s中符合\"%s\"的选项:", + "carpet.ui.statement.all_%s_settings": "所有的%s选项", + "carpet.ui.statement.tags": "分类", + "carpet.ui.statement.change_permanently": "永久更改", + "carpet.ui.statement.click_to_keep_the_settings_in_%s_to_save_across_restarts": "点击此按钮以使此选项保存于%s,重启后依旧生效", + "carpet.ui.statement.rule_%s_will_now_default_to_%s": "规则%s将会被默认设置为%s", + "carpet.ui.statement.current_value": "当前的值" + +} \ No newline at end of file From 1e39f6caa82b2b82aa9ce8273b93685ed01d3803 Mon Sep 17 00:00:00 2001 From: gnembon Date: Fri, 15 May 2020 17:26:36 -0300 Subject: [PATCH 131/198] updates to translations --- src/main/java/carpet/CarpetSettings.java | 28 ++++- src/main/java/carpet/settings/ParsedRule.java | 31 +++++ .../java/carpet/settings/SettingsManager.java | 64 +++++------ src/main/java/carpet/utils/LanguageUtils.java | 106 ------------------ src/main/java/carpet/utils/Translations.java | 68 +++++++++++ 5 files changed, 152 insertions(+), 145 deletions(-) delete mode 100644 src/main/java/carpet/utils/LanguageUtils.java create mode 100644 src/main/java/carpet/utils/Translations.java diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index e2b6b843..938e11c0 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -4,6 +4,7 @@ import carpet.settings.ParsedRule; import carpet.settings.Rule; import carpet.settings.SettingsManager; import carpet.settings.Validator; +import carpet.utils.Translations; import carpet.utils.Messenger; import carpet.utils.SpawnChunks; import net.minecraft.server.MinecraftServer; @@ -41,13 +42,30 @@ public class CarpetSettings public static Vec3d fixedPosition = null; public static int runPermissionLevel = 2; + private static class LanguageValidator extends Validator { + @Override public String validate(ServerCommandSource source, ParsedRule currentRule, String newValue, String string) { + if (currentRule.get().equals(newValue)) + { + return newValue; + } + if (!Translations.isValidLanguage(newValue)) + { + Messenger.m(source, "r "+newValue+" is not a valid language"); + return null; + } + CarpetSettings.language = newValue; + Translations.updateLanguage(source); + return newValue; + } + } @Rule( - desc = "sets the language of CarpetMod", - category = {CREATIVE, SURVIVAL}, - options = {"none"}, - strict = false + desc = "sets the language for carpet", + category = FEATURE, + options = {"none", "zh_cn"}, + strict = false, + validate = LanguageValidator.class ) - public static String carpetLanguage = "none"; + public static String language = "none"; @Rule( desc = "Nether portals correctly place entities going through", diff --git a/src/main/java/carpet/settings/ParsedRule.java b/src/main/java/carpet/settings/ParsedRule.java index e75bb3f6..652ae454 100644 --- a/src/main/java/carpet/settings/ParsedRule.java +++ b/src/main/java/carpet/settings/ParsedRule.java @@ -1,6 +1,7 @@ package carpet.settings; import carpet.CarpetServer; +import carpet.utils.Translations; import carpet.utils.Messenger; import com.google.common.collect.ImmutableList; import net.minecraft.server.command.ServerCommandSource; @@ -12,6 +13,8 @@ import java.util.Arrays; import java.util.List; import java.util.Locale; +import static carpet.utils.Translations.tr; + public final class ParsedRule implements Comparable { public final Field field; public final String name; @@ -225,4 +228,32 @@ public final class ParsedRule implements Comparable { { return this.name + ": " + getAsString(); } + + private String translationKey() + { + return String.format("carpet.rule.%s.name", name); + } + + public String translatedName(){ + String key = translationKey(); + return Translations.hasTranslation(key) ? tr(key) + String.format(" (%s)", name): name; + } + + public String translatedDescription() + { + return tr(String.format("carpet.rule.%s.desc", (name)), description); + } + + public List translatedExtras() + { + if (!Translations.hasTranslations()) return extraInfo; + String keyBase = String.format("carpet.rule.%s.extra.", name); + List extras = new ArrayList<>(); + int i = 0; + while (Translations.hasTranslation(keyBase+i)) + { + extras.add(Translations.tr(keyBase+i)); + } + return (extras.isEmpty()) ? extraInfo : extras; + } } diff --git a/src/main/java/carpet/settings/SettingsManager.java b/src/main/java/carpet/settings/SettingsManager.java index bb1fd66f..cb5eede2 100644 --- a/src/main/java/carpet/settings/SettingsManager.java +++ b/src/main/java/carpet/settings/SettingsManager.java @@ -2,7 +2,7 @@ package carpet.settings; import carpet.CarpetServer; import carpet.CarpetSettings; -import carpet.utils.LanguageUtils; +import carpet.utils.Translations; import carpet.utils.Messenger; import com.google.common.collect.ImmutableList; import com.google.common.collect.Sets; @@ -40,6 +40,7 @@ import java.util.Set; import java.util.TreeMap; import java.util.stream.Collectors; +import static carpet.utils.Translations.tr; import static net.minecraft.server.command.CommandManager.argument; import static net.minecraft.server.command.CommandManager.literal; import static net.minecraft.server.command.CommandSource.suggestMatching; @@ -351,7 +352,7 @@ public class SettingsManager String ruleName = StringArgumentType.getString(ctx, "rule"); ParsedRule rule = getRule(ruleName); if (rule == null) - throw new SimpleCommandExceptionType(Messenger.c("rb "+ LanguageUtils.translateOrDefault("carpet.ui.statement.unknown_rule","Unknown rule")+": "+ruleName)).create(); + throw new SimpleCommandExceptionType(Messenger.c("rb "+ tr("carpet.ui.statement.unknown_rule","Unknown rule")+": "+ruleName)).create(); return rule; } @@ -367,22 +368,18 @@ public class SettingsManager LiteralArgumentBuilder literalargumentbuilder = literal(identifier).requires((player) -> player.hasPermissionLevel(2) && !locked); - literalargumentbuilder.executes((context)-> - { - LanguageUtils.setLanguage(CarpetSettings.carpetLanguage); - return listAllSettings(context.getSource()); - }). + literalargumentbuilder.executes((context)-> listAllSettings(context.getSource())). then(literal("list"). - executes( (c) -> listSettings(c.getSource(), String.format(LanguageUtils.translateOrDefault("carpet.ui.statement.all_%s_settings","All %s Settings"), fancyName), + executes( (c) -> listSettings(c.getSource(), String.format(tr("carpet.ui.statement.all_%s_settings","All %s Settings"), fancyName), getRules())). then(literal("defaults"). executes( (c)-> listSettings(c.getSource(), - String.format(LanguageUtils.translateOrDefault("carpet.ui.statement.current_%s_startup_settings_from_%s","Current %s Startup Settings from %s"), fancyName, (identifier+".conf")), + String.format(tr("carpet.ui.statement.current_%s_startup_settings_from_%s","Current %s Startup Settings from %s"), fancyName, (identifier+".conf")), findStartupOverrides()))). then(argument("tag",StringArgumentType.word()). suggests( (c, b)->suggestMatching(getCategories(), b)). executes( (c) -> listSettings(c.getSource(), - String.format(LanguageUtils.translateOrDefault("carpet.ui.statement.%s_settings_matching_'%s'","%s Settings matching \"%s\""), fancyName, LanguageUtils.translateOrDefault("carpet.ui.category." + StringArgumentType.getString(c, "tag"),StringArgumentType.getString(c, "tag"))), + String.format(tr("carpet.ui.statement.%s_settings_matching_'%s'","%s Settings matching \"%s\""), fancyName, tr("carpet.ui.category." + StringArgumentType.getString(c, "tag"),StringArgumentType.getString(c, "tag"))), getRulesMatching(StringArgumentType.getString(c, "tag")))))). then(literal("removeDefault"). requires(s -> !locked). @@ -410,36 +407,35 @@ public class SettingsManager private int displayRuleMenu(ServerCommandSource source, ParsedRule rule) { PlayerEntity player; - String translatedPlusName = LanguageUtils.translatePlusDefault(LanguageUtils.getRuleNameKey(rule.name), rule.name); + String displayName = rule.translatedName(); try { player = source.getPlayer(); } catch (CommandSyntaxException e) { - Messenger.m(source, "w "+ translatedPlusName +" "+LanguageUtils.translateOrDefault( "carpet.ui.statement.is_set_to","is set to")+": ","wb "+rule.getAsString()); + Messenger.m(source, "w "+ displayName +" "+ tr( "carpet.ui.statement.is_set_to","is set to")+": ","wb "+rule.getAsString()); return 1; } Messenger.m(player, ""); - Messenger.m(player, "wb "+ translatedPlusName ,"!/"+identifier+" "+rule.name,"^g refresh"); - Messenger.m(player, "w "+ LanguageUtils.translateOrDefault(LanguageUtils.getRuleDescKey(rule.name), rule.description)); + Messenger.m(player, "wb "+ displayName ,"!/"+identifier+" "+rule.name,"^g refresh"); + Messenger.m(player, "w "+ rule.translatedDescription()); - ImmutableList translatedExtraInfo = LanguageUtils.getRuleExtras(rule.name, rule.extraInfo); - translatedExtraInfo.forEach(s -> Messenger.m(player, "g "+s)); + rule.translatedExtras().forEach(s -> Messenger.m(player, "g "+s)); List tags = new ArrayList<>(); - tags.add(Messenger.c("w "+LanguageUtils.translateOrDefault("carpet.ui.statement.tags", "Tags")+": ")); + tags.add(Messenger.c("w "+ tr("carpet.ui.statement.tags", "Tags")+": ")); for (String t: rule.categories) { - String translated = LanguageUtils.translateOrDefault("carpet.ui.category." + t, t); - tags.add(Messenger.c("c ["+ translated +"]", "^g "+ String.format(LanguageUtils.translateOrDefault("list_all_%s_settings","list all %s settings"), translated),"!/"+identifier+" list "+t)); + String translated = tr("carpet.ui.category." + t, t); + tags.add(Messenger.c("c ["+ translated +"]", "^g "+ String.format(tr("list_all_%s_settings","list all %s settings"), translated),"!/"+identifier+" list "+t)); tags.add(Messenger.c("w , ")); } tags.remove(tags.size()-1); Messenger.m(player, tags.toArray(new Object[0])); - Messenger.m(player, "w "+LanguageUtils.translateOrDefault("carpet.ui.statement.current_value", "Current value")+": ",String.format("%s %s (%s value)",rule.getBoolValue()?"lb":"nb", rule.getAsString(),rule.isDefault()?"default":"modified")); + Messenger.m(player, "w "+ tr("carpet.ui.statement.current_value", "Current value")+": ",String.format("%s %s (%s value)",rule.getBoolValue()?"lb":"nb", rule.getAsString(),rule.isDefault()?"default":"modified")); List options = new ArrayList<>(); options.add(Messenger.c("w Options: ", "y [ ")); for (String o: rule.options) @@ -457,8 +453,8 @@ public class SettingsManager private int setRule(ServerCommandSource source, ParsedRule rule, String newValue) { if (rule.set(source, newValue) != null) - Messenger.m(source, "w "+rule.toString()+", ", "c ["+LanguageUtils.translateOrDefault("carpet.ui.statement.change_permanently","change permanently")+"?]", - "^w "+String.format(LanguageUtils.translateOrDefault("carpet.ui.statement.click_to_keep_the_settings_in_%s_to_save_across_restarts","Click to keep the settings in %s to save across restarts"), identifier+".conf"), + Messenger.m(source, "w "+rule.toString()+", ", "c ["+ tr("carpet.ui.statement.change_permanently","change permanently")+"?]", + "^w "+String.format(tr("carpet.ui.statement.click_to_keep_the_settings_in_%s_to_save_across_restarts","Click to keep the settings in %s to save across restarts"), identifier+".conf"), "?/"+identifier+" setDefault "+rule.name+" "+rule.getAsString()); return 1; } @@ -473,7 +469,7 @@ public class SettingsManager writeSettingsToConf(conf.getLeft()); // this may feels weird, but if conf // is locked, it will never reach this point. rule.set(source,stringValue); - Messenger.m(source ,"gi "+String.format(LanguageUtils.translateOrDefault("carpet.ui.statement.rule_%s_will_now_default_to_%s","rule %s will now default to %s"), LanguageUtils.translateOrDefault(LanguageUtils.getRuleNameKey(rule.name), rule.name), stringValue)); + Messenger.m(source ,"gi "+String.format(tr("carpet.ui.statement.rule_%s_will_now_default_to_%s","rule %s will now default to %s"), rule.translatedName(), stringValue)); return 1; } // removes overrides of the default values in the file @@ -490,11 +486,11 @@ public class SettingsManager private BaseText displayInteractiveSetting(ParsedRule rule) { - String translatedPlusName = LanguageUtils.translatePlusDefault(LanguageUtils.getRuleNameKey(rule.name), rule.name); + String displayName = rule.translatedName(); List args = new ArrayList<>(); - args.add("w - "+ translatedPlusName +" "); + args.add("w - "+ displayName +" "); args.add("!/"+identifier+" "+rule.name); - args.add("^y "+LanguageUtils.translateOrDefault(LanguageUtils.getRuleDescKey(rule.name), rule.description)); + args.add("^y "+rule.translatedDescription()); for (String option: rule.options) { args.add(makeSetRuleButton(rule, option, true)); @@ -520,10 +516,10 @@ public class SettingsManager } String baseText = style + (brackets ? " [" : " ") + option + (brackets ? "]" : ""); if (locked) - return Messenger.c(baseText, "^g "+fancyName+" " + LanguageUtils.translateOrDefault("carpet.ui.statement.settings_are_locked","settings are locked")); + return Messenger.c(baseText, "^g "+fancyName+" " + tr("carpet.ui.statement.settings_are_locked","settings are locked")); if (option.equalsIgnoreCase(rule.getAsString())) return Messenger.c(baseText); - return Messenger.c(baseText, "^g "+ LanguageUtils.translateOrDefault("carpet.ui.statement.switch_to","Switch to") +" " + option+(option.equalsIgnoreCase(rule.defaultAsString)?" (default)":""), "?/"+identifier+" " + rule.name + " " + option); + return Messenger.c(baseText, "^g "+ tr("carpet.ui.statement.switch_to","Switch to") +" " + option+(option.equalsIgnoreCase(rule.defaultAsString)?" (default)":""), "?/"+identifier+" " + rule.name + " " + option); } private int listSettings(ServerCommandSource source, String title, Collection> settings_list) @@ -545,24 +541,24 @@ public class SettingsManager private int listAllSettings(ServerCommandSource source) { //listSettings(source, "Current "+fancyName+" Settings", getNonDefault()); - listSettings(source, String.format(LanguageUtils.translateOrDefault("carpet.ui.statement.current_%s_settings","Current %s Settings"), fancyName), getNonDefault()); + listSettings(source, String.format(tr("carpet.ui.statement.current_%s_settings","Current %s Settings"), fancyName), getNonDefault()); if (version != null) //Messenger.m(source, "g "+fancyName+" version: "+ version); - Messenger.m(source, "g "+fancyName+" "+ LanguageUtils.translateOrDefault("carpet.ui.statement.version", "version") + ": "+ version); + Messenger.m(source, "g "+fancyName+" "+ tr("carpet.ui.statement.version", "version") + ": "+ version); try { PlayerEntity player = source.getPlayer(); List tags = new ArrayList<>(); //tags.add("w Browse Categories:\n"); - tags.add("w " + LanguageUtils.translateOrDefault("carpet.ui.statement.browse_categories", "Browse Categories") + ":\n"); + tags.add("w " + tr("carpet.ui.statement.browse_categories", "Browse Categories") + ":\n"); for (String t : getCategories()) { - String translated = LanguageUtils.translateOrDefault("carpet.ui.category." + t, t); - String translatedPlus = LanguageUtils.translatePlusDefault("carpet.ui.category." + t, t); + String translated = tr("carpet.ui.category." + t, t); + String translatedPlus = Translations.hasTranslation("carpet.ui.category." + t) ? tr("carpet.ui.category." + t, t) + String.format(" (%s)", t) : t; tags.add("c [" + translated +"]"); //tags.add("^g list all " + translated + " settings"); - tags.add("^g " + String.format(LanguageUtils.translateOrDefault("carpet.ui.statement.list_all_%s_settings","list all %s settings"), translatedPlus)); + tags.add("^g " + String.format(tr("carpet.ui.statement.list_all_%s_settings","list all %s settings"), translatedPlus)); tags.add("!/"+identifier+" list " + t); tags.add("w "); } diff --git a/src/main/java/carpet/utils/LanguageUtils.java b/src/main/java/carpet/utils/LanguageUtils.java deleted file mode 100644 index 65e3015b..00000000 --- a/src/main/java/carpet/utils/LanguageUtils.java +++ /dev/null @@ -1,106 +0,0 @@ -package carpet.utils; - -import com.google.common.collect.ImmutableList; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.reflect.TypeToken; -import org.apache.commons.io.IOUtils; - -import java.io.IOException; -import java.lang.reflect.Type; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -public class LanguageUtils -{ - private static Map translationMap; - - public static String currentLanguage; - - public static String translate(String translationKey) - { - if (translationMap == null) - { - return translationKey; - } - return translationMap.getOrDefault(translationKey, translationKey); - } - - public static String translateOrDefault(String translationKey, String defaultValue) - { - if (translationMap == null) - { - return defaultValue; - } - return translationMap.getOrDefault(translationKey, defaultValue); - } - - public static String translatePlusDefault(String translationKey, String defaultValue){ - return translationMap.containsKey(translationKey) ? translateOrDefault(translationKey, defaultValue) + String.format(" (%s)", defaultValue): defaultValue; - } - - public static String getRuleNameKey(String rule) - { - return String.format("carpet.rule.%s.name", rule); - } - - public static String getRuleDescKey(String rule) - { - return String.format("carpet.rule.%s.desc", rule); - } - - public static ImmutableList getRuleExtras(String rule, ImmutableList defaultList) - { - if (translationMap == null) return defaultList; - String keyBase = String.format("carpet.rule.%s.extra.", rule); - List extras = new ArrayList<>(); - int i = 0; - do { - String keyExtra = keyBase + i; - String value = translationMap.get(keyExtra); - System.out.println(keyExtra); - System.out.println(value); - if (value != null && !value.equals("")) - { - extras.add(value); - } - i++; - } - while (translationMap.containsKey(keyBase + (i - 1))); - return (extras.isEmpty()) ? defaultList : ImmutableList.copyOf(extras); - } - - public static void setLanguage(String language) - { - if (language.equals("none")) - { - currentLanguage = language; - translationMap = null; - return; - } - - String langJs; - try{ - langJs = IOUtils.toString( - Objects.requireNonNull(LanguageUtils.class.getClassLoader().getResourceAsStream(String.format("assets/carpet/lang/%s.json", language))), - StandardCharsets.UTF_8); - } catch (NullPointerException | IOException e) { - return; - } - Gson gson = new GsonBuilder().enableComplexMapKeySerialization().create(); - Type type = new TypeToken>() {}.getType(); - Map map1 = gson.fromJson(langJs, type); - currentLanguage = language; - translationMap = map1; - } - - public static void loadConfiguration() - { - - } - - -} diff --git a/src/main/java/carpet/utils/Translations.java b/src/main/java/carpet/utils/Translations.java new file mode 100644 index 00000000..e8ffd8a6 --- /dev/null +++ b/src/main/java/carpet/utils/Translations.java @@ -0,0 +1,68 @@ +package carpet.utils; + +import carpet.CarpetSettings; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; +import net.minecraft.server.command.ServerCommandSource; +import org.apache.commons.io.IOUtils; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.Objects; + +public class Translations +{ + private static Map translationMap; + + public static String tr(String key) + { + return translationMap == null ? key : translationMap.getOrDefault(key, key); + } + + public static String tr(String key, String str) + { + return translationMap == null ? str : translationMap.getOrDefault(key, str); + } + + public static boolean hasTranslations() + { + return translationMap != null; + } + + public static boolean hasTranslation(String key) + { + return translationMap != null && translationMap.containsKey(key); + } + + public static void updateLanguage(ServerCommandSource source) + { + if (CarpetSettings.language.equalsIgnoreCase("none")) + { + translationMap = null; + return; + } + String langJs; + try + { + langJs = IOUtils.toString( + Objects.requireNonNull(Translations.class.getClassLoader().getResourceAsStream(String.format("assets/carpet/lang/%s.json", CarpetSettings.language))), + StandardCharsets.UTF_8); + } catch (NullPointerException | IOException e) { + Messenger.m(source, "r Failed to update language"); + return; + } + Gson gson = new GsonBuilder().enableComplexMapKeySerialization().create(); + Type type = new TypeToken>() {}.getType(); + translationMap = gson.fromJson(langJs, type); + } + + + public static boolean isValidLanguage(String newValue) + { + // will put some validations for availble languages at some point + return true; + } +} From 74c62e5a13aa7d2f5505be7d8212501d9659ab03 Mon Sep 17 00:00:00 2001 From: gnembon Date: Fri, 15 May 2020 20:00:27 -0300 Subject: [PATCH 132/198] simplified translations keys --- src/main/java/carpet/settings/ParsedRule.java | 6 +- .../java/carpet/settings/SettingsManager.java | 39 ++++----- src/main/java/carpet/utils/Translations.java | 1 + .../resources/assets/carpet/lang/en_us.json | 72 +++++++++-------- .../resources/assets/carpet/lang/zh_cn.json | 80 +++++++++---------- 5 files changed, 102 insertions(+), 96 deletions(-) diff --git a/src/main/java/carpet/settings/ParsedRule.java b/src/main/java/carpet/settings/ParsedRule.java index 652ae454..e2acdd25 100644 --- a/src/main/java/carpet/settings/ParsedRule.java +++ b/src/main/java/carpet/settings/ParsedRule.java @@ -231,7 +231,7 @@ public final class ParsedRule implements Comparable { private String translationKey() { - return String.format("carpet.rule.%s.name", name); + return String.format("rule.%s.name", name); } public String translatedName(){ @@ -241,13 +241,13 @@ public final class ParsedRule implements Comparable { public String translatedDescription() { - return tr(String.format("carpet.rule.%s.desc", (name)), description); + return tr(String.format("rule.%s.desc", (name)), description); } public List translatedExtras() { if (!Translations.hasTranslations()) return extraInfo; - String keyBase = String.format("carpet.rule.%s.extra.", name); + String keyBase = String.format("rule.%s.extra.", name); List extras = new ArrayList<>(); int i = 0; while (Translations.hasTranslation(keyBase+i)) diff --git a/src/main/java/carpet/settings/SettingsManager.java b/src/main/java/carpet/settings/SettingsManager.java index cb5eede2..3b27d3c2 100644 --- a/src/main/java/carpet/settings/SettingsManager.java +++ b/src/main/java/carpet/settings/SettingsManager.java @@ -352,7 +352,7 @@ public class SettingsManager String ruleName = StringArgumentType.getString(ctx, "rule"); ParsedRule rule = getRule(ruleName); if (rule == null) - throw new SimpleCommandExceptionType(Messenger.c("rb "+ tr("carpet.ui.statement.unknown_rule","Unknown rule")+": "+ruleName)).create(); + throw new SimpleCommandExceptionType(Messenger.c("rb "+ tr("ui.unknown_rule","Unknown rule")+": "+ruleName)).create(); return rule; } @@ -370,16 +370,16 @@ public class SettingsManager literalargumentbuilder.executes((context)-> listAllSettings(context.getSource())). then(literal("list"). - executes( (c) -> listSettings(c.getSource(), String.format(tr("carpet.ui.statement.all_%s_settings","All %s Settings"), fancyName), + executes( (c) -> listSettings(c.getSource(), String.format(tr("ui.all_%(mod)s_settings","All %s Settings"), fancyName), getRules())). then(literal("defaults"). executes( (c)-> listSettings(c.getSource(), - String.format(tr("carpet.ui.statement.current_%s_startup_settings_from_%s","Current %s Startup Settings from %s"), fancyName, (identifier+".conf")), + String.format(tr("ui.current_%(mod)s_startup_settings_from_%(conf)s","Current %s Startup Settings from %s"), fancyName, (identifier+".conf")), findStartupOverrides()))). then(argument("tag",StringArgumentType.word()). suggests( (c, b)->suggestMatching(getCategories(), b)). executes( (c) -> listSettings(c.getSource(), - String.format(tr("carpet.ui.statement.%s_settings_matching_'%s'","%s Settings matching \"%s\""), fancyName, tr("carpet.ui.category." + StringArgumentType.getString(c, "tag"),StringArgumentType.getString(c, "tag"))), + String.format(tr("ui.%(mod)s_settings_matching_'%(query)s'","%s Settings matching \"%s\""), fancyName, tr("category." + StringArgumentType.getString(c, "tag"),StringArgumentType.getString(c, "tag"))), getRulesMatching(StringArgumentType.getString(c, "tag")))))). then(literal("removeDefault"). requires(s -> !locked). @@ -414,7 +414,7 @@ public class SettingsManager } catch (CommandSyntaxException e) { - Messenger.m(source, "w "+ displayName +" "+ tr( "carpet.ui.statement.is_set_to","is set to")+": ","wb "+rule.getAsString()); + Messenger.m(source, "w "+ displayName +" "+ tr( "ui.is_set_to","is set to")+": ","wb "+rule.getAsString()); return 1; } @@ -425,17 +425,17 @@ public class SettingsManager rule.translatedExtras().forEach(s -> Messenger.m(player, "g "+s)); List tags = new ArrayList<>(); - tags.add(Messenger.c("w "+ tr("carpet.ui.statement.tags", "Tags")+": ")); + tags.add(Messenger.c("w "+ tr("ui.tags", "Tags")+": ")); for (String t: rule.categories) { - String translated = tr("carpet.ui.category." + t, t); + String translated = tr("category." + t, t); tags.add(Messenger.c("c ["+ translated +"]", "^g "+ String.format(tr("list_all_%s_settings","list all %s settings"), translated),"!/"+identifier+" list "+t)); tags.add(Messenger.c("w , ")); } tags.remove(tags.size()-1); Messenger.m(player, tags.toArray(new Object[0])); - Messenger.m(player, "w "+ tr("carpet.ui.statement.current_value", "Current value")+": ",String.format("%s %s (%s value)",rule.getBoolValue()?"lb":"nb", rule.getAsString(),rule.isDefault()?"default":"modified")); + Messenger.m(player, "w "+ tr("ui.current_value", "Current value")+": ",String.format("%s %s (%s value)",rule.getBoolValue()?"lb":"nb", rule.getAsString(),rule.isDefault()?"default":"modified")); List options = new ArrayList<>(); options.add(Messenger.c("w Options: ", "y [ ")); for (String o: rule.options) @@ -453,8 +453,8 @@ public class SettingsManager private int setRule(ServerCommandSource source, ParsedRule rule, String newValue) { if (rule.set(source, newValue) != null) - Messenger.m(source, "w "+rule.toString()+", ", "c ["+ tr("carpet.ui.statement.change_permanently","change permanently")+"?]", - "^w "+String.format(tr("carpet.ui.statement.click_to_keep_the_settings_in_%s_to_save_across_restarts","Click to keep the settings in %s to save across restarts"), identifier+".conf"), + Messenger.m(source, "w "+rule.toString()+", ", "c ["+ tr("ui.change_permanently","change permanently")+"?]", + "^w "+String.format(tr("ui.click_to_keep_the_settings_in_%(conf)s_to_save_across_restarts","Click to keep the settings in %s to save across restarts"), identifier+".conf"), "?/"+identifier+" setDefault "+rule.name+" "+rule.getAsString()); return 1; } @@ -469,7 +469,7 @@ public class SettingsManager writeSettingsToConf(conf.getLeft()); // this may feels weird, but if conf // is locked, it will never reach this point. rule.set(source,stringValue); - Messenger.m(source ,"gi "+String.format(tr("carpet.ui.statement.rule_%s_will_now_default_to_%s","rule %s will now default to %s"), rule.translatedName(), stringValue)); + Messenger.m(source ,"gi "+String.format(tr("ui.rule_%(rule)s_will_now_default_to_%(value)s","rule %s will now default to %s"), rule.translatedName(), stringValue)); return 1; } // removes overrides of the default values in the file @@ -516,10 +516,10 @@ public class SettingsManager } String baseText = style + (brackets ? " [" : " ") + option + (brackets ? "]" : ""); if (locked) - return Messenger.c(baseText, "^g "+fancyName+" " + tr("carpet.ui.statement.settings_are_locked","settings are locked")); + return Messenger.c(baseText, "^g "+fancyName+" " + tr("ui.settings_are_locked","settings are locked")); if (option.equalsIgnoreCase(rule.getAsString())) return Messenger.c(baseText); - return Messenger.c(baseText, "^g "+ tr("carpet.ui.statement.switch_to","Switch to") +" " + option+(option.equalsIgnoreCase(rule.defaultAsString)?" (default)":""), "?/"+identifier+" " + rule.name + " " + option); + return Messenger.c(baseText, "^g "+ tr("ui.switch_to","Switch to") +" " + option+(option.equalsIgnoreCase(rule.defaultAsString)?" (default)":""), "?/"+identifier+" " + rule.name + " " + option); } private int listSettings(ServerCommandSource source, String title, Collection> settings_list) @@ -541,24 +541,25 @@ public class SettingsManager private int listAllSettings(ServerCommandSource source) { //listSettings(source, "Current "+fancyName+" Settings", getNonDefault()); - listSettings(source, String.format(tr("carpet.ui.statement.current_%s_settings","Current %s Settings"), fancyName), getNonDefault()); + listSettings(source, String.format(tr("ui.current_%(mod)s_settings","Current %s Settings"), fancyName), getNonDefault()); if (version != null) //Messenger.m(source, "g "+fancyName+" version: "+ version); - Messenger.m(source, "g "+fancyName+" "+ tr("carpet.ui.statement.version", "version") + ": "+ version); + Messenger.m(source, "g "+fancyName+" "+ tr("ui.version", "version") + ": "+ version); try { PlayerEntity player = source.getPlayer(); List tags = new ArrayList<>(); //tags.add("w Browse Categories:\n"); - tags.add("w " + tr("carpet.ui.statement.browse_categories", "Browse Categories") + ":\n"); + tags.add("w " + tr("ui.browse_categories", "Browse Categories") + ":\n"); for (String t : getCategories()) { - String translated = tr("carpet.ui.category." + t, t); - String translatedPlus = Translations.hasTranslation("carpet.ui.category." + t) ? tr("carpet.ui.category." + t, t) + String.format(" (%s)", t) : t; + String catKey = "category." + t; + String translated = tr(catKey, t); + String translatedPlus = Translations.hasTranslation(catKey) ? String.format("%s (%s)",tr(catKey, t), t) : t; tags.add("c [" + translated +"]"); //tags.add("^g list all " + translated + " settings"); - tags.add("^g " + String.format(tr("carpet.ui.statement.list_all_%s_settings","list all %s settings"), translatedPlus)); + tags.add("^g " + String.format(tr("ui.list_all_%(cat)s_settings","list all %s settings"), translatedPlus)); tags.add("!/"+identifier+" list " + t); tags.add("w "); } diff --git a/src/main/java/carpet/utils/Translations.java b/src/main/java/carpet/utils/Translations.java index e8ffd8a6..081d656b 100644 --- a/src/main/java/carpet/utils/Translations.java +++ b/src/main/java/carpet/utils/Translations.java @@ -57,6 +57,7 @@ public class Translations Gson gson = new GsonBuilder().enableComplexMapKeySerialization().create(); Type type = new TypeToken>() {}.getType(); translationMap = gson.fromJson(langJs, type); + translationMap.entrySet().removeIf(e -> e.getKey().startsWith("//")); } diff --git a/src/main/resources/assets/carpet/lang/en_us.json b/src/main/resources/assets/carpet/lang/en_us.json index ad516a4a..34331d5c 100644 --- a/src/main/resources/assets/carpet/lang/en_us.json +++ b/src/main/resources/assets/carpet/lang/en_us.json @@ -3,47 +3,51 @@ // But it could be a good example for writing the language file for other languages. { - "carpet.rule.portalSuffocationFix.name": "", - "// the key is genetated as:" : "String.format('carpet.rule.%s.name', rule.name)", + "// Rules:": "", + "rule.portalSuffocationFix.name": "", + "// the key is genetated as:" : "String.format('rule.%s.name', rule.name)", - "carpet.rule.portalSuffocationFix.desc": "", - "// the key is genetated as:" : "String.format('carpet.rule.%s.desc', rule.name)", + "rule.portalSuffocationFix.desc": "", + "// the key is genetated as:" : "String.format('rule.%s.desc', rule.name)", - "carpet.rule.portalSuffocationFix.extra.0": "", - "carpet.rule.portalSuffocationFix.extra.1": "", - "// the key is genetated as:" : "String.format('carpet.rule.%s.extra.%i', rule.name, index)", + "rule.portalSuffocationFix.extra.0": "", + "rule.portalSuffocationFix.extra.1": "", + "// the key is genetated as:" : "String.format('rule.%s.extra.%i', rule.name, index)", - "carpet.ui.category.bugfix": "bugfix", - "carpet.ui.category.survival": "survival", - "carpet.ui.category.creative": "creative", - "carpet.ui.category.experimental": "experimental", - "carpet.ui.category.optimization": "optimization", - "carpet.ui.category.feature": "feature", - "carpet.ui.category.command": "command", - "carpet.ui.category.tnt": "TNT", - "carpet.ui.category.dispenser": "dispenser", - "carpet.ui.category.scarpet": "scarpet", - "carpet.ui.category.client": "client", + "// Categories:": "", + "category.bugfix": "bugfix", + "category.survival": "survival", + "category.creative": "creative", + "category.experimental": "experimental", + "category.optimization": "optimization", + "category.feature": "feature", + "category.command": "command", + "category.tnt": "TNT", + "category.dispenser": "dispenser", + "category.scarpet": "scarpet", + "category.client": "client", - "carpet.ui.statement.browse_categories": "Brouse categories", - "carpet.ui.statement.list_all_%s_settings": "list all %s settings", - "carpet.ui.statement.version": "Version", - "carpet.ui.statement.current_%s_settings": "Current %s settings", - "carpet.ui.statement.switch_to": "Switch to", - "carpet.ui.statement.settings_are_locked": "settings are locked", - "carpet.ui.statement.is_set_to": "is set to", - "carpet.ui.statement.unknown_rule": "Unknown ruls", - "carpet.ui.statement.current_%s_startup_settings_from_%s": "current %s startup settings from %s", - "carpet.ui.statement.%s_settings_matching_'%s'": "%s settings matching \"%s\" ", - "carpet.ui.statement.all_%s_settings": "all %s settings", - "carpet.ui.statement.tags": "Tags", - "carpet.ui.statement.change_permanently": "Change permanently", - "carpet.ui.statement.click_to_keep_the_settings_in_%s_to_save_across_restarts": "click to keep the settings in %s to save across restarts", - "carpet.ui.statement.rule_%s_will_now_default_to_%s": "rule %s will now default to %s", - "carpet.ui.statement.current_value": "current value" + "// Settings command UI elements": "", + + "ui.browse_categories": "Browse categories", + "ui.list_all_%(cat)s_settings": "list all %s settings", + "ui.version": "Version", + "ui.current_%(mod)s_settings": "Current %s settings", + "ui.switch_to": "Switch to", + "ui.settings_are_locked": "settings are locked", + "ui.is_set_to": "is set to", + "ui.unknown_rule": "Unknown rule", + "ui.current_%(mod)s_startup_settings_from_%(conf)s": "Current %s Startup Settings from %s", + "ui.%(mod)s_settings_matching_'%(query)s'": "%s settings matching \"%s\" ", + "ui.all_%(mod)s_settings": "All %s settings", + "ui.tags": "Tags", + "ui.change_permanently": "Change permanently", + "ui.click_to_keep_the_settings_in_%(conf)s_to_save_across_restarts": "click to keep the settings in %s to save across restarts", + "ui.rule_%(rule)s_will_now_default_to_%(value)s": "rule %s will now default to %s", + "ui.current_value": "current value" } diff --git a/src/main/resources/assets/carpet/lang/zh_cn.json b/src/main/resources/assets/carpet/lang/zh_cn.json index 0ff8835f..9784f087 100644 --- a/src/main/resources/assets/carpet/lang/zh_cn.json +++ b/src/main/resources/assets/carpet/lang/zh_cn.json @@ -1,41 +1,41 @@ -{ - "carpet.rule.portalSuffocationFix.name": "传送门窒息修复", - - - "carpet.rule.portalSuffocationFix.desc": "使下界传送门正确地传送实体", - - - "carpet.rule.portalSuffocationFix.extra.0": "0000000", - "carpet.rule.portalSuffocationFix.extra.1": "1111111", - - - "carpet.ui.category.bugfix": "BUG修复", - "carpet.ui.category.survival": "生存", - "carpet.ui.category.creative": "创造", - "carpet.ui.category.experimental": "试验性", - "carpet.ui.category.optimization": "优化", - "carpet.ui.category.feature": "特性", - "carpet.ui.category.command": "指令", - "carpet.ui.category.tnt": "TNT", - "carpet.ui.category.dispenser": "发射器", - "carpet.ui.category.scarpet": "SCarpet脚本语言", - "carpet.ui.category.client": "客户端", - - "carpet.ui.statement.browse_categories": "浏览分类", - "carpet.ui.statement.list_all_%s_settings": "列出所有 %s 选项", - "carpet.ui.statement.version": "版本", - "carpet.ui.statement.current_%s_settings": "目前启用的 %s 选项", - "carpet.ui.statement.switch_to": "切换至", - "carpet.ui.statement.settings_are_locked": "选项被锁定", - "carpet.ui.statement.is_set_to": "被设置为", - "carpet.ui.statement.unknown_rule": "未知的规则选项", - "carpet.ui.statement.current_%s_startup_settings_from_%s": "目前启用的%s选项,从%s中读取得", - "carpet.ui.statement.%s_settings_matching_'%s'": "%s中符合\"%s\"的选项:", - "carpet.ui.statement.all_%s_settings": "所有的%s选项", - "carpet.ui.statement.tags": "分类", - "carpet.ui.statement.change_permanently": "永久更改", - "carpet.ui.statement.click_to_keep_the_settings_in_%s_to_save_across_restarts": "点击此按钮以使此选项保存于%s,重启后依旧生效", - "carpet.ui.statement.rule_%s_will_now_default_to_%s": "规则%s将会被默认设置为%s", - "carpet.ui.statement.current_value": "当前的值" - +{ + "rule.portalSuffocationFix.name": "传送门窒息修复", + + + "rule.portalSuffocationFix.desc": "使下界传送门正确地传送实体", + + + "rule.portalSuffocationFix.extra.0": "0000000", + "rule.portalSuffocationFix.extra.1": "1111111", + + + "category.bugfix": "BUG修复", + "category.survival": "生存", + "category.creative": "创造", + "category.experimental": "试验性", + "category.optimization": "优化", + "category.feature": "特性", + "category.command": "指令", + "category.tnt": "TNT", + "category.dispenser": "发射器", + "category.scarpet": "scarpet脚本语言", + "category.client": "客户端", + + "ui.browse_categories": "浏览分类", + "ui.list_all_%(cat)s_settings": "列出所有 %s 选项", + "ui.version": "版本", + "ui.current_%(mod)s_settings": "目前启用的 %s 选项", + "ui.switch_to": "切换至", + "ui.settings_are_locked": "选项被锁定", + "ui.is_set_to": "被设置为", + "ui.unknown_rule": "未知的规则选项", + "ui.current_%(mod)s_startup_settings_from_%(conf)s": "目前启用的%s选项,从%s中读取得", + "ui.%(mod)s_settings_matching_'%(query)s'": "%s中符合\"%s\"的选项:", + "ui.all_%(mod)s_settings": "所有的%s选项", + "ui.tags": "分类", + "ui.change_permanently": "永久更改", + "ui.click_to_keep_the_settings_in_%(conf)s_to_save_across_restarts": "点击此按钮以使此选项保存于%s,重启后依旧生效", + "ui.rule_%(rule)s_will_now_default_to_%(value)s": "规则%s将会被默认设置为%s", + "ui.current_value": "当前的值" + } \ No newline at end of file From 06ede1fbc02c2427d7120ebbec23916f1cdd853e Mon Sep 17 00:00:00 2001 From: gnembon Date: Sun, 17 May 2020 23:52:59 -0300 Subject: [PATCH 133/198] added add_chunk_ticket --- docs/scarpet/api/BlocksAndWorldAccess.md | 7 +++++ docs/scarpet/resources/editors/idea/2.txt | 1 + .../scarpet/resources/editors/npp/scarpet.xml | 1 + .../java/carpet/script/CarpetExpression.java | 29 +++++++++++++++++++ 4 files changed, 38 insertions(+) diff --git a/docs/scarpet/api/BlocksAndWorldAccess.md b/docs/scarpet/api/BlocksAndWorldAccess.md index 17f16470..522faff2 100644 --- a/docs/scarpet/api/BlocksAndWorldAccess.md +++ b/docs/scarpet/api/BlocksAndWorldAccess.md @@ -712,3 +712,10 @@ It returns a `map` with a report indicating how many chunks were affected, and h * `layer_count_`: number of chunks for which a `` generation step has been performed * `layer_time_`: cumulative time for all chunks spent on generating `` step +### add_chunk_ticket(pos, type, radius) + +Adds a chunk ticket at a position, which makes the game to keep the designated area centered around +`pos` with radius of `radius` loaded for a predefined amount of ticks, defined by `type`. Allowed types +are `portal`: 300 ticks, `teleport`: 5 ticks, and `unknown`: 1 tick. Radius can be from 1 to 32 ticks. + +This function is tentative - will likely change when chunk ticket API is properly fleshed out. \ No newline at end of file diff --git a/docs/scarpet/resources/editors/idea/2.txt b/docs/scarpet/resources/editors/idea/2.txt index e62bf3e0..81803965 100644 --- a/docs/scarpet/resources/editors/idea/2.txt +++ b/docs/scarpet/resources/editors/idea/2.txt @@ -1,4 +1,5 @@ air +add_chunk_ticket biome blast_resistance block diff --git a/docs/scarpet/resources/editors/npp/scarpet.xml b/docs/scarpet/resources/editors/npp/scarpet.xml index 8491a743..da7e1bf4 100644 --- a/docs/scarpet/resources/editors/npp/scarpet.xml +++ b/docs/scarpet/resources/editors/npp/scarpet.xml @@ -56,6 +56,7 @@ blocks_movement block_sound material map_colour property block_properties block_data poi set_poi place_item set_biome biome loaded_status generation_status inhabited_time spawn_potential chunk_tickets structure_eligibility structures structure_references set_structure reset_chunk reload_chunk + add_chunk_ticket scoreboard scoreboard_add scoreboard_remove scoreboard_display diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 370b5faf..2e155927 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -88,6 +88,7 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ChunkTicket; +import net.minecraft.server.world.ChunkTicketType; import net.minecraft.server.world.ServerWorld; import net.minecraft.sound.BlockSoundGroup; import net.minecraft.sound.SoundCategory; @@ -1383,7 +1384,35 @@ public class CarpetExpression return (_c, _t) -> ret; }); + this.expr.addLazyFunction("add_chunk_ticket", -1, (c, t, lv) -> + { + CarpetContext cc = (CarpetContext)c; + BlockArgument locator = BlockArgument.findIn(cc, lv, 0); + BlockPos pos = locator.block.getPos(); + if (lv.size() != locator.offset+2) throw new InternalExpressionException("'add_chunk_ticket' requires block position, ticket type and radius"); + String type = lv.get(locator.offset).evalValue(c).getString(); + ChunkTicketType ticket = ticketTypes.get(type.toLowerCase(Locale.ROOT)); + if (ticket == null) throw new InternalExpressionException("Unknown ticket type: "+type); + int radius = NumericValue.asNumber(lv.get(locator.offset+1).evalValue(c)).getInt(); + if (radius < 1 || radius > 32) throw new InternalExpressionException("Ticket radius should be between 1 and 32 chunks"); + // due to types we will wing it: + ChunkPos target = new ChunkPos(pos); + if (ticket == ChunkTicketType.PORTAL) + cc.s.getWorld().getChunkManager().addTicket(ChunkTicketType.PORTAL, target, radius, pos); + else if (ticket == ChunkTicketType.POST_TELEPORT) + cc.s.getWorld().getChunkManager().addTicket(ChunkTicketType.POST_TELEPORT, target, radius, 1); + else + cc.s.getWorld().getChunkManager().addTicket(ChunkTicketType.UNKNOWN, target, radius, target); + Value ret = new NumericValue(ticket.getExpiryTicks()); + return (_c, _t) -> ret; + }); + } + private Map> ticketTypes = new HashMap>(){{ + put("portal", ChunkTicketType.PORTAL); + put("teleport", ChunkTicketType.POST_TELEPORT); + put("unknown", ChunkTicketType.UNKNOWN); + }}; private static String getScoreboardKeyFromValue(Value keyValue) { From a272725928af716713bf0106c747d170e5605b49 Mon Sep 17 00:00:00 2001 From: Ghoulboy Date: Mon, 18 May 2020 22:24:19 +0200 Subject: [PATCH 134/198] Cylinders n cuboids (#284) Co-authored-by: Ghoulboy78 <53367549+Ghoulboy-78@users.noreply.github.com> --- .../java/carpet/commands/DrawCommand.java | 65 ++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/src/main/java/carpet/commands/DrawCommand.java b/src/main/java/carpet/commands/DrawCommand.java index ed53dfb5..f52e16d7 100644 --- a/src/main/java/carpet/commands/DrawCommand.java +++ b/src/main/java/carpet/commands/DrawCommand.java @@ -64,7 +64,19 @@ public class DrawCommand then(argument("height",IntegerArgumentType.integer(1)). then(argument("pointing",StringArgumentType.word()).suggests( (c, b) -> suggestMatching(new String[]{"up","down"},b)). then(argument("orientation",StringArgumentType.word()).suggests( (c, b) -> suggestMatching(new String[]{"y","x","z"},b)) - .then(drawShape(c -> DrawCommand.drawPyramid(c, "circle", true))))))))); + .then(drawShape(c -> DrawCommand.drawPyramid(c, "circle", true))))))))). + then(literal("cylinder"). + then(argument("center", BlockPosArgumentType.blockPos()). + then(argument("radius", IntegerArgumentType.integer(1)). + then(argument("height",IntegerArgumentType.integer(1)). + then(argument("orientation",StringArgumentType.word()).suggests( (c, b) -> suggestMatching(new String[]{"y","x","z"},b)) + .then(drawShape(c -> DrawCommand.drawPrism(c, "circle")))))))). + then(literal("cuboid"). + then(argument("center", BlockPosArgumentType.blockPos()). + then(argument("radius", IntegerArgumentType.integer(1)). + then(argument("height",IntegerArgumentType.integer(1)). + then(argument("orientation",StringArgumentType.word()).suggests( (c, b) -> suggestMatching(new String[]{"y","x","z"},b)) + .then(drawShape(c -> DrawCommand.drawPrism(c, "square")))))))); dispatcher.register(command); } @@ -389,4 +401,55 @@ public class DrawCommand return affected; } + + private static int drawPrism(CommandContext ctx, String base){ + BlockPos pos; + double radius; + int height; + String orientation; + BlockStateArgument block; + Predicate replacement; + try + { + pos = getArg(ctx, BlockPosArgumentType::getBlockPos, "center"); + radius = getArg(ctx, IntegerArgumentType::getInteger, "radius")+0.5D; + height = getArg(ctx, IntegerArgumentType::getInteger, "height"); + orientation = getArg(ctx, StringArgumentType::getString,"orientation"); + block = getArg(ctx, BlockStateArgumentType::getBlockState, "block"); + replacement = getArg(ctx, BlockPredicateArgumentType::getBlockPredicate, "filter", true); + } + catch (ErrorHandled | CommandSyntaxException ignored) { return 0; } + + ServerCommandSource source = ctx.getSource(); + + int affected = 0; + BlockPos.Mutable mbpos = new BlockPos.Mutable(pos); + + List list = Lists.newArrayList(); + + ServerWorld world = source.getWorld(); + + CarpetSettings.impendingFillSkipUpdates = !CarpetSettings.fillUpdates; + + boolean isSquare = base.equalsIgnoreCase("square"); + + for(int i =0; i Date: Mon, 18 May 2020 22:14:07 -0300 Subject: [PATCH 135/198] added add_chunk_ticket --- docs/scarpet/Full.md | 16 +++++++-- docs/scarpet/api/Events.md | 8 ++++- docs/scarpet/resources/editors/idea/4.txt | 1 + .../scarpet/resources/editors/npp/scarpet.xml | 1 + .../ServerPlayerEntity_scarpetEventMixin.java | 33 +++++++++++++++++++ .../java/carpet/script/CarpetEventServer.java | 22 +++++++++++++ .../assets/carpet/scripts/event_test.sc | 10 ++++++ 7 files changed, 88 insertions(+), 3 deletions(-) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index e73d99ad..9882a423 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -2268,7 +2268,13 @@ It returns a `map` with a report indicating how many chunks were affected, and h * `layer_count_`: number of chunks for which a `` generation step has been performed * `layer_time_`: cumulative time for all chunks spent on generating `` step -# Iterating over larger areas of blocks +### add_chunk_ticket(pos, type, radius) + +Adds a chunk ticket at a position, which makes the game to keep the designated area centered around +`pos` with radius of `radius` loaded for a predefined amount of ticks, defined by `type`. Allowed types +are `portal`: 300 ticks, `teleport`: 5 ticks, and `unknown`: 1 tick. Radius can be from 1 to 32 ticks. + +This function is tentative - will likely change when chunk ticket API is properly fleshed out.# Iterating over larger areas of blocks These functions help scan larger areas of blocks without using generic loop functions, like nested `loop`. @@ -2993,7 +2999,7 @@ __on_tick() // can access blocks and entities in the overworld __on_tick_nether() // can access blocks and entities in the nether __on_tick_ender() // can access blocks and entities in the end __on_chunk_generated(x,z) // called after a chunk is promoted to the full chunk, - // prodiving lowest x and z coords in the chunk + // providing lowest x and z coords in the chunk // event will not work with optifine installed in the game __on_lightning(block, mode) // mode is `true` if lightning caused horse trap to spawn // player specific callbacks @@ -3011,6 +3017,7 @@ __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_changes_dimension(player, from_pos, from_dimension, to_pos, to_dimension) __on_player_rides(player, forward, strafe, jumping, sneaking) __on_player_jumps(player) __on_player_deploys_elytra(player) @@ -3024,6 +3031,11 @@ __on_player_drops_stack(player) __on_statistic(player, category, event, value) // player statistic changes +Couple special cases. +* `__on_player_changes_dimension` returns `null` as `to_pos` when player goes back to the overworld from the end +, since the respawn location of the player is not control by the teleport, or a player can see the end credits. After + the player is eligible to respawn in the overworld, `__on_player_respawns` will be triggered. + ### `/script event` command used to display current events and bounded functions. use `add_to` ro register new event, or `remove_from` to diff --git a/docs/scarpet/api/Events.md b/docs/scarpet/api/Events.md index 6408ac94..39992450 100644 --- a/docs/scarpet/api/Events.md +++ b/docs/scarpet/api/Events.md @@ -19,7 +19,7 @@ __on_tick() // can access blocks and entities in the overworld __on_tick_nether() // can access blocks and entities in the nether __on_tick_ender() // can access blocks and entities in the end __on_chunk_generated(x,z) // called after a chunk is promoted to the full chunk, - // prodiving lowest x and z coords in the chunk + // providing lowest x and z coords in the chunk // event will not work with optifine installed in the game __on_lightning(block, mode) // mode is `true` if lightning caused horse trap to spawn // player specific callbacks @@ -37,6 +37,7 @@ __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_changes_dimension(player, from_pos, from_dimension, to_pos, to_dimension) __on_player_rides(player, forward, strafe, jumping, sneaking) __on_player_jumps(player) __on_player_deploys_elytra(player) @@ -50,6 +51,11 @@ __on_player_drops_stack(player) __on_statistic(player, category, event, value) // player statistic changes +Couple special cases. +* `__on_player_changes_dimension` returns `null` as `to_pos` when player goes back to the overworld from the end +, since the respawn location of the player is not control by the teleport, or a player can see the end credits. After + the player is eligible to respawn in the overworld, `__on_player_respawns` will be triggered. + ### `/script event` command used to display current events and bounded functions. use `add_to` ro register new event, or `remove_from` to diff --git a/docs/scarpet/resources/editors/idea/4.txt b/docs/scarpet/resources/editors/idea/4.txt index 6200e26c..4799c846 100644 --- a/docs/scarpet/resources/editors/idea/4.txt +++ b/docs/scarpet/resources/editors/idea/4.txt @@ -5,6 +5,7 @@ __on_close __on_player_attacks_entity __on_player_breaks_block __on_player_clicks_block +__on_player_changes_dimension __on_player_deploys_elytra __on_player_drops_item __on_player_drops_stack diff --git a/docs/scarpet/resources/editors/npp/scarpet.xml b/docs/scarpet/resources/editors/npp/scarpet.xml index da7e1bf4..c17b3811 100644 --- a/docs/scarpet/resources/editors/npp/scarpet.xml +++ b/docs/scarpet/resources/editors/npp/scarpet.xml @@ -84,6 +84,7 @@ __on_player_attacks_entity __on_player_breaks_block __on_player_clicks_block + __on_player_changes_dimension __on_player_deploys_elytra __on_player_drops_item __on_player_drops_stack diff --git a/src/main/java/carpet/mixins/ServerPlayerEntity_scarpetEventMixin.java b/src/main/java/carpet/mixins/ServerPlayerEntity_scarpetEventMixin.java index 17bbd74d..51ddea2f 100644 --- a/src/main/java/carpet/mixins/ServerPlayerEntity_scarpetEventMixin.java +++ b/src/main/java/carpet/mixins/ServerPlayerEntity_scarpetEventMixin.java @@ -3,20 +3,25 @@ package carpet.mixins; import carpet.fakes.EntityInterface; import carpet.script.EntityEventsGroup; import com.mojang.authlib.GameProfile; +import net.minecraft.entity.Entity; import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.stat.Stat; import net.minecraft.util.Hand; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; +import net.minecraft.world.dimension.DimensionType; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import static carpet.script.CarpetEventServer.Event.PLAYER_CHANGES_DIMENSION; 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; @@ -31,6 +36,8 @@ public abstract class ServerPlayerEntity_scarpetEventMixin extends PlayerEntity @Shadow protected abstract void consumeItem(); + @Shadow public boolean notInAnyWorld; + @Redirect(method = "consumeItem", at = @At( value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;consumeItem()V" @@ -77,4 +84,30 @@ public abstract class ServerPlayerEntity_scarpetEventMixin extends PlayerEntity if (!((EntityInterface)serverPlayerEntity.getVehicle()).isPermanentVehicle()) // won't since that method makes sure its not null serverPlayerEntity.setSneaking(sneaking); } + + private Vec3d previousLocation; + private DimensionType previousDimension; + + @Inject(method = "changeDimension", at = @At("HEAD")) + private void logPreviousCoordinates(DimensionType newDimension, CallbackInfoReturnable cir) + { + previousLocation = getPos(); + previousDimension = dimension; + } + + @Inject(method = "changeDimension", at = @At("RETURN")) + private void atChangeDimension(DimensionType newDimension, CallbackInfoReturnable cir) + { + if (PLAYER_CHANGES_DIMENSION.isNeeded()) + { + ServerPlayerEntity player = (ServerPlayerEntity) (Object)this; + Vec3d to = null; + if (!notInAnyWorld || previousDimension != DimensionType.THE_END || newDimension != DimensionType.OVERWORLD) + { + to = getPos(); + } + PLAYER_CHANGES_DIMENSION.onDimensionChange(player, previousLocation, to, previousDimension, newDimension); + } + } + } diff --git a/src/main/java/carpet/script/CarpetEventServer.java b/src/main/java/carpet/script/CarpetEventServer.java index 447396c0..10ca5210 100644 --- a/src/main/java/carpet/script/CarpetEventServer.java +++ b/src/main/java/carpet/script/CarpetEventServer.java @@ -527,6 +527,26 @@ public class CarpetEventServer handler.call( () -> Collections.singletonList(((c, t) -> new EntityValue(player))), player::getCommandSource); } }, + PLAYER_CHANGES_DIMENSION("player_changes_dimension", 5, false) + { + @Override + public void onDimensionChange(ServerPlayerEntity player, Vec3d from, Vec3d to, DimensionType fromDim, DimensionType dimTo) + { + // eligibility already checked in mixin + Value fromValue = ListValue.fromTriple(from.x, from.y, from.z); + Value toValue = (to == null)?Value.NULL:ListValue.fromTriple(to.x, to.y, to.z); + Value fromDimStr = new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.DIMENSION_TYPE.getId(fromDim))); + Value toDimStr = new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.DIMENSION_TYPE.getId(dimTo))); + + handler.call( () -> Arrays.asList( + ((c, t) -> new EntityValue(player)), + ((c, t) -> fromValue), + ((c, t) -> fromDimStr), + ((c, t) -> toValue), + ((c, t) -> toDimStr) + ), player::getCommandSource); + } + }, STATISTICS("statistic", 4, false) { private Identifier getStatId(Stat stat) @@ -599,8 +619,10 @@ 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 onDimensionChange(ServerPlayerEntity player, Vec3d from, Vec3d to, DimensionType fromDim, DimensionType dimTo) {} 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 8e3d937a..036a0e38 100644 --- a/src/main/resources/assets/carpet/scripts/event_test.sc +++ b/src/main/resources/assets/carpet/scripts/event_test.sc @@ -220,3 +220,13 @@ __on_player_respawns(player) -> print('__on_player_respawns(player)'); print('Player '+player+' respawns.') ); + +__on_player_changes_dimension(player, from_pos, from_dimension, to_pos, to_dimension) -> +( + print(''); + print('__on_player_changes_dimension(player, from_pos, from_dimension, to_pos, to_dimension)'); + print('player changes dimensions:'); + print(' - player: '+player); + print(' - from '+from_dimension+' at '+map(from_pos, str('%.2f',_))); + print(' - to '+to_dimension+if(to_pos == null, '', ' at '+map(to_pos, str('%.2f',_)))); +) From 66c222a77a7ca22277710aaf43f8c3c2d4c954f3 Mon Sep 17 00:00:00 2001 From: gnembon Date: Tue, 19 May 2020 18:17:50 -0300 Subject: [PATCH 136/198] poi results now come out sorted by distance --- src/main/java/carpet/script/CarpetExpression.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 2e155927..b77e2ea4 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -510,7 +510,7 @@ public class CarpetExpression return LazyValue.NULL; } - Value ret = ListValue.wrap(store.get(condition, pos, (int)radius, status).map( p -> + Value ret = ListValue.wrap(store.get(condition, pos, (int)radius, status).sorted(Comparator.comparingDouble(p -> p.getPos().getSquaredDistance(pos))).map(p -> ListValue.of( new StringValue(p.getType().toString()), new NumericValue(p.getType().getTicketCount() - ((PointOfInterest_scarpetMixin)p).getFreeTickets()), From ab86fc929292521f42f1dd7751bd65da9805e9a0 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 20 May 2020 02:09:57 -0300 Subject: [PATCH 137/198] added 'portal_cooldown' and 'portal_timer' to entity API (query and modify) --- docs/scarpet/Full.md | 16 ++++++++++++++++ docs/scarpet/api/Entities.md | 16 ++++++++++++++++ src/main/java/carpet/fakes/EntityInterface.java | 4 ++++ .../carpet/mixins/Entity_scarpetEventsMixin.java | 13 +++++++++++++ .../java/carpet/script/value/EntityValue.java | 16 ++++++++++++++++ 5 files changed, 65 insertions(+) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index 9882a423..b8c7ae9c 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -2526,6 +2526,14 @@ Breeding age of passive entity, in ticks. If negative, time to adulthood, if pos For living entities, the number of ticks they fall outside of immediate player presence. +### `query(e, 'portal_cooldown')` + +Number of ticks remaining until an entity can use a portal again. + +### `query(e, 'portal_timer')` + +Number of ticks an entity sits in a portal. + ### `query(e, 'item')` The item triple (name, count, nbt) if its an item entity, `null` otherwise @@ -2739,6 +2747,14 @@ Sets the breeding age for the animal. Sets a custom despawn timer value. +### `modify(e, 'portal_cooldown', number)` + +Sets a custom number of ticks remaining until an entity can use a portal again. + +### `modify(e, 'portal_timer', number)` + +Sets a custom number of ticks an entity sits in a portal. + ### `modify(e, 'dismount')` Dismounts riding entity. diff --git a/docs/scarpet/api/Entities.md b/docs/scarpet/api/Entities.md index b41bbde0..36365a78 100644 --- a/docs/scarpet/api/Entities.md +++ b/docs/scarpet/api/Entities.md @@ -204,6 +204,14 @@ Breeding age of passive entity, in ticks. If negative, time to adulthood, if pos For living entities, the number of ticks they fall outside of immediate player presence. +### `query(e, 'portal_cooldown')` + +Number of ticks remaining until an entity can use a portal again. + +### `query(e, 'portal_timer')` + +Number of ticks an entity sits in a portal. + ### `query(e, 'item')` The item triple (name, count, nbt) if its an item entity, `null` otherwise @@ -417,6 +425,14 @@ Sets the breeding age for the animal. Sets a custom despawn timer value. +### `modify(e, 'portal_cooldown', number)` + +Sets a custom number of ticks remaining until an entity can use a portal again. + +### `modify(e, 'portal_timer', number)` + +Sets a custom number of ticks an entity sits in a portal. + ### `modify(e, 'dismount')` Dismounts riding entity. diff --git a/src/main/java/carpet/fakes/EntityInterface.java b/src/main/java/carpet/fakes/EntityInterface.java index 3e4713b9..4970d5e7 100644 --- a/src/main/java/carpet/fakes/EntityInterface.java +++ b/src/main/java/carpet/fakes/EntityInterface.java @@ -11,4 +11,8 @@ public interface EntityInterface boolean isPermanentVehicle(); void setPermanentVehicle(boolean permanent); + + int getPortalTimer(); + + void setPortalTimer(int amount); } diff --git a/src/main/java/carpet/mixins/Entity_scarpetEventsMixin.java b/src/main/java/carpet/mixins/Entity_scarpetEventsMixin.java index c4193054..45a8afcf 100644 --- a/src/main/java/carpet/mixins/Entity_scarpetEventsMixin.java +++ b/src/main/java/carpet/mixins/Entity_scarpetEventsMixin.java @@ -14,6 +14,7 @@ public abstract class Entity_scarpetEventsMixin implements EntityInterface { @Shadow public boolean removed; + @Shadow protected int netherPortalTime; private boolean permanentVehicle; private final EntityEventsGroup events = new EntityEventsGroup(); @@ -36,6 +37,18 @@ public abstract class Entity_scarpetEventsMixin implements EntityInterface permanentVehicle = permanent; } + @Override + public int getPortalTimer() + { + return netherPortalTime; + } + + @Override + public void setPortalTimer(int amount) + { + netherPortalTime = amount; + } + @Inject(method = "tick", at = @At("HEAD")) private void onTickCall(CallbackInfo ci) { diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index d6948451..45be924e 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -259,6 +259,8 @@ public class EntityValue extends Value put("item", (e, a) -> (e instanceof ItemEntity)?ListValue.fromItemStack(((ItemEntity) e).getStack()):Value.NULL); put("count", (e, a) -> (e instanceof ItemEntity)?new NumericValue(((ItemEntity) e).getStack().getCount()):Value.NULL); put("pickup_delay", (e, a) -> (e instanceof ItemEntity)?new NumericValue(((ItemEntityInterface) e).getPickupDelayCM()):Value.NULL); + put("portal_cooldown", (e , a) ->new NumericValue(((EntityInterface)e).getPortalTimer())); + put("portal_timer", (e , a) ->new NumericValue(e.netherPortalCooldown)); // ItemEntity -> despawn timer via ssGetAge put("is_baby", (e, a) -> (e instanceof LivingEntity)?new NumericValue(((LivingEntity) e).isBaby()):Value.NULL); put("target", (e, a) -> { @@ -825,6 +827,20 @@ public class EntityValue extends Value } }); + put("portal_cooldown", (e , v) -> + { + if (v==null) + throw new InternalExpressionException("'portal_cooldown' requires a value to set"); + e.netherPortalCooldown = NumericValue.asNumber(v).getInt(); + }); + + put("portal_timer", (e , v) -> + { + if (v==null) + throw new InternalExpressionException("'portal_timer' requires a value to set"); + ((EntityInterface) e).setPortalTimer(NumericValue.asNumber(v).getInt()); + }); + put("ai", (e, v) -> { if (e instanceof MobEntity) From 934038828cb24b3a5d3fa2895fd6b2d20daf3a45 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 20 May 2020 02:13:12 -0300 Subject: [PATCH 138/198] handled errors in server docked tasks to continue stack trace of internal exceptions. --- .../java/carpet/script/CarpetExpression.java | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index b77e2ea4..d1329558 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -139,6 +139,7 @@ import java.util.Locale; import java.util.Map; import java.util.Optional; import java.util.UUID; +import java.util.concurrent.CompletionException; import java.util.function.BiFunction; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -2833,12 +2834,43 @@ public class CarpetExpression return (_c, _t) -> ret; }); - this.expr.addLazyFunction("task_dock", 1, (c, t, lv) -> { + this.expr.addLazyFunctionWithDelegation("task_dock", 1, (c, t, expr, tok, lv) -> { CarpetContext cc = (CarpetContext)c; MinecraftServer server = cc.s.getMinecraftServer(); if (server.isOnThread()) return lv.get(0); // pass through for on thread tasks Value[] result = new Value[]{Value.NULL}; - ((CarpetContext) c).s.getMinecraftServer().submitAndJoin(() -> result[0] = lv.get(0).evalValue(c, t)); + RuntimeException[] internal = new RuntimeException[]{null}; + try + { + ((CarpetContext) c).s.getMinecraftServer().submitAndJoin(() -> + { + try + { + result[0] = lv.get(0).evalValue(c, t); + } + catch (ExpressionException exc) + { + internal[0] = exc; + } + catch (InternalExpressionException exc) + { + internal[0] = new ExpressionException(c, expr, tok, exc.getMessage(), exc.stack); + } + + catch (ArithmeticException exc) + { + internal[0] = new ExpressionException(c, expr, tok, "Your math is wrong, "+exc.getMessage()); + } + }); + } + catch (CompletionException exc) + { + throw new InternalExpressionException("Error while executing docked task section, internal stack trace is gone"); + } + if (internal[0] != null) + { + throw internal[0]; + } Value ret = result[0]; // preventing from lazy evaluating of the result in case a future completes later return (_c, _t) -> ret; // pass through placeholder From 864c9450f7a5734dcf618a7db2d26c901d959201 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 20 May 2020 10:40:01 -0300 Subject: [PATCH 139/198] renamed vine to vegetation and redstone_bits to decoration --- src/main/java/carpet/utils/BlockInfo.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/carpet/utils/BlockInfo.java b/src/main/java/carpet/utils/BlockInfo.java index 30da08fd..f343d1b4 100644 --- a/src/main/java/carpet/utils/BlockInfo.java +++ b/src/main/java/carpet/utils/BlockInfo.java @@ -109,14 +109,14 @@ public class BlockInfo put(Material.CARPET , "carpet" ); put(Material.PLANT , "plant" ); put(Material.UNDERWATER_PLANT, "water_plant" ); - put(Material.REPLACEABLE_PLANT, "vine" ); + put(Material.REPLACEABLE_PLANT, "vegetation" ); put(Material.SEAGRASS , "sea_grass" ); put(Material.WATER , "water" ); put(Material.BUBBLE_COLUMN , "bubble_column"); put(Material.LAVA , "lava" ); put(Material.SNOW , "snow_layer" ); put(Material.FIRE , "fire" ); - put(Material.PART , "redstone_bits"); + put(Material.PART , "decoration" ); put(Material.COBWEB , "cobweb" ); put(Material.REDSTONE_LAMP , "redstone_lamp"); put(Material.CLAY , "clay" ); From 706ddb546a1a63e5811d3908a12754505bb80ff8 Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 21 May 2020 03:07:08 -0300 Subject: [PATCH 140/198] 1.3.24 --- gradle.properties | 2 +- src/main/java/carpet/CarpetSettings.java | 2 +- src/main/resources/fabric.mod.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 5a75063c..4d90ff2c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ org.gradle.jvmargs=-Xmx1G loader_version=0.8.3+build.196 # Mod Properties - mod_version = 1.3.23+v200513 + mod_version = 1.3.24+v200520 maven_group = carpet archives_base_name = fabric-carpet diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index 938e11c0..2364f373 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -34,7 +34,7 @@ import static carpet.settings.RuleCategory.CLIENT; @SuppressWarnings("CanBeFinal") public class CarpetSettings { - public static final String carpetVersion = "1.3.23+v200513"; + public static final String carpetVersion = "1.3.24+v200520"; public static final Logger LOG = LogManager.getLogger(); public static boolean skipGenerationChecks = false; public static boolean impendingFillSkipUpdates = false; diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 4ff9c1ff..2fefa220 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,7 +1,7 @@ { "schemaVersion": 1, "id": "carpet", - "version": "1.3.23", + "version": "1.3.24", "name": "Carpet Mod in Fabric", "description": "Carpet made out of fabric", From e7170ddef9e4331e4ceb4f134d4969f37d24993d Mon Sep 17 00:00:00 2001 From: gnembon Date: Fri, 22 May 2020 01:19:08 -0300 Subject: [PATCH 141/198] added translation support for extensions --- src/main/java/carpet/CarpetExtension.java | 4 ++ src/main/java/carpet/utils/Translations.java | 51 +++++++++++++++----- 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/src/main/java/carpet/CarpetExtension.java b/src/main/java/carpet/CarpetExtension.java index 7bb705cd..499c6c9e 100644 --- a/src/main/java/carpet/CarpetExtension.java +++ b/src/main/java/carpet/CarpetExtension.java @@ -6,6 +6,8 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; +import java.util.Map; + public interface CarpetExtension { /** @@ -51,4 +53,6 @@ public interface CarpetExtension default String version() {return null;} default void registerLoggers() {} + + default Map canHasTranslations(String lang) { return null;} } diff --git a/src/main/java/carpet/utils/Translations.java b/src/main/java/carpet/utils/Translations.java index 081d656b..b27be4b1 100644 --- a/src/main/java/carpet/utils/Translations.java +++ b/src/main/java/carpet/utils/Translations.java @@ -1,5 +1,7 @@ package carpet.utils; +import carpet.CarpetExtension; +import carpet.CarpetServer; import carpet.CarpetSettings; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -8,8 +10,8 @@ import net.minecraft.server.command.ServerCommandSource; import org.apache.commons.io.IOUtils; import java.io.IOException; -import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; +import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -37,6 +39,22 @@ public class Translations return translationMap != null && translationMap.containsKey(key); } + public static Map getTranslationFromResourcePath(String path) + { + String dataJSON; + try + { + dataJSON = IOUtils.toString( + Objects.requireNonNull(Translations.class.getClassLoader().getResourceAsStream(String.format("assets/carpet/lang/%s.json", CarpetSettings.language))), + StandardCharsets.UTF_8); + } catch (NullPointerException | IOException e) { + return null; + } + Gson gson = new GsonBuilder().enableComplexMapKeySerialization().create(); + return gson.fromJson(dataJSON, new TypeToken>() {}.getType()); + } + + public static void updateLanguage(ServerCommandSource source) { if (CarpetSettings.language.equalsIgnoreCase("none")) @@ -44,23 +62,30 @@ public class Translations translationMap = null; return; } - String langJs; - try + Map translations = new HashMap<>(); + Map trans = getTranslationFromResourcePath(String.format("assets/carpet/lang/%s.json", CarpetSettings.language)); + if (trans != null) trans.forEach(translations::put); + + for (CarpetExtension ext : CarpetServer.extensions) { - langJs = IOUtils.toString( - Objects.requireNonNull(Translations.class.getClassLoader().getResourceAsStream(String.format("assets/carpet/lang/%s.json", CarpetSettings.language))), - StandardCharsets.UTF_8); - } catch (NullPointerException | IOException e) { - Messenger.m(source, "r Failed to update language"); + Map extMappings = ext.canHasTranslations(CarpetSettings.language); + if (extMappings != null) + { + extMappings.forEach((key, value) -> + { + if (!translations.containsKey(key)) translations.put(key, value); + }); + } + } + translations.entrySet().removeIf(e -> e.getKey().startsWith("//")); + if (translations.isEmpty()) + { + translationMap = null; return; } - Gson gson = new GsonBuilder().enableComplexMapKeySerialization().create(); - Type type = new TypeToken>() {}.getType(); - translationMap = gson.fromJson(langJs, type); - translationMap.entrySet().removeIf(e -> e.getKey().startsWith("//")); + translationMap = translations; } - public static boolean isValidLanguage(String newValue) { // will put some validations for availble languages at some point From 64310ed84bf8896bb97422daad5de595816a443d Mon Sep 17 00:00:00 2001 From: gnembon Date: Mon, 25 May 2020 01:59:56 -0300 Subject: [PATCH 142/198] fixed timings, fixes #291 --- src/main/java/carpet/helpers/EntityPlayerActionPack.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/carpet/helpers/EntityPlayerActionPack.java b/src/main/java/carpet/helpers/EntityPlayerActionPack.java index 5defa3a1..d33694a2 100644 --- a/src/main/java/carpet/helpers/EntityPlayerActionPack.java +++ b/src/main/java/carpet/helpers/EntityPlayerActionPack.java @@ -390,6 +390,7 @@ public class EntityPlayerActionPack { player.interactionManager.processBlockBreakingAction(pos, PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, side, player.server.getWorldHeight()); ap.currentBlock = null; + ap.blockHitDelay = 5; blockBroken = true; } player.world.setBlockBreakingInfo(-1, pos, (int) (ap.curBlockDamageMP * 10)); From 6618afa5ede458f71850ef3b7ba1af9422255926 Mon Sep 17 00:00:00 2001 From: gnembon Date: Mon, 25 May 2020 23:50:28 -0300 Subject: [PATCH 143/198] clean log when placing structures and features --- src/main/java/carpet/mixins/ChunkMixin.java | 1 + .../mixins/ChunkRegion_scarpetPlopMixin.java | 19 ++++++++++++++++ .../StructurePiece_scarpetPlopMixin.java | 22 +++++++++++++++++++ src/main/resources/carpet.mixins.json | 2 ++ 4 files changed, 44 insertions(+) create mode 100644 src/main/java/carpet/mixins/ChunkRegion_scarpetPlopMixin.java create mode 100644 src/main/java/carpet/mixins/StructurePiece_scarpetPlopMixin.java diff --git a/src/main/java/carpet/mixins/ChunkMixin.java b/src/main/java/carpet/mixins/ChunkMixin.java index 92eb8dd7..b1a9b128 100644 --- a/src/main/java/carpet/mixins/ChunkMixin.java +++ b/src/main/java/carpet/mixins/ChunkMixin.java @@ -11,6 +11,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(Chunk.class) public abstract class ChunkMixin { + // failed to mixin into interface. need to mixin in two places that uses it @Inject(method = "markBlockForPostProcessing(Lnet/minecraft/util/math/BlockPos;)V", at =@At("HEAD"), cancellable = true) private void squashWarnings(BlockPos blockPos_1, CallbackInfo ci) diff --git a/src/main/java/carpet/mixins/ChunkRegion_scarpetPlopMixin.java b/src/main/java/carpet/mixins/ChunkRegion_scarpetPlopMixin.java new file mode 100644 index 00000000..fb06e695 --- /dev/null +++ b/src/main/java/carpet/mixins/ChunkRegion_scarpetPlopMixin.java @@ -0,0 +1,19 @@ +package carpet.mixins; + +import carpet.CarpetSettings; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.ChunkRegion; +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.CallbackInfo; + +@Mixin(ChunkRegion.class) +public class ChunkRegion_scarpetPlopMixin +{ + @Inject(method = "markBlockForPostProcessing", at = @At("HEAD")) + private void markOrNot(BlockPos blockPos, CallbackInfo ci) + { + if (CarpetSettings.skipGenerationChecks) ci.cancel(); + } +} diff --git a/src/main/java/carpet/mixins/StructurePiece_scarpetPlopMixin.java b/src/main/java/carpet/mixins/StructurePiece_scarpetPlopMixin.java new file mode 100644 index 00000000..94b2cfc1 --- /dev/null +++ b/src/main/java/carpet/mixins/StructurePiece_scarpetPlopMixin.java @@ -0,0 +1,22 @@ +package carpet.mixins; + +import carpet.CarpetSettings; +import net.minecraft.structure.StructurePiece; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.chunk.Chunk; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(StructurePiece.class) +public class StructurePiece_scarpetPlopMixin +{ + @Redirect(method = "addBlock", at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/chunk/Chunk;markBlockForPostProcessing(Lnet/minecraft/util/math/BlockPos;)V" + )) + private void markOrNot(Chunk chunk, BlockPos pos) + { + if (!CarpetSettings.skipGenerationChecks) chunk.markBlockForPostProcessing(pos); + } +} diff --git a/src/main/resources/carpet.mixins.json b/src/main/resources/carpet.mixins.json index 46ccfed2..c1356941 100644 --- a/src/main/resources/carpet.mixins.json +++ b/src/main/resources/carpet.mixins.json @@ -64,6 +64,8 @@ "CoralFeatureMixin", "StructureFeatureMixin", "World_scarpetPlopMixin", + "ChunkRegion_scarpetPlopMixin", + "StructurePiece_scarpetPlopMixin", "ServerPlayNetworkHandler_scarpetEventsMixin", "ServerPlayerInteractionManager_scarpetEventsMixin", From 2c777ea3ad555a64d1d23204e94fc64630be407e Mon Sep 17 00:00:00 2001 From: gnembon Date: Tue, 26 May 2020 14:44:06 -0300 Subject: [PATCH 144/198] fix client crash when accessing messenger --- .../carpet/mixins/ClientPlayerEntity_clientCommandMixin.java | 3 ++- src/main/java/carpet/settings/SettingsManager.java | 4 ++-- src/main/java/carpet/utils/Messenger.java | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/carpet/mixins/ClientPlayerEntity_clientCommandMixin.java b/src/main/java/carpet/mixins/ClientPlayerEntity_clientCommandMixin.java index 622de0c3..a0347524 100644 --- a/src/main/java/carpet/mixins/ClientPlayerEntity_clientCommandMixin.java +++ b/src/main/java/carpet/mixins/ClientPlayerEntity_clientCommandMixin.java @@ -13,7 +13,8 @@ public class ClientPlayerEntity_clientCommandMixin @Inject(method = "sendChatMessage", at = @At("HEAD")) private void inspectMessage(String string, CallbackInfo ci) { + ClientPlayerEntity playerSource = (ClientPlayerEntity)(Object) this; if (CarpetServer.minecraft_server == null) - CarpetServer.settingsManager.inspectClientsideCommand(string); + CarpetServer.settingsManager.inspectClientsideCommand(playerSource.getCommandSource(), string); } } diff --git a/src/main/java/carpet/settings/SettingsManager.java b/src/main/java/carpet/settings/SettingsManager.java index 3b27d3c2..93aac4df 100644 --- a/src/main/java/carpet/settings/SettingsManager.java +++ b/src/main/java/carpet/settings/SettingsManager.java @@ -570,7 +570,7 @@ public class SettingsManager return 1; } - public void inspectClientsideCommand(String string) + public void inspectClientsideCommand(ServerCommandSource source, String string) { if (string.startsWith("/carpet ")) { @@ -581,7 +581,7 @@ public class SettingsManager String strOption = res[2]; if (rules.containsKey(setting) && rules.get(setting).isClient) { - rules.get(setting).set(null, strOption); + rules.get(setting).set(source, strOption); } } diff --git a/src/main/java/carpet/utils/Messenger.java b/src/main/java/carpet/utils/Messenger.java index 953028f8..78e7fddc 100644 --- a/src/main/java/carpet/utils/Messenger.java +++ b/src/main/java/carpet/utils/Messenger.java @@ -231,7 +231,7 @@ public class Messenger //message source public static void m(ServerCommandSource source, Object ... fields) { - source.sendFeedback(Messenger.c(fields),source.getMinecraftServer().getWorld(DimensionType.OVERWORLD) != null); + source.sendFeedback(Messenger.c(fields),source.getMinecraftServer() != null && source.getMinecraftServer().getWorld(DimensionType.OVERWORLD) != null); } public static void m(PlayerEntity player, Object ... fields) { From a1200d4c37cabad1c78c9d716bf60b9e7fdd086c Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 27 May 2020 00:53:21 -0300 Subject: [PATCH 145/198] fixed so modify(..,'effect',...) does what docs say. --- src/main/java/carpet/script/value/EntityValue.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index 45be924e..68c3f14d 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -861,7 +861,10 @@ public class EntityValue extends Value if (!(e instanceof LivingEntity)) return; LivingEntity le = (LivingEntity)e; if (v == null) + { le.clearStatusEffects(); + return; + } else if (v instanceof ListValue) { List lv = ((ListValue) v).getItems(); @@ -895,6 +898,15 @@ public class EntityValue extends Value return; } } + else + { + String effectName = v.getString(); + StatusEffect effect = Registry.STATUS_EFFECT.get(new Identifier(effectName)); + if (effect == null) + throw new InternalExpressionException("Wrong effect name: "+effectName); + le.removeStatusEffect(effect); + return; + } throw new InternalExpressionException("'effect' needs either no arguments (clear) or effect name, duration, and optional amplifier, show particles and show icon"); }); From 6747bb600155a4dc5f0c8ac26c7beb5230d0c613 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 27 May 2020 09:28:14 -0300 Subject: [PATCH 146/198] 1.3.25 --- gradle.properties | 2 +- src/main/java/carpet/CarpetSettings.java | 2 +- src/main/resources/fabric.mod.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 4d90ff2c..27ae8895 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ org.gradle.jvmargs=-Xmx1G loader_version=0.8.3+build.196 # Mod Properties - mod_version = 1.3.24+v200520 + mod_version = 1.3.25+v200527 maven_group = carpet archives_base_name = fabric-carpet diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index 2364f373..4913bb1f 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -34,7 +34,7 @@ import static carpet.settings.RuleCategory.CLIENT; @SuppressWarnings("CanBeFinal") public class CarpetSettings { - public static final String carpetVersion = "1.3.24+v200520"; + public static final String carpetVersion = "1.3.25+v200527"; public static final Logger LOG = LogManager.getLogger(); public static boolean skipGenerationChecks = false; public static boolean impendingFillSkipUpdates = false; diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 2fefa220..0e33c3ef 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,7 +1,7 @@ { "schemaVersion": 1, "id": "carpet", - "version": "1.3.24", + "version": "1.3.25", "name": "Carpet Mod in Fabric", "description": "Carpet made out of fabric", From 2522884da3a2da8e5752e7eb6646df208cc1e2bb Mon Sep 17 00:00:00 2001 From: DeadlyMC <43000902+DeadlyMC@users.noreply.github.com> Date: Thu, 28 May 2020 00:53:52 +0530 Subject: [PATCH 147/198] Client-server syncing (#295) * Sync carpet settings * Sync tick rate --- src/main/java/carpet/CarpetServer.java | 7 ++ .../carpet/helpers/ClientNetworkHandler.java | 59 +++++++++++++++++ .../carpet/helpers/ServerNetworkHandler.java | 66 +++++++++++++++++++ src/main/java/carpet/helpers/TickSpeed.java | 1 + .../mixins/ClientPlayNetworkHandlerMixin.java | 44 +++++++++++++ src/main/resources/carpet.mixins.json | 3 +- 6 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 src/main/java/carpet/helpers/ClientNetworkHandler.java create mode 100644 src/main/java/carpet/helpers/ServerNetworkHandler.java create mode 100644 src/main/java/carpet/mixins/ClientPlayNetworkHandlerMixin.java diff --git a/src/main/java/carpet/CarpetServer.java b/src/main/java/carpet/CarpetServer.java index 554a4ca1..f86cfa31 100644 --- a/src/main/java/carpet/CarpetServer.java +++ b/src/main/java/carpet/CarpetServer.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.Random; import carpet.commands.*; +import carpet.helpers.ServerNetworkHandler; import carpet.helpers.TickSpeed; import carpet.logging.LoggerRegistry; import carpet.script.CarpetScriptServer; @@ -17,6 +18,7 @@ import net.fabricmc.loader.api.FabricLoader; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.Identifier; public class CarpetServer // static for now - easier to handle all around the code, its one anyways { @@ -26,6 +28,7 @@ public class CarpetServer // static for now - easier to handle all around the co public static CarpetScriptServer scriptServer; public static SettingsManager settingsManager; public static final List extensions = new ArrayList<>(); + public static final Identifier CARPET_CHANNEL = new Identifier("carpet:info"); // Separate from onServerLoaded, because a server can be loaded multiple times in singleplayer public static void manageExtension(CarpetExtension extension) @@ -45,6 +48,9 @@ public class CarpetServer // static for now - easier to handle all around the co settingsManager = new SettingsManager(CarpetSettings.carpetVersion, "carpet", "Carpet Mod"); settingsManager.parseSettingsClass(CarpetSettings.class); extensions.forEach(CarpetExtension::onGameStarted); + CarpetServer.settingsManager.addRuleObserver((source, parsedRule, s) -> { + ServerNetworkHandler.sendUpdateToClient(parsedRule.name, parsedRule.getAsString(), source); + }); } public static void onServerLoaded(MinecraftServer server) @@ -104,6 +110,7 @@ public class CarpetServer // static for now - easier to handle all around the co { LoggerRegistry.playerConnected(player); extensions.forEach(e -> e.onPlayerLoggedIn(player)); + ServerNetworkHandler.onPlayerJoin(player); } public static void onPlayerLoggedOut(ServerPlayerEntity player) diff --git a/src/main/java/carpet/helpers/ClientNetworkHandler.java b/src/main/java/carpet/helpers/ClientNetworkHandler.java new file mode 100644 index 00000000..5e15e6ba --- /dev/null +++ b/src/main/java/carpet/helpers/ClientNetworkHandler.java @@ -0,0 +1,59 @@ +package carpet.helpers; + +import carpet.CarpetServer; +import carpet.CarpetSettings; +import carpet.settings.ParsedRule; +import net.minecraft.client.MinecraftClient; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.util.Identifier; +import net.minecraft.util.PacketByteBuf; + +public class ClientNetworkHandler +{ + public static void handleData(Identifier channel, PacketByteBuf data) + { + if (CarpetServer.CARPET_CHANNEL.equals(channel) && data != null) + { + int id = data.readVarInt(); + + if (id == 1) + setOnJoinInfo(data); + else if (id == 2) + updateRule(data); + else if (id == 3) + updateTickRateClient(data); + } + } + + private static void setOnJoinInfo(PacketByteBuf data) + { + CompoundTag compound = data.readCompoundTag(); + if (compound == null) return; + + TickSpeed.tickrate(compound.getFloat("Tickrate")); + + ListTag rulesList = compound.getList("rules", 10); + for (Tag tag : rulesList) + { + CompoundTag ruleNBT = (CompoundTag) tag; + String rule = ruleNBT.getString("rule"); + String value = ruleNBT.getString("value"); + CarpetServer.settingsManager.getRule(rule).set(null, value); + } + } + + private static void updateRule(PacketByteBuf data) + { + String rule = data.readString(); + String newValue = data.readString(); + CarpetServer.settingsManager.getRule(rule).set(null, newValue); + } + + private static void updateTickRateClient(PacketByteBuf data) + { + float rate = data.readFloat(); + TickSpeed.tickrate(rate); + } +} diff --git a/src/main/java/carpet/helpers/ServerNetworkHandler.java b/src/main/java/carpet/helpers/ServerNetworkHandler.java new file mode 100644 index 00000000..77b393d3 --- /dev/null +++ b/src/main/java/carpet/helpers/ServerNetworkHandler.java @@ -0,0 +1,66 @@ +package carpet.helpers; + +import carpet.CarpetServer; +import carpet.CarpetSettings; +import carpet.settings.ParsedRule; +import io.netty.buffer.Unpooled; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.PacketByteBuf; + +public class ServerNetworkHandler +{ + public static void onPlayerJoin(ServerPlayerEntity playerEntity) + { + CompoundTag data = new CompoundTag(); + + data.putFloat("Tickrate", TickSpeed.tickrate); + + ListTag rulesList = new ListTag(); + for (ParsedRule rule : CarpetServer.settingsManager.getRules()) + { + CompoundTag ruleNBT = new CompoundTag(); + + ruleNBT.putString("rule" ,rule.name); + ruleNBT.putString("value", rule.getAsString()); + ruleNBT.putString("default", rule.defaultAsString); + rulesList.add(ruleNBT); + } + data.put("rules", rulesList); + PacketByteBuf packetBuf = new PacketByteBuf(Unpooled.buffer()); + packetBuf.writeVarInt(1); + packetBuf.writeCompoundTag(data); + playerEntity.networkHandler.sendPacket(new CustomPayloadS2CPacket(CarpetServer.CARPET_CHANNEL, packetBuf)); + } + + public static void sendUpdateToClient(String rule, String newValue, ServerCommandSource source) + { + PacketByteBuf data = new PacketByteBuf(Unpooled.buffer()); + + data.writeVarInt(2); + data.writeString(rule); + data.writeString(newValue); + for (ServerPlayerEntity player : source.getMinecraftServer().getPlayerManager().getPlayerList()) + { + player.networkHandler.sendPacket(new CustomPayloadS2CPacket(CarpetServer.CARPET_CHANNEL, data)); + } + } + + public static void sendTickRateToPlayers(float rate) + { + PacketByteBuf data = new PacketByteBuf(Unpooled.buffer()); + data.writeVarInt(3); + data.writeFloat(rate); + if (CarpetServer.minecraft_server != null) + { + for (ServerPlayerEntity player : CarpetServer.minecraft_server.getPlayerManager().getPlayerList()) + { + player.networkHandler.sendPacket(new CustomPayloadS2CPacket(CarpetServer.CARPET_CHANNEL, data)); + } + } + } +} diff --git a/src/main/java/carpet/helpers/TickSpeed.java b/src/main/java/carpet/helpers/TickSpeed.java index 33d735b7..1c1c4d2b 100644 --- a/src/main/java/carpet/helpers/TickSpeed.java +++ b/src/main/java/carpet/helpers/TickSpeed.java @@ -221,6 +221,7 @@ public class TickSpeed } } } + ServerNetworkHandler.sendTickRateToPlayers(tickrate); } public static BiConsumer addTickrateListener(String modId, BiConsumer tickrateListener) diff --git a/src/main/java/carpet/mixins/ClientPlayNetworkHandlerMixin.java b/src/main/java/carpet/mixins/ClientPlayNetworkHandlerMixin.java new file mode 100644 index 00000000..0e8fafcf --- /dev/null +++ b/src/main/java/carpet/mixins/ClientPlayNetworkHandlerMixin.java @@ -0,0 +1,44 @@ +package carpet.mixins; + +import carpet.CarpetServer; +import carpet.helpers.ClientNetworkHandler; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket; +import net.minecraft.util.Identifier; +import net.minecraft.util.PacketByteBuf; +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.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +@Mixin(ClientPlayNetworkHandler.class) +public abstract class ClientPlayNetworkHandlerMixin +{ + @Inject(method = "onCustomPayload", at = @At(value = "CONSTANT", args = "stringValue=Unknown custom packed identifier: {}"), cancellable = true, locals = LocalCapture.CAPTURE_FAILSOFT, require = 0) + private void onCustomPayloadNotFound(CustomPayloadS2CPacket packet, CallbackInfo ci, Identifier id, PacketByteBuf buf) + { + if (CarpetServer.CARPET_CHANNEL.equals(id)) + { + if (buf.refCnt() > 0) + { + buf.release(); + } + + ci.cancel(); + } + } + + @Inject(method = "onCustomPayload", at = @At("HEAD"), cancellable = true) + private void onOnCustomPayload(CustomPayloadS2CPacket packet, CallbackInfo ci) + { + Identifier channel = packet.getChannel(); + PacketByteBuf buf = packet.getData(); + ClientNetworkHandler.handleData(channel, buf); + ci.cancel(); + } +} diff --git a/src/main/resources/carpet.mixins.json b/src/main/resources/carpet.mixins.json index c1356941..041dbaaa 100644 --- a/src/main/resources/carpet.mixins.json +++ b/src/main/resources/carpet.mixins.json @@ -177,7 +177,8 @@ "ClientPlayNetworkHandler_smoothClientAnimationsMixin", "ClientPlayerEntity_clientCommandMixin", "WorldRenderer_fogOffMixin", - "WorldRenderer_creativeNoClipMixin" + "WorldRenderer_creativeNoClipMixin", + "ClientPlayNetworkHandlerMixin" ], "server": [ From e540f9e2383f9d4268bd840ad147d833b7fe1e88 Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 28 May 2020 00:06:28 -0300 Subject: [PATCH 148/198] carpet client synchronizations and protocols --- src/main/java/carpet/CarpetServer.java | 24 ++-- src/main/java/carpet/CarpetSettings.java | 5 +- .../java/carpet/commands/TickCommand.java | 2 +- .../CustomPayloadC2SPacketInterface.java | 10 ++ .../carpet/helpers/ClientNetworkHandler.java | 59 --------- .../carpet/helpers/ServerNetworkHandler.java | 66 ---------- src/main/java/carpet/helpers/TickSpeed.java | 7 +- .../mixins/ClientPlayNetworkHandlerMixin.java | 51 ++++---- ...ClientPlayerEntity_clientCommandMixin.java | 7 +- .../mixins/CustomPayloadC2SPacketMixin.java | 27 ++++ .../carpet/mixins/MinecraftClientMixin.java | 8 ++ .../mixins/ServerPlayNetworkHandlerMixin.java | 31 +++++ .../java/carpet/network/CarpetClient.java | 52 ++++++++ .../carpet/network/ClientNetworkHandler.java | 93 +++++++++++++ .../carpet/network/ServerNetworkHandler.java | 123 ++++++++++++++++++ .../java/carpet/settings/SettingsManager.java | 6 +- src/main/java/carpet/settings/Validator.java | 2 +- src/main/java/carpet/utils/Messenger.java | 3 +- src/main/resources/carpet.mixins.json | 3 + 19 files changed, 406 insertions(+), 173 deletions(-) create mode 100644 src/main/java/carpet/fakes/CustomPayloadC2SPacketInterface.java delete mode 100644 src/main/java/carpet/helpers/ClientNetworkHandler.java delete mode 100644 src/main/java/carpet/helpers/ServerNetworkHandler.java create mode 100644 src/main/java/carpet/mixins/CustomPayloadC2SPacketMixin.java create mode 100644 src/main/java/carpet/mixins/ServerPlayNetworkHandlerMixin.java create mode 100644 src/main/java/carpet/network/CarpetClient.java create mode 100644 src/main/java/carpet/network/ClientNetworkHandler.java create mode 100644 src/main/java/carpet/network/ServerNetworkHandler.java diff --git a/src/main/java/carpet/CarpetServer.java b/src/main/java/carpet/CarpetServer.java index f86cfa31..7cc7f021 100644 --- a/src/main/java/carpet/CarpetServer.java +++ b/src/main/java/carpet/CarpetServer.java @@ -6,7 +6,7 @@ import java.util.List; import java.util.Random; import carpet.commands.*; -import carpet.helpers.ServerNetworkHandler; +import carpet.network.ServerNetworkHandler; import carpet.helpers.TickSpeed; import carpet.logging.LoggerRegistry; import carpet.script.CarpetScriptServer; @@ -18,7 +18,6 @@ import net.fabricmc.loader.api.FabricLoader; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.util.Identifier; public class CarpetServer // static for now - easier to handle all around the code, its one anyways { @@ -28,7 +27,6 @@ public class CarpetServer // static for now - easier to handle all around the co public static CarpetScriptServer scriptServer; public static SettingsManager settingsManager; public static final List extensions = new ArrayList<>(); - public static final Identifier CARPET_CHANNEL = new Identifier("carpet:info"); // Separate from onServerLoaded, because a server can be loaded multiple times in singleplayer public static void manageExtension(CarpetExtension extension) @@ -48,9 +46,6 @@ public class CarpetServer // static for now - easier to handle all around the co settingsManager = new SettingsManager(CarpetSettings.carpetVersion, "carpet", "Carpet Mod"); settingsManager.parseSettingsClass(CarpetSettings.class); extensions.forEach(CarpetExtension::onGameStarted); - CarpetServer.settingsManager.addRuleObserver((source, parsedRule, s) -> { - ServerNetworkHandler.sendUpdateToClient(parsedRule.name, parsedRule.getAsString(), source); - }); } public static void onServerLoaded(MinecraftServer server) @@ -66,6 +61,7 @@ public class CarpetServer // static for now - easier to handle all around the co scriptServer.loadAllWorldScripts(); MobAI.resetTrackers(); LoggerRegistry.initLoggers(); + //TickSpeed.reset(); } public static void tick(MinecraftServer server) @@ -108,31 +104,41 @@ public class CarpetServer // static for now - easier to handle all around the co public static void onPlayerLoggedIn(ServerPlayerEntity player) { + ServerNetworkHandler.onPlayerJoin(player); LoggerRegistry.playerConnected(player); extensions.forEach(e -> e.onPlayerLoggedIn(player)); - ServerNetworkHandler.onPlayerJoin(player); + } public static void onPlayerLoggedOut(ServerPlayerEntity player) { + ServerNetworkHandler.onPlayerLoggedOut(player); LoggerRegistry.playerDisconnected(player); extensions.forEach(e -> e.onPlayerLoggedOut(player)); } public static void onServerClosed(MinecraftServer server) { + ServerNetworkHandler.close(); currentCommandDispatcher = null; if (scriptServer != null) scriptServer.onClose(); - settingsManager.detachServer(); + LoggerRegistry.stopLoggers(); - TickSpeed.reset(); extensions.forEach(e -> e.onServerClosed(server)); minecraft_server = null; + disconnect(); } public static void registerExtensionLoggers() { extensions.forEach(CarpetExtension::registerLoggers); } + + public static void disconnect() + { + // this for whatever reason gets called multiple times even when joining; + TickSpeed.reset(); + settingsManager.detachServer(); + } } diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index 4913bb1f..a198b438 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -44,7 +44,7 @@ public class CarpetSettings private static class LanguageValidator extends Validator { @Override public String validate(ServerCommandSource source, ParsedRule currentRule, String newValue, String string) { - if (currentRule.get().equals(newValue)) + if (currentRule.get().equals(newValue) || source == null) { return newValue; } @@ -487,7 +487,7 @@ public class CarpetSettings { @Override public Integer validate(ServerCommandSource source, ParsedRule currentRule, Integer newValue, String string) { - if (currentRule.get().equals(newValue)) + if (currentRule.get().equals(newValue) || source == null) { return newValue; } @@ -538,6 +538,7 @@ public class CarpetSettings } } @Override public Integer validate(ServerCommandSource source, ParsedRule currentRule, Integer newValue, String string) { + if (source == null) return newValue; if (newValue < 0 || newValue > 32) { Messenger.m(source, "r spawn chunk size has to be between 0 and 32"); diff --git a/src/main/java/carpet/commands/TickCommand.java b/src/main/java/carpet/commands/TickCommand.java index cc7dc38c..0b559f38 100644 --- a/src/main/java/carpet/commands/TickCommand.java +++ b/src/main/java/carpet/commands/TickCommand.java @@ -67,7 +67,7 @@ public class TickCommand private static int setTps(ServerCommandSource source, float tps) { - TickSpeed.tickrate(tps); + TickSpeed.tickrate(tps, true); queryTps(source); return (int)tps; } diff --git a/src/main/java/carpet/fakes/CustomPayloadC2SPacketInterface.java b/src/main/java/carpet/fakes/CustomPayloadC2SPacketInterface.java new file mode 100644 index 00000000..baa636e7 --- /dev/null +++ b/src/main/java/carpet/fakes/CustomPayloadC2SPacketInterface.java @@ -0,0 +1,10 @@ +package carpet.fakes; + +import net.minecraft.util.Identifier; +import net.minecraft.util.PacketByteBuf; + +public interface CustomPayloadC2SPacketInterface +{ + Identifier getPacketChannel(); + PacketByteBuf getPacketData(); +} diff --git a/src/main/java/carpet/helpers/ClientNetworkHandler.java b/src/main/java/carpet/helpers/ClientNetworkHandler.java deleted file mode 100644 index 5e15e6ba..00000000 --- a/src/main/java/carpet/helpers/ClientNetworkHandler.java +++ /dev/null @@ -1,59 +0,0 @@ -package carpet.helpers; - -import carpet.CarpetServer; -import carpet.CarpetSettings; -import carpet.settings.ParsedRule; -import net.minecraft.client.MinecraftClient; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.Tag; -import net.minecraft.util.Identifier; -import net.minecraft.util.PacketByteBuf; - -public class ClientNetworkHandler -{ - public static void handleData(Identifier channel, PacketByteBuf data) - { - if (CarpetServer.CARPET_CHANNEL.equals(channel) && data != null) - { - int id = data.readVarInt(); - - if (id == 1) - setOnJoinInfo(data); - else if (id == 2) - updateRule(data); - else if (id == 3) - updateTickRateClient(data); - } - } - - private static void setOnJoinInfo(PacketByteBuf data) - { - CompoundTag compound = data.readCompoundTag(); - if (compound == null) return; - - TickSpeed.tickrate(compound.getFloat("Tickrate")); - - ListTag rulesList = compound.getList("rules", 10); - for (Tag tag : rulesList) - { - CompoundTag ruleNBT = (CompoundTag) tag; - String rule = ruleNBT.getString("rule"); - String value = ruleNBT.getString("value"); - CarpetServer.settingsManager.getRule(rule).set(null, value); - } - } - - private static void updateRule(PacketByteBuf data) - { - String rule = data.readString(); - String newValue = data.readString(); - CarpetServer.settingsManager.getRule(rule).set(null, newValue); - } - - private static void updateTickRateClient(PacketByteBuf data) - { - float rate = data.readFloat(); - TickSpeed.tickrate(rate); - } -} diff --git a/src/main/java/carpet/helpers/ServerNetworkHandler.java b/src/main/java/carpet/helpers/ServerNetworkHandler.java deleted file mode 100644 index 77b393d3..00000000 --- a/src/main/java/carpet/helpers/ServerNetworkHandler.java +++ /dev/null @@ -1,66 +0,0 @@ -package carpet.helpers; - -import carpet.CarpetServer; -import carpet.CarpetSettings; -import carpet.settings.ParsedRule; -import io.netty.buffer.Unpooled; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.util.PacketByteBuf; - -public class ServerNetworkHandler -{ - public static void onPlayerJoin(ServerPlayerEntity playerEntity) - { - CompoundTag data = new CompoundTag(); - - data.putFloat("Tickrate", TickSpeed.tickrate); - - ListTag rulesList = new ListTag(); - for (ParsedRule rule : CarpetServer.settingsManager.getRules()) - { - CompoundTag ruleNBT = new CompoundTag(); - - ruleNBT.putString("rule" ,rule.name); - ruleNBT.putString("value", rule.getAsString()); - ruleNBT.putString("default", rule.defaultAsString); - rulesList.add(ruleNBT); - } - data.put("rules", rulesList); - PacketByteBuf packetBuf = new PacketByteBuf(Unpooled.buffer()); - packetBuf.writeVarInt(1); - packetBuf.writeCompoundTag(data); - playerEntity.networkHandler.sendPacket(new CustomPayloadS2CPacket(CarpetServer.CARPET_CHANNEL, packetBuf)); - } - - public static void sendUpdateToClient(String rule, String newValue, ServerCommandSource source) - { - PacketByteBuf data = new PacketByteBuf(Unpooled.buffer()); - - data.writeVarInt(2); - data.writeString(rule); - data.writeString(newValue); - for (ServerPlayerEntity player : source.getMinecraftServer().getPlayerManager().getPlayerList()) - { - player.networkHandler.sendPacket(new CustomPayloadS2CPacket(CarpetServer.CARPET_CHANNEL, data)); - } - } - - public static void sendTickRateToPlayers(float rate) - { - PacketByteBuf data = new PacketByteBuf(Unpooled.buffer()); - data.writeVarInt(3); - data.writeFloat(rate); - if (CarpetServer.minecraft_server != null) - { - for (ServerPlayerEntity player : CarpetServer.minecraft_server.getPlayerManager().getPlayerList()) - { - player.networkHandler.sendPacket(new CustomPayloadS2CPacket(CarpetServer.CARPET_CHANNEL, data)); - } - } - } -} diff --git a/src/main/java/carpet/helpers/TickSpeed.java b/src/main/java/carpet/helpers/TickSpeed.java index 1c1c4d2b..091c7c73 100644 --- a/src/main/java/carpet/helpers/TickSpeed.java +++ b/src/main/java/carpet/helpers/TickSpeed.java @@ -5,6 +5,7 @@ import java.util.Map; import java.util.function.BiConsumer; import carpet.CarpetServer; +import carpet.network.ServerNetworkHandler; import carpet.utils.Messenger; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.server.MinecraftServer; @@ -177,7 +178,7 @@ public class TickSpeed } } - public static void tickrate(float rate) + public static void tickrate(float rate, boolean update) { tickrate = rate; long mspt = (long)(1000.0 / tickrate); @@ -189,7 +190,7 @@ public class TickSpeed TickSpeed.mspt = (float)mspt; - notifyTickrateListeners("carpet"); + if (update) notifyTickrateListeners("carpet"); } private static void tickrateChanged(String modId, float rate) @@ -221,7 +222,7 @@ public class TickSpeed } } } - ServerNetworkHandler.sendTickRateToPlayers(tickrate); + ServerNetworkHandler.updateTickSpeedToConnectedPlayers(); } public static BiConsumer addTickrateListener(String modId, BiConsumer tickrateListener) diff --git a/src/main/java/carpet/mixins/ClientPlayNetworkHandlerMixin.java b/src/main/java/carpet/mixins/ClientPlayNetworkHandlerMixin.java index 0e8fafcf..362828ea 100644 --- a/src/main/java/carpet/mixins/ClientPlayNetworkHandlerMixin.java +++ b/src/main/java/carpet/mixins/ClientPlayNetworkHandlerMixin.java @@ -1,44 +1,43 @@ package carpet.mixins; -import carpet.CarpetServer; -import carpet.helpers.ClientNetworkHandler; +import carpet.network.CarpetClient; +import carpet.network.ClientNetworkHandler; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.Tag; import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket; -import net.minecraft.util.Identifier; -import net.minecraft.util.PacketByteBuf; +import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket; +import net.minecraft.text.Text; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @Mixin(ClientPlayNetworkHandler.class) public abstract class ClientPlayNetworkHandlerMixin { - @Inject(method = "onCustomPayload", at = @At(value = "CONSTANT", args = "stringValue=Unknown custom packed identifier: {}"), cancellable = true, locals = LocalCapture.CAPTURE_FAILSOFT, require = 0) - private void onCustomPayloadNotFound(CustomPayloadS2CPacket packet, CallbackInfo ci, Identifier id, PacketByteBuf buf) - { - if (CarpetServer.CARPET_CHANNEL.equals(id)) - { - if (buf.refCnt() > 0) - { - buf.release(); - } - - ci.cancel(); - } - } - + @Shadow private MinecraftClient client; + @Inject(method = "onCustomPayload", at = @At("HEAD"), cancellable = true) private void onOnCustomPayload(CustomPayloadS2CPacket packet, CallbackInfo ci) { - Identifier channel = packet.getChannel(); - PacketByteBuf buf = packet.getData(); - ClientNetworkHandler.handleData(channel, buf); - ci.cancel(); + if (CarpetClient.CARPET_CHANNEL.equals(packet.getChannel())) + { + ClientNetworkHandler.handleData(packet.getData(), client.player); + ci.cancel(); + } } + + @Inject(method = "onGameJoin", at = @At("RETURN")) + private void onGameJoined(GameJoinS2CPacket packet, CallbackInfo info) + { + CarpetClient.gameJoined(client.player); + } + + @Inject(method = "onDisconnected", at = @At("HEAD")) + private void onCMDisconnected(Text reason, CallbackInfo ci) + { + CarpetClient.disconnect(); + } + } diff --git a/src/main/java/carpet/mixins/ClientPlayerEntity_clientCommandMixin.java b/src/main/java/carpet/mixins/ClientPlayerEntity_clientCommandMixin.java index a0347524..16a41708 100644 --- a/src/main/java/carpet/mixins/ClientPlayerEntity_clientCommandMixin.java +++ b/src/main/java/carpet/mixins/ClientPlayerEntity_clientCommandMixin.java @@ -1,6 +1,7 @@ package carpet.mixins; import carpet.CarpetServer; +import carpet.network.CarpetClient; import net.minecraft.client.network.ClientPlayerEntity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -13,8 +14,10 @@ public class ClientPlayerEntity_clientCommandMixin @Inject(method = "sendChatMessage", at = @At("HEAD")) private void inspectMessage(String string, CallbackInfo ci) { - ClientPlayerEntity playerSource = (ClientPlayerEntity)(Object) this; - if (CarpetServer.minecraft_server == null) + if (CarpetServer.minecraft_server == null && !CarpetClient.isCarpet()) + { + ClientPlayerEntity playerSource = (ClientPlayerEntity)(Object) this; CarpetServer.settingsManager.inspectClientsideCommand(playerSource.getCommandSource(), string); + } } } diff --git a/src/main/java/carpet/mixins/CustomPayloadC2SPacketMixin.java b/src/main/java/carpet/mixins/CustomPayloadC2SPacketMixin.java new file mode 100644 index 00000000..0465c72e --- /dev/null +++ b/src/main/java/carpet/mixins/CustomPayloadC2SPacketMixin.java @@ -0,0 +1,27 @@ +package carpet.mixins; + +import carpet.fakes.CustomPayloadC2SPacketInterface; +import net.minecraft.network.packet.c2s.play.CustomPayloadC2SPacket; +import net.minecraft.util.Identifier; +import net.minecraft.util.PacketByteBuf; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(CustomPayloadC2SPacket.class) +public class CustomPayloadC2SPacketMixin implements CustomPayloadC2SPacketInterface +{ + @Shadow + private Identifier channel; + @Shadow + private PacketByteBuf data; + + @Override + public Identifier getPacketChannel() { + return channel; + } + + @Override + public PacketByteBuf getPacketData() { + return new PacketByteBuf(this.data.copy()); + } +} diff --git a/src/main/java/carpet/mixins/MinecraftClientMixin.java b/src/main/java/carpet/mixins/MinecraftClientMixin.java index 2598239a..c2c9be06 100644 --- a/src/main/java/carpet/mixins/MinecraftClientMixin.java +++ b/src/main/java/carpet/mixins/MinecraftClientMixin.java @@ -1,7 +1,9 @@ package carpet.mixins; import carpet.CarpetServer; +import carpet.network.CarpetClient; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Screen; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -18,4 +20,10 @@ public class MinecraftClientMixin //CM start game hook CarpetServer.onGameStarted(); } + + @Inject(method = "disconnect(Lnet/minecraft/client/gui/screen/Screen;)V", at = @At("HEAD")) + private void onCloseGame(Screen screen, CallbackInfo ci) + { + CarpetClient.disconnect(); + } } diff --git a/src/main/java/carpet/mixins/ServerPlayNetworkHandlerMixin.java b/src/main/java/carpet/mixins/ServerPlayNetworkHandlerMixin.java new file mode 100644 index 00000000..bec53d32 --- /dev/null +++ b/src/main/java/carpet/mixins/ServerPlayNetworkHandlerMixin.java @@ -0,0 +1,31 @@ +package carpet.mixins; + +import carpet.fakes.CustomPayloadC2SPacketInterface; +import carpet.network.CarpetClient; +import carpet.network.ServerNetworkHandler; +import net.minecraft.network.packet.c2s.play.CustomPayloadC2SPacket; +import net.minecraft.server.network.ServerPlayNetworkHandler; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.Identifier; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ServerPlayNetworkHandler.class) +public class ServerPlayNetworkHandlerMixin +{ + @Shadow public ServerPlayerEntity player; + + @Inject(method = "onCustomPayload", at = @At("HEAD"), cancellable = true) + private void onCustomCarpetPayload(CustomPayloadC2SPacket packet, CallbackInfo ci) + { + Identifier channel = ((CustomPayloadC2SPacketInterface) packet).getPacketChannel(); + if (CarpetClient.CARPET_CHANNEL.equals(channel)) + { + ServerNetworkHandler.handleData(((CustomPayloadC2SPacketInterface) packet).getPacketData(), player); + ci.cancel(); + } + } +} diff --git a/src/main/java/carpet/network/CarpetClient.java b/src/main/java/carpet/network/CarpetClient.java new file mode 100644 index 00000000..0846a9d0 --- /dev/null +++ b/src/main/java/carpet/network/CarpetClient.java @@ -0,0 +1,52 @@ +package carpet.network; + +import carpet.CarpetServer; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.util.Identifier; + +public class CarpetClient +{ + public static final Object sync = new Object(); + public static final int HI = 69; + public static final int HELLO = 420; + public static final int DATA = 1; + + private static ClientPlayerEntity clientPlayer = null; + private static boolean isServerCarpet = false; + public static String serverCarpetVersion; + public static final Identifier CARPET_CHANNEL = new Identifier("carpet:hello"); + + public static void gameJoined(ClientPlayerEntity player) + { + synchronized (sync) + { + clientPlayer = player; + // client didn't say hi back yet + if (isServerCarpet) + ClientNetworkHandler.respondHello(); + + } + } + + public static void disconnect() + { + isServerCarpet = false; + clientPlayer = null; + CarpetServer.disconnect(); + } + + public static void setCarpet() + { + isServerCarpet = true; + } + + public static ClientPlayerEntity getPlayer() + { + return clientPlayer; + } + + public static boolean isCarpet() + { + return isServerCarpet; + } +} diff --git a/src/main/java/carpet/network/ClientNetworkHandler.java b/src/main/java/carpet/network/ClientNetworkHandler.java new file mode 100644 index 00000000..68e2349a --- /dev/null +++ b/src/main/java/carpet/network/ClientNetworkHandler.java @@ -0,0 +1,93 @@ +package carpet.network; + +import carpet.CarpetServer; +import carpet.CarpetSettings; +import carpet.helpers.TickSpeed; +import carpet.settings.ParsedRule; +import io.netty.buffer.Unpooled; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.nbt.AbstractNumberTag; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.packet.c2s.play.CustomPayloadC2SPacket; +import net.minecraft.util.PacketByteBuf; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.BiConsumer; + +public class ClientNetworkHandler +{ + private static Map> dataHandlers = new HashMap>(){{ + put("Rules", (p, t) -> { + CompoundTag ruleset = (CompoundTag)t; + for (String ruleName: ruleset.getKeys()) + { + ParsedRule rule = CarpetServer.settingsManager.getRule(ruleName); + if (rule == null) + CarpetSettings.LOG.error("Received unknown rule: "+ruleName); + else + { + CompoundTag ruleNBT = (CompoundTag) ruleset.get(ruleName); + String value = ruleNBT.getString("Value"); + rule.set(null, value); + } + } + }); + put("TickRate", (p, t) -> TickSpeed.tickrate(((AbstractNumberTag)t).getFloat(), false)); + }}; + + + public static void handleData(PacketByteBuf data, ClientPlayerEntity player) + { + if (data != null) + { + int id = data.readVarInt(); + if (id == CarpetClient.HI) + onHi(data); + if (id == CarpetClient.DATA) + onSyncData(data, player); + } + } + + private static void onHi(PacketByteBuf data) + { + synchronized (CarpetClient.sync) + { + CarpetClient.setCarpet(); + CarpetClient.serverCarpetVersion = data.readString(64); + if (CarpetSettings.carpetVersion.equals(CarpetClient.serverCarpetVersion)) + { + CarpetSettings.LOG.info("Joined carpet server with matching carpet version"); + } + else + { + CarpetSettings.LOG.warn("Joined carpet server with another carpet version: "+CarpetClient.serverCarpetVersion); + } + if (CarpetClient.getPlayer() != null) + respondHello(); + + } + } + + public static void respondHello() + { + CarpetClient.getPlayer().networkHandler.sendPacket(new CustomPayloadC2SPacket( + CarpetClient.CARPET_CHANNEL, + (new PacketByteBuf(Unpooled.buffer())).writeVarInt(CarpetClient.HELLO).writeString(CarpetSettings.carpetVersion) + )); + } + + private static void onSyncData(PacketByteBuf data, ClientPlayerEntity player) + { + CompoundTag compound = data.readCompoundTag(); + if (compound == null) return; + for (String key: compound.getKeys()) + { + if (dataHandlers.containsKey(key)) + dataHandlers.get(key).accept(player, compound.get(key)); + else + CarpetSettings.LOG.error("Unknown carpet data: "+key); + } + } +} diff --git a/src/main/java/carpet/network/ServerNetworkHandler.java b/src/main/java/carpet/network/ServerNetworkHandler.java new file mode 100644 index 00000000..152fcc37 --- /dev/null +++ b/src/main/java/carpet/network/ServerNetworkHandler.java @@ -0,0 +1,123 @@ +package carpet.network; + +import carpet.CarpetServer; +import carpet.CarpetSettings; +import carpet.helpers.TickSpeed; +import carpet.settings.ParsedRule; +import io.netty.buffer.Unpooled; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.PacketByteBuf; + +import java.util.ArrayList; +import java.util.List; + +public class ServerNetworkHandler +{ + private static List carpetPlayers = new ArrayList<>(); + + public static void handleData(PacketByteBuf data, ServerPlayerEntity player) + { + if (data != null) + { + int id = data.readVarInt(); + if (id == CarpetClient.HELLO) + onHello(player, data); + } + } + public static void onPlayerJoin(ServerPlayerEntity playerEntity) + { + if (!playerEntity.networkHandler.connection.isLocal()) + { + playerEntity.networkHandler.sendPacket(new CustomPayloadS2CPacket( + CarpetClient.CARPET_CHANNEL, + (new PacketByteBuf(Unpooled.buffer())).writeVarInt(CarpetClient.HI).writeString(CarpetSettings.carpetVersion) + )); + } + } + + public static void onHello(ServerPlayerEntity playerEntity, PacketByteBuf packetData) + { + carpetPlayers.add(playerEntity); + String clientVersion = packetData.readString(64); + if (clientVersion.equals(CarpetSettings.carpetVersion)) + CarpetSettings.LOG.info("Player "+playerEntity.getName().getString()+" joined with a matching carpet client"); + else + CarpetSettings.LOG.warn("Player "+playerEntity.getName().getString()+" joined with another carpet version: "+clientVersion); + DataBuilder data = DataBuilder.create().withTickRate(); + CarpetServer.settingsManager.getRules().forEach(data::withRule); + playerEntity.networkHandler.sendPacket(new CustomPayloadS2CPacket(CarpetClient.CARPET_CHANNEL, data.build() )); + } + + public static void updateRuleWithConnectedClients(ParsedRule rule) + { + for (ServerPlayerEntity player : carpetPlayers) + { + player.networkHandler.sendPacket(new CustomPayloadS2CPacket( + CarpetClient.CARPET_CHANNEL, + DataBuilder.create().withRule(rule).build() + )); + } + } + + public static void updateTickSpeedToConnectedPlayers() + { + for (ServerPlayerEntity player : carpetPlayers) + { + player.networkHandler.sendPacket(new CustomPayloadS2CPacket( + CarpetClient.CARPET_CHANNEL, + DataBuilder.create().withTickRate().build() + )); + } + } + + public static void onPlayerLoggedOut(ServerPlayerEntity player) + { + if (!player.networkHandler.connection.isLocal()) + carpetPlayers.remove(player); + } + + public static void close() + { + carpetPlayers.clear(); + } + + private static class DataBuilder + { + private CompoundTag tag; + private static DataBuilder create() + { + return new DataBuilder(); + } + private DataBuilder() + { + tag = new CompoundTag(); + } + private DataBuilder withTickRate() + { + tag.putFloat("TickRate", TickSpeed.tickrate); + return this; + } + private DataBuilder withRule(ParsedRule rule) + { + CompoundTag rules = (CompoundTag) tag.get("Rules"); + if (rules == null) + { + rules = new CompoundTag(); + tag.put("Rules", rules); + } + CompoundTag ruleNBT = new CompoundTag(); + ruleNBT.putString("Value", rule.getAsString()); + rules.put(rule.name, ruleNBT); + return this; + } + private PacketByteBuf build() + { + PacketByteBuf packetBuf = new PacketByteBuf(Unpooled.buffer()); + packetBuf.writeVarInt(CarpetClient.DATA); + packetBuf.writeCompoundTag(tag); + return packetBuf; + } + } +} diff --git a/src/main/java/carpet/settings/SettingsManager.java b/src/main/java/carpet/settings/SettingsManager.java index 93aac4df..5765f422 100644 --- a/src/main/java/carpet/settings/SettingsManager.java +++ b/src/main/java/carpet/settings/SettingsManager.java @@ -2,6 +2,7 @@ package carpet.settings; import carpet.CarpetServer; import carpet.CarpetSettings; +import carpet.network.ServerNetworkHandler; import carpet.utils.Translations; import carpet.utils.Messenger; import com.google.common.collect.ImmutableList; @@ -80,7 +81,7 @@ public class SettingsManager public void detachServer() { - for (ParsedRule rule : rules.values()) rule.resetToDefault(server.getCommandSource()); + for (ParsedRule rule : rules.values()) rule.resetToDefault(null); server = null; } @@ -103,6 +104,7 @@ public class SettingsManager void notifyRuleChanged(ServerCommandSource source, ParsedRule rule, String userTypedValue) { observers.forEach(observer -> observer.accept(source, rule, userTypedValue)); + ServerNetworkHandler.updateRuleWithConnectedClients(rule); } public Iterable getCategories() @@ -584,8 +586,6 @@ public class SettingsManager rules.get(setting).set(source, strOption); } } - - } } } diff --git a/src/main/java/carpet/settings/Validator.java b/src/main/java/carpet/settings/Validator.java index 8b561ff6..3f48fff0 100644 --- a/src/main/java/carpet/settings/Validator.java +++ b/src/main/java/carpet/settings/Validator.java @@ -22,7 +22,7 @@ public abstract class Validator @Override public T validate(ServerCommandSource source, ParsedRule currentRule, T newValue, String string) { - if (CarpetServer.settingsManager != null) + if (CarpetServer.settingsManager != null && source != null) CarpetServer.settingsManager.notifyPlayersCommandsChanged(); return newValue; } diff --git a/src/main/java/carpet/utils/Messenger.java b/src/main/java/carpet/utils/Messenger.java index 78e7fddc..7aa4f7b5 100644 --- a/src/main/java/carpet/utils/Messenger.java +++ b/src/main/java/carpet/utils/Messenger.java @@ -231,7 +231,8 @@ public class Messenger //message source public static void m(ServerCommandSource source, Object ... fields) { - source.sendFeedback(Messenger.c(fields),source.getMinecraftServer() != null && source.getMinecraftServer().getWorld(DimensionType.OVERWORLD) != null); + if (source != null) + source.sendFeedback(Messenger.c(fields),source.getMinecraftServer() != null && source.getMinecraftServer().getWorld(DimensionType.OVERWORLD) != null); } public static void m(PlayerEntity player, Object ... fields) { diff --git a/src/main/resources/carpet.mixins.json b/src/main/resources/carpet.mixins.json index 041dbaaa..247b24d1 100644 --- a/src/main/resources/carpet.mixins.json +++ b/src/main/resources/carpet.mixins.json @@ -6,6 +6,9 @@ "mixins": [ "CommandManagerMixin", + "ServerPlayNetworkHandlerMixin", + "CustomPayloadC2SPacketMixin", + "FillCommandMixin", "CloneCommandMixin", "SetBlockCommandMixin", From cf18aa3fcfa29caf18ffd7eeed2779f779c56fe5 Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 28 May 2020 09:40:50 -0300 Subject: [PATCH 149/198] mod compat --- src/main/java/carpet/helpers/TickSpeed.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/carpet/helpers/TickSpeed.java b/src/main/java/carpet/helpers/TickSpeed.java index 091c7c73..dd642112 100644 --- a/src/main/java/carpet/helpers/TickSpeed.java +++ b/src/main/java/carpet/helpers/TickSpeed.java @@ -177,7 +177,8 @@ public class TickSpeed } } } - + //unused - mod compat reasons + public static void tickrate(float rate) {tickrate(rate, true);} public static void tickrate(float rate, boolean update) { tickrate = rate; From cfe1b7d837179318d4a1a7c133fe041e2429f7ca Mon Sep 17 00:00:00 2001 From: gnembon Date: Fri, 29 May 2020 14:05:37 -0300 Subject: [PATCH 150/198] docs on time --- docs/scarpet/language/SystemFunctions.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/scarpet/language/SystemFunctions.md b/docs/scarpet/language/SystemFunctions.md index 7c506921..a1efa6d6 100644 --- a/docs/scarpet/language/SystemFunctions.md +++ b/docs/scarpet/language/SystemFunctions.md @@ -263,8 +263,11 @@ sleep(50) ### `time()` -Returns the number of milliseconds since 'some point', like Java's `System.nanoTime()`. -It returns a float, which has 1 microsecond precision (0.001 ms) +Returns the number of milliseconds since 'some point', like Java's `System.nanoTime()`, which varies from system to +system and from Java to Java. This measure should NOT be used to determine the current (date)time, but to measure +durations of things. +it returns a float with time in milliseconds (ms) for convenience and microsecond (μs) resolution for sanity. +
 start_time = time();

From 7c0a377d711ebc1861aa9c319f6effdbb476b44a Mon Sep 17 00:00:00 2001
From: gnembon 
Date: Fri, 29 May 2020 14:06:32 -0300
Subject: [PATCH 151/198] shapes renderer WIP

---
 .../carpet/script/utils/ShapesRenderer.java   | 53 +++++++++++++++++++
 1 file changed, 53 insertions(+)
 create mode 100644 src/main/java/carpet/script/utils/ShapesRenderer.java

diff --git a/src/main/java/carpet/script/utils/ShapesRenderer.java b/src/main/java/carpet/script/utils/ShapesRenderer.java
new file mode 100644
index 00000000..528be080
--- /dev/null
+++ b/src/main/java/carpet/script/utils/ShapesRenderer.java
@@ -0,0 +1,53 @@
+package carpet.script.utils;
+
+import net.minecraft.client.render.VertexConsumer;
+import net.minecraft.client.render.VertexConsumerProvider;
+import net.minecraft.client.util.math.MatrixStack;
+import net.minecraft.util.math.Vec3d;
+
+import java.util.List;
+
+public class ShapesRenderer
+{
+    List shapes;
+
+    void render(MatrixStack matrices, VertexConsumerProvider vertexConsumers, double cameraX, double cameraY, double cameraZ){
+
+    }
+    void addShape() {}
+
+
+    public abstract static class ExpiringShape
+    {
+        protected int r;
+        protected int g;
+        protected int b;
+        protected int a;
+        protected int expiryTick = 0;
+        public abstract void render(MatrixStack matrix, VertexConsumer vertexConsumer);
+        public ExpiringShape expiresIn(int ticks)
+        {
+            expiryTick = ticks;
+            return this;
+        }
+
+    }
+
+    public static class SolidLine extends ExpiringShape
+    {
+        public SolidLine(Vec3d from, Vec3d to, int r, int g, int b, int a)
+        {
+            this.r = r;
+            this.g = g;
+            this.b = b;
+            this.a = a;
+
+        }
+        @Override
+        public void render(MatrixStack matrix, VertexConsumer vertexConsumer)
+        {
+
+        }
+    }
+
+}

From f6fb8e58991f9468a4a849d0053b34df650dece7 Mon Sep 17 00:00:00 2001
From: gnembon 
Date: Sun, 31 May 2020 01:06:41 -0300
Subject: [PATCH 152/198] ++ got eaten

---
 src/main/java/carpet/settings/ParsedRule.java | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/main/java/carpet/settings/ParsedRule.java b/src/main/java/carpet/settings/ParsedRule.java
index e2acdd25..f25b0a38 100644
--- a/src/main/java/carpet/settings/ParsedRule.java
+++ b/src/main/java/carpet/settings/ParsedRule.java
@@ -253,6 +253,7 @@ public final class ParsedRule implements Comparable {
         while (Translations.hasTranslation(keyBase+i))
         {
             extras.add(Translations.tr(keyBase+i));
+            i++;
         }
         return (extras.isEmpty()) ? extraInfo : extras;
     }

From 47452b5b12cb2e0b23d5304785d8631fe85e3fe9 Mon Sep 17 00:00:00 2001
From: gnembon 
Date: Sun, 31 May 2020 01:57:04 -0300
Subject: [PATCH 153/198] added marker lines and boxes with client synchro
 fixes.

---
 docs/scarpet/Full.md                          |   2 +-
 docs/scarpet/api/Auxiliary.md                 |  28 +-
 .../DebugRenderer_scarpetRenderMixin.java     |  38 +++
 .../java/carpet/network/CarpetClient.java     |   2 +
 .../carpet/network/ClientNetworkHandler.java  |  12 +
 .../carpet/network/ServerNetworkHandler.java  |  58 +++-
 .../java/carpet/script/CarpetExpression.java  | 271 +++++++++-------
 src/main/java/carpet/script/Expression.java   |   6 +
 .../carpet/script/utils/ShapeDispatcher.java  | 289 ++++++++++++++++++
 .../carpet/script/utils/ShapesRenderer.java   | 170 +++++++++--
 .../assets/carpet/scripts/overlay.sc          |  45 ++-
 src/main/resources/carpet.mixins.json         |   4 +-
 12 files changed, 752 insertions(+), 173 deletions(-)
 create mode 100644 src/main/java/carpet/mixins/DebugRenderer_scarpetRenderMixin.java
 create mode 100644 src/main/java/carpet/script/utils/ShapeDispatcher.java

diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md
index b8c7ae9c..99523a4f 100644
--- a/docs/scarpet/Full.md
+++ b/docs/scarpet/Full.md
@@ -1513,7 +1513,7 @@ range(5,10)  => [5, 6, 7, 8, 9]
 range(20, 10, -2)  => [20, 18, 16, 14, 12]
 
-### `element(list, index)(deprecated)` +### `element(list, index)` (deprecated) Legacy support for older method that worked only on lists. Please use `get(...)` for equivalent support, or `.` operator. Also previous unique behaviours with `put` on lists has been removed to support all type of diff --git a/docs/scarpet/api/Auxiliary.md b/docs/scarpet/api/Auxiliary.md index a3ea3296..7d9da627 100644 --- a/docs/scarpet/api/Auxiliary.md +++ b/docs/scarpet/api/Auxiliary.md @@ -14,24 +14,42 @@ and `voice`. `pos` can be either a block, triple of coords, or a list of thee nu ## Particles -### `particle(name, pos, count?. spread?, speed?, playername?)` +### `particle(name, pos, count?. spread?, speed?, player?)` Renders a cloud of particles `name` centered around `pos` position, by default `count` 10 of them, default `speed` of 0, and to all players nearby, but these options can be changed via optional arguments. Follow vanilla `/particle` command on details on those options. Valid particle names are for example `'angry_villager', 'item diamond', 'block stone', 'dust 0.8 0.1 0.1 4'`. -### `particle_line(name, pos, pos2, density?)` +### `particle_line(name, pos, pos2, density?, player?)` Renders a line of particles from point `pos` to `pos2` with supplied density (defaults to 1), which indicates how far -apart you would want particles to appear, so `0.1` means one every 10cm. +apart you would want particles to appear, so `0.1` means one every 10cm. If a player (or player name) is supplied, only +that player will receive particles. -### `particle_rect(name, pos, pos2, density?)` -Renders a cuboid of particles between points `pos` and `pos2` with supplied density. +### `particle_box(name, pos, pos2, density?, player?)` +### `particle_rect` (deprecated) + +Renders a cuboid of particles between points `pos` and `pos2` with supplied density. If a player (or player name) is +supplied, only that player will receive particles. ## Markers +### `marker_box(from, to, duration?, color?, player?)` + +Draws a box with `from` and `to` corners in the box. The boxes will dissipate after `duration` ticks (defaults to 10). +The color is an integer that indicate red, green, blue and alpha components in the form of `0xRRGGBBAA`, with the +default of `-1`, so white opaque, or `0xFFFFFFFF`. If player is specified, only displays for that player, otherwise all +players will see them. `marker_box` requires proper client synchronization to display these, and on non-supported +clients, the box will be replaced with close matching dust particles, so using of `marker_box` is safe to use for +scripts regardless who is targeted. The only consideration is that with vanilla clients, duration of particles cannot +be controlled, and last whatever the original particles do. + +### `marker_line(from, to, duration?, color?, player?)` + +Draws a marker line on client's screen. Uses similar setup as `marker_box`. + ### `create_marker(text, pos, rotation?, block?)` Spawns a (permanent) marker entity with text or block at position. Returns that entity for further manipulations. diff --git a/src/main/java/carpet/mixins/DebugRenderer_scarpetRenderMixin.java b/src/main/java/carpet/mixins/DebugRenderer_scarpetRenderMixin.java new file mode 100644 index 00000000..a57a3b26 --- /dev/null +++ b/src/main/java/carpet/mixins/DebugRenderer_scarpetRenderMixin.java @@ -0,0 +1,38 @@ +package carpet.mixins; + +import carpet.network.CarpetClient; +import carpet.script.utils.ShapesRenderer; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.debug.DebugRenderer; +import net.minecraft.client.util.math.MatrixStack; +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.CallbackInfo; + +@Mixin(DebugRenderer.class) +public class DebugRenderer_scarpetRenderMixin +{ + private ShapesRenderer shapes; + + @Inject(method = "", at = @At("RETURN")) + private void addRenderers(MinecraftClient client, CallbackInfo ci) + { + shapes = new ShapesRenderer(client); + CarpetClient.shapes = shapes; + } + + @Inject(method = "reset", at = @At("HEAD")) + private void resetScarpetRenderes(CallbackInfo ci) + { + shapes.reset(); + } + + @Inject(method = "render", at = @At("HEAD")) + private void renderScarpetThings(MatrixStack matrices, VertexConsumerProvider.Immediate vertexConsumers, double cameraX, double cameraY, double cameraZ, CallbackInfo ci) + { + shapes.render(matrices, vertexConsumers, cameraX, cameraY, cameraZ); + } + +} diff --git a/src/main/java/carpet/network/CarpetClient.java b/src/main/java/carpet/network/CarpetClient.java index 0846a9d0..7010eb31 100644 --- a/src/main/java/carpet/network/CarpetClient.java +++ b/src/main/java/carpet/network/CarpetClient.java @@ -1,6 +1,7 @@ package carpet.network; import carpet.CarpetServer; +import carpet.script.utils.ShapesRenderer; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.util.Identifier; @@ -10,6 +11,7 @@ public class CarpetClient public static final int HI = 69; public static final int HELLO = 420; public static final int DATA = 1; + public static ShapesRenderer shapes = null; private static ClientPlayerEntity clientPlayer = null; private static boolean isServerCarpet = false; diff --git a/src/main/java/carpet/network/ClientNetworkHandler.java b/src/main/java/carpet/network/ClientNetworkHandler.java index 68e2349a..7c1336c3 100644 --- a/src/main/java/carpet/network/ClientNetworkHandler.java +++ b/src/main/java/carpet/network/ClientNetworkHandler.java @@ -11,6 +11,7 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; import net.minecraft.network.packet.c2s.play.CustomPayloadC2SPacket; import net.minecraft.util.PacketByteBuf; +import net.minecraft.world.dimension.DimensionType; import java.util.HashMap; import java.util.Map; @@ -35,6 +36,17 @@ public class ClientNetworkHandler } }); put("TickRate", (p, t) -> TickSpeed.tickrate(((AbstractNumberTag)t).getFloat(), false)); + put("renderShape", (p, t) -> { + if (CarpetClient.shapes != null) + { + CompoundTag boxData = (CompoundTag)t; + CarpetClient.shapes.addShape( + boxData.getString("type"), + DimensionType.byRawId(boxData.getInt("dim")), + boxData + ); + } + }); }}; diff --git a/src/main/java/carpet/network/ServerNetworkHandler.java b/src/main/java/carpet/network/ServerNetworkHandler.java index 152fcc37..b609dd7d 100644 --- a/src/main/java/carpet/network/ServerNetworkHandler.java +++ b/src/main/java/carpet/network/ServerNetworkHandler.java @@ -6,16 +6,18 @@ import carpet.helpers.TickSpeed; import carpet.settings.ParsedRule; import io.netty.buffer.Unpooled; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.PacketByteBuf; -import java.util.ArrayList; -import java.util.List; +import java.util.HashSet; +import java.util.Set; public class ServerNetworkHandler { - private static List carpetPlayers = new ArrayList<>(); + public static Set remoteCarpetPlayers = new HashSet<>(); + public static Set validCarpetPlayers = new HashSet<>(); public static void handleData(PacketByteBuf data, ServerPlayerEntity player) { @@ -35,11 +37,17 @@ public class ServerNetworkHandler (new PacketByteBuf(Unpooled.buffer())).writeVarInt(CarpetClient.HI).writeString(CarpetSettings.carpetVersion) )); } + else + { + validCarpetPlayers.add(playerEntity); + } + } public static void onHello(ServerPlayerEntity playerEntity, PacketByteBuf packetData) { - carpetPlayers.add(playerEntity); + remoteCarpetPlayers.add(playerEntity); + validCarpetPlayers.add(playerEntity); String clientVersion = packetData.readString(64); if (clientVersion.equals(CarpetSettings.carpetVersion)) CarpetSettings.LOG.info("Player "+playerEntity.getName().getString()+" joined with a matching carpet client"); @@ -52,7 +60,7 @@ public class ServerNetworkHandler public static void updateRuleWithConnectedClients(ParsedRule rule) { - for (ServerPlayerEntity player : carpetPlayers) + for (ServerPlayerEntity player : remoteCarpetPlayers) { player.networkHandler.sendPacket(new CustomPayloadS2CPacket( CarpetClient.CARPET_CHANNEL, @@ -63,7 +71,7 @@ public class ServerNetworkHandler public static void updateTickSpeedToConnectedPlayers() { - for (ServerPlayerEntity player : carpetPlayers) + for (ServerPlayerEntity player : remoteCarpetPlayers) { player.networkHandler.sendPacket(new CustomPayloadS2CPacket( CarpetClient.CARPET_CHANNEL, @@ -72,15 +80,40 @@ public class ServerNetworkHandler } } + public static void sendCustomCommand(String command, Tag data) + { + for (ServerPlayerEntity player : validCarpetPlayers) + { + player.networkHandler.sendPacket(new CustomPayloadS2CPacket( + CarpetClient.CARPET_CHANNEL, + DataBuilder.create().withCustomNbt(command, data).build() + )); + } + } + + public static void sendCustomCommand(ServerPlayerEntity player, String command, Tag data) + { + if (validCarpetPlayers.contains(player)) + { + player.networkHandler.sendPacket(new CustomPayloadS2CPacket( + CarpetClient.CARPET_CHANNEL, + DataBuilder.create().withCustomNbt(command, data).build() + )); + } + } + + public static void onPlayerLoggedOut(ServerPlayerEntity player) { + validCarpetPlayers.remove(player); if (!player.networkHandler.connection.isLocal()) - carpetPlayers.remove(player); + remoteCarpetPlayers.remove(player); } public static void close() { - carpetPlayers.clear(); + remoteCarpetPlayers.clear(); + validCarpetPlayers.clear(); } private static class DataBuilder @@ -112,6 +145,13 @@ public class ServerNetworkHandler rules.put(rule.name, ruleNBT); return this; } + + public DataBuilder withCustomNbt(String key, Tag value) + { + tag.put(key, value); + return this; + } + private PacketByteBuf build() { PacketByteBuf packetBuf = new PacketByteBuf(Unpooled.buffer()); @@ -119,5 +159,7 @@ public class ServerNetworkHandler packetBuf.writeCompoundTag(tag); return packetBuf; } + + } } diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index d1329558..42bad5a4 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -21,6 +21,7 @@ import carpet.script.exception.ContinueStatement; import carpet.script.exception.ExitStatement; import carpet.script.exception.ExpressionException; import carpet.script.exception.InternalExpressionException; +import carpet.script.utils.ShapeDispatcher; import carpet.script.value.BlockValue; import carpet.script.value.EntityValue; import carpet.script.value.FormattedTextValue; @@ -63,7 +64,6 @@ import net.minecraft.item.TridentItem; import net.minecraft.network.packet.s2c.play.ContainerSlotUpdateS2CPacket; import net.minecraft.network.packet.s2c.play.PlaySoundIdS2CPacket; import net.minecraft.command.arguments.ItemStackArgument; -import net.minecraft.command.arguments.ParticleArgumentType; import net.minecraft.enchantment.Enchantments; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; @@ -148,7 +148,6 @@ import static carpet.script.utils.WorldTools.canHasChunk; import static java.lang.Math.abs; import static java.lang.Math.max; import static java.lang.Math.min; -import static java.lang.Math.sqrt; public class CarpetExpression { @@ -261,90 +260,6 @@ public class CarpetExpression return bs; } - private static final Map particleCache = new HashMap<>(); - private ParticleEffect getParticleData(String name) - { - ParticleEffect particle = particleCache.get(name); - if (particle != null) - return particle; - try - { - particle = ParticleArgumentType.readParameters(new StringReader(name)); - } - catch (CommandSyntaxException e) - { - throw new InternalExpressionException("No such particle: "+name); - } - particleCache.put(name, particle); - return particle; - } - - - private boolean isStraight(Vec3d from, Vec3d to, double density) - { - if ( (from.x == to.x && from.y == to.y) || (from.x == to.x && from.z == to.z) || (from.y == to.y && from.z == to.z)) - return from.distanceTo(to) / density > 20; - return false; - } - - private int drawOptimizedParticleLine(ServerWorld world, ParticleEffect particle, Vec3d from, Vec3d to, double density) - { - double distance = from.distanceTo(to); - int particles = (int)(distance/density); - Vec3d towards = to.subtract(from); - int parts = 0; - for (PlayerEntity player : world.getPlayers()) - { - world.spawnParticles((ServerPlayerEntity)player, particle, true, - (towards.x)/2+from.x, (towards.y)/2+from.y, (towards.z)/2+from.z, particles/3, - towards.x/6, towards.y/6, towards.z/6, 0.0); - world.spawnParticles((ServerPlayerEntity)player, particle, true, - from.x, from.y, from.z,1,0.0,0.0,0.0,0.0); - world.spawnParticles((ServerPlayerEntity)player, particle, true, - to.x, to.y, to.z,1,0.0,0.0,0.0,0.0); - parts += particles/3+2; - } - int divider = 6; - while (particles/divider > 1) - { - int center = (divider*2)/3; - int dev = 2*divider; - for (PlayerEntity player : world.getPlayers()) - { - world.spawnParticles((ServerPlayerEntity)player, particle, true, - (towards.x)/center+from.x, (towards.y)/center+from.y, (towards.z)/center+from.z, particles/divider, - towards.x/dev, towards.y/dev, towards.z/dev, 0.0); - world.spawnParticles((ServerPlayerEntity)player, particle, true, - (towards.x)*(1.0-1.0/center)+from.x, (towards.y)*(1.0-1.0/center)+from.y, (towards.z)*(1.0-1.0/center)+from.z, particles/divider, - towards.x/dev, towards.y/dev, towards.z/dev, 0.0); - } - parts += 2*particles/divider; - divider = 2*divider; - } - return parts; - } - - private int drawParticleLine(ServerWorld world, ParticleEffect particle, Vec3d from, Vec3d to, double density) - { - if (isStraight(from, to, density)) return drawOptimizedParticleLine(world, particle, from, to, density); - double lineLengthSq = from.squaredDistanceTo(to); - if (lineLengthSq == 0) return 0; - Vec3d incvec = to.subtract(from).multiply(2*density/sqrt(lineLengthSq)); - int pcount = 0; - for (Vec3d delta = new Vec3d(0.0,0.0,0.0); - delta.lengthSquared() offset)? NumericValue.asNumber(lv.get(offset).evalValue(c)).getDouble():1.0; - if (density <= 0) + double density = 1.0; + ServerPlayerEntity player = null; + if (lv.size() > pos2.offset+0 ) { - throw new InternalExpressionException("Particle density should be positive"); + density = NumericValue.asNumber(lv.get(pos2.offset+0).evalValue(c)).getDouble(); + if (density <= 0) + { + throw new InternalExpressionException("Particle density should be positive"); + } + if (lv.size() > pos2.offset+1) + { + Value playerValue = lv.get(pos2.offset+1).evalValue(c); + if (playerValue instanceof EntityValue) + { + Entity e = ((EntityValue) playerValue).getEntity(); + if (!(e instanceof ServerPlayerEntity)) throw new InternalExpressionException("'particle_line' player argument has to be a player"); + player = (ServerPlayerEntity) e; + } + else + { + player = cc.s.getMinecraftServer().getPlayerManager().getPlayer(playerValue.getString()); + } + } } - Value retval = new NumericValue(drawParticleLine(world, particle, pos1.vec, pos2.vec, density)); + + Value retval = new NumericValue(ShapeDispatcher.drawParticleLine( + (player == null)?world.getPlayers():Collections.singletonList(player), + particle, pos1.vec, pos2.vec, density)); + return (c_, t_) -> retval; }); - this.expr.addLazyFunction("particle_rect", -1, (c, t, lv) -> + this.expr.addLazyFunction("particle_box", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; ServerWorld world = cc.s.getWorld(); String particleName = lv.get(0).evalValue(c).getString(); - ParticleEffect particle = getParticleData(particleName); + ParticleEffect particle = ShapeDispatcher.getParticleData(particleName); Vector3Argument pos1 = Vector3Argument.findIn(cc, lv, 1); Vector3Argument pos2 = Vector3Argument.findIn(cc, lv, pos1.offset); - int offset = pos2.offset; + double density = 1.0; - if (lv.size() > offset) + ServerPlayerEntity player = null; + if (lv.size() > pos2.offset+0 ) { - density = NumericValue.asNumber(lv.get(offset).evalValue(c)).getDouble(); - } - if (density <= 0) - { - throw new InternalExpressionException("Particle density should be positive"); + density = NumericValue.asNumber(lv.get(pos2.offset+0).evalValue(c)).getDouble(); + if (density <= 0) + { + throw new InternalExpressionException("Particle density should be positive"); + } + if (lv.size() > pos2.offset+1) + { + Value playerValue = lv.get(pos2.offset+1).evalValue(c); + if (playerValue instanceof EntityValue) + { + Entity e = ((EntityValue) playerValue).getEntity(); + if (!(e instanceof ServerPlayerEntity)) throw new InternalExpressionException("'particle_box' player argument has to be a player"); + player = (ServerPlayerEntity) e; + } + else + { + player = cc.s.getMinecraftServer().getPlayerManager().getPlayer(playerValue.getString()); + } + } } Vec3d a = pos1.vec; Vec3d b = pos2.vec; @@ -2689,24 +2641,107 @@ public class CarpetExpression double bx = max(a.x, b.x); double by = max(a.y, b.y); double bz = max(a.z, b.z); - int pc = 0; - pc += drawParticleLine(world, particle, new Vec3d(ax, ay, az), new Vec3d(ax, by, az), density); - pc += drawParticleLine(world, particle, new Vec3d(ax, by, az), new Vec3d(bx, by, az), density); - pc += drawParticleLine(world, particle, new Vec3d(bx, by, az), new Vec3d(bx, ay, az), density); - pc += drawParticleLine(world, particle, new Vec3d(bx, ay, az), new Vec3d(ax, ay, az), density); - - pc += drawParticleLine(world, particle, new Vec3d(ax, ay, bz), new Vec3d(ax, by, bz), density); - pc += drawParticleLine(world, particle, new Vec3d(ax, by, bz), new Vec3d(bx, by, bz), density); - pc += drawParticleLine(world, particle, new Vec3d(bx, by, bz), new Vec3d(bx, ay, bz), density); - pc += drawParticleLine(world, particle, new Vec3d(bx, ay, bz), new Vec3d(ax, ay, bz), density); - - pc += drawParticleLine(world, particle, new Vec3d(ax, ay, az), new Vec3d(ax, ay, bz), density); - pc += drawParticleLine(world, particle, new Vec3d(ax, by, az), new Vec3d(ax, by, bz), density); - pc += drawParticleLine(world, particle, new Vec3d(bx, by, az), new Vec3d(bx, by, bz), density); - pc += drawParticleLine(world, particle, new Vec3d(bx, ay, az), new Vec3d(bx, ay, bz), density); - int particleCount = pc; + int particleCount = ShapeDispatcher.Box.mesh( + player==null?world.getPlayers():Collections.singletonList(player), + particle, density, ax, ay, az, bx, by, bz + ); return (c_, t_) -> new NumericValue(particleCount); }); + // deprecated + this.expr.alias("particle_rect", "particle_box"); + + + this.expr.addLazyFunction("marker_box", -1, (c, t, lv) -> + { + CarpetContext cc = (CarpetContext)c; + Vector3Argument from = Vector3Argument.findIn(cc, lv, 0); + Vector3Argument to = Vector3Argument.findIn(cc, lv, from.offset); + int duration = 10; + int color = -1; // hwite + ServerPlayerEntity player = null; + + if (lv.size() > to.offset+0 ) + { + duration = NumericValue.asNumber(lv.get(to.offset).evalValue(c)).getInt(); + if (duration <= 0) + { + throw new InternalExpressionException("Particle density should be positive"); + } + if (lv.size() > to.offset + 1) + { + color = NumericValue.asNumber(lv.get(to.offset+1).evalValue(c)).getInt(); + + + if (lv.size() > to.offset + 2) + { + Value playerValue = lv.get(to.offset + 2).evalValue(c); + if (playerValue instanceof EntityValue) + { + Entity e = ((EntityValue) playerValue).getEntity(); + if (!(e instanceof ServerPlayerEntity)) + throw new InternalExpressionException("'particle_box' player argument has to be a player"); + player = (ServerPlayerEntity) e; + } + else + { + player = cc.s.getMinecraftServer().getPlayerManager().getPlayer(playerValue.getString()); + } + } + } + } + ShapeDispatcher.sendShape( + (player==null)?cc.s.getWorld().getPlayers():Collections.singletonList(player), + cc.s.getWorld().getDimension().getType(), + new ShapeDispatcher.Box(duration, from.vec, to.vec, color) + ); + return LazyValue.TRUE; + }); + + this.expr.addLazyFunction("marker_line", -1, (c, t, lv) -> + { + CarpetContext cc = (CarpetContext)c; + Vector3Argument from = Vector3Argument.findIn(cc, lv, 0); + Vector3Argument to = Vector3Argument.findIn(cc, lv, from.offset); + int duration = 10; + int color = -1; // hwite + ServerPlayerEntity player = null; + + if (lv.size() > to.offset+0 ) + { + duration = NumericValue.asNumber(lv.get(to.offset).evalValue(c)).getInt(); + if (duration <= 0) + { + throw new InternalExpressionException("Particle density should be positive"); + } + if (lv.size() > to.offset + 1) + { + color = NumericValue.asNumber(lv.get(to.offset+1).evalValue(c)).getInt(); + + + if (lv.size() > to.offset + 2) + { + Value playerValue = lv.get(to.offset + 2).evalValue(c); + if (playerValue instanceof EntityValue) + { + Entity e = ((EntityValue) playerValue).getEntity(); + if (!(e instanceof ServerPlayerEntity)) + throw new InternalExpressionException("'particle_box' player argument has to be a player"); + player = (ServerPlayerEntity) e; + } + else + { + player = cc.s.getMinecraftServer().getPlayerManager().getPlayer(playerValue.getString()); + } + } + } + } + ShapeDispatcher.sendShape( + (player==null)?cc.s.getWorld().getPlayers():Collections.singletonList(player), + cc.s.getWorld().getDimension().getType(), + new ShapeDispatcher.Line(duration, from.vec, to.vec, color) + ); + return LazyValue.TRUE; + }); this.expr.addLazyFunction("create_marker", -1, (c, t, lv) ->{ CarpetContext cc = (CarpetContext)c; diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index 83e607fe..a53f4eb5 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -418,6 +418,12 @@ public class Expression return result; } + public void alias(String copy, String original) + { + functions.put(copy, functions.get(original)); + } + + private void UserDefinedFunctionsAndControlFlow() // public just to get the javadoc right { // artificial construct to handle user defined functions and function definitions diff --git a/src/main/java/carpet/script/utils/ShapeDispatcher.java b/src/main/java/carpet/script/utils/ShapeDispatcher.java new file mode 100644 index 00000000..4a6c8c7c --- /dev/null +++ b/src/main/java/carpet/script/utils/ShapeDispatcher.java @@ -0,0 +1,289 @@ +package carpet.script.utils; + +import carpet.network.ServerNetworkHandler; +import carpet.script.Expression; +import carpet.script.exception.InternalExpressionException; +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.command.arguments.ParticleArgumentType; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.particle.ParticleEffect; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.dimension.DimensionType; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.function.Consumer; + +import static java.lang.Math.sqrt; + +public class ShapeDispatcher +{ + private static final Map particleCache = new HashMap<>(); + + public static void sendShape(List players, DimensionType dim, ExpiringShape shape) + { + Consumer alternative = null; + CompoundTag tag = null; + for (ServerPlayerEntity player : players) + { + if (ServerNetworkHandler.validCarpetPlayers.contains(player)) + { + if (tag == null) tag = shape.toTag(); + tag.putInt("dim", dim.getRawId()); + ServerNetworkHandler.sendCustomCommand(player,"renderShape", tag); + } + else + { + if (alternative == null) alternative = shape.alternative(); + alternative.accept(player); + } + } + } + + public static void sendBox(ServerPlayerEntity player, int duration, Vec3d from, Vec3d to, int color) + { + + } + + public static ParticleEffect getParticleData(String name) + { + ParticleEffect particle = particleCache.get(name); + if (particle != null) + return particle; + try + { + particle = ParticleArgumentType.readParameters(new StringReader(name)); + } + catch (CommandSyntaxException e) + { + throw new InternalExpressionException("No such particle: "+name); + } + particleCache.put(name, particle); + return particle; + } + + + public abstract static class ExpiringShape + { + protected float r, g, b, a; + protected int color; + protected int duration = 0; + public ExpiringShape(int duration, int color) + { + this.r = (float)(color >> 24 & 0xFF) / 255.0F; + this.g = (float)(color >> 16 & 0xFF) / 255.0F; + this.b = (float)(color >> 8 & 0xFF) / 255.0F; + this.a = (float)(color & 0xFF) / 255.0F; + this.color = color; + this.duration = duration; + }; + + public int getExpiry() { return duration; }; + public CompoundTag toTag() + { + CompoundTag tag = new CompoundTag(); + tag.putInt("color", color); + tag.putInt("duration", duration); + return tag; + }; + public abstract Consumer alternative(); + } + + public static class Box extends ExpiringShape + { + float x1, y1, z1; + float x2, y2, z2; + public Box(int duration, Vec3d from, Vec3d to, int color) + { + super(duration, color); + x1 = (float)from.x; + y1 = (float)from.y; + z1 = (float)from.z; + x2 = (float)to.x; + y2 = (float)to.y; + z2 = (float)to.z; + } + + + public static ExpiringShape fromTag(CompoundTag tag) + { + return new Box(tag.getInt("duration"), + new Vec3d(tag.getFloat("x1"), tag.getFloat("y1"), tag.getFloat("z1")), + new Vec3d(tag.getFloat("x2"), tag.getFloat("y2"), tag.getFloat("z2")), + tag.getInt("color") + ); + } + + @Override + public CompoundTag toTag() + { + CompoundTag tag = super.toTag(); + tag.putFloat("x1", x1); + tag.putFloat("y1", y1); + tag.putFloat("z1", z1); + tag.putFloat("x2", x2); + tag.putFloat("y2", y2); + tag.putFloat("z2", z2); + tag.putString("type", "debugBox"); + return tag; + } + + @Override + public Consumer alternative() + { + String particleName = String.format(Locale.ROOT , "dust %.1f %.1f %.1f 1.0", r, g, b); + ParticleEffect particle = getParticleData(particleName); + double dx = x1-x2; + double dy = y1-y2; + double dz = z1-z2; + double density = Math.max(2.0, Math.sqrt(dx*dx+dy*dy+dz*dz) /50) / (a+0.1); + return p -> mesh(Collections.singletonList(p), particle, density, x1, y1, z1, x2, y2, z2); + } + + public static int mesh(List playerList, ParticleEffect particle, double density, + double x1, double y1, double z1, double x2, double y2, double z2 ) + { + return + drawParticleLine(playerList, particle, new Vec3d(x1, y1, z1), new Vec3d(x1, y2, z1), density)+ + drawParticleLine(playerList, particle, new Vec3d(x1, y2, z1), new Vec3d(x2, y2, z1), density)+ + drawParticleLine(playerList, particle, new Vec3d(x2, y2, z1), new Vec3d(x2, y1, z1), density)+ + drawParticleLine(playerList, particle, new Vec3d(x2, y1, z1), new Vec3d(x1, y1, z1), density)+ + + drawParticleLine(playerList, particle, new Vec3d(x1, y1, z2), new Vec3d(x1, y2, z2), density)+ + drawParticleLine(playerList, particle, new Vec3d(x1, y2, z2), new Vec3d(x2, y2, z2), density)+ + drawParticleLine(playerList, particle, new Vec3d(x2, y2, z2), new Vec3d(x2, y1, z2), density)+ + drawParticleLine(playerList, particle, new Vec3d(x2, y1, z2), new Vec3d(x1, y1, z2), density)+ + + drawParticleLine(playerList, particle, new Vec3d(x1, y1, z1), new Vec3d(x1, y1, z2), density)+ + drawParticleLine(playerList, particle, new Vec3d(x1, y2, z1), new Vec3d(x1, y2, z2), density)+ + drawParticleLine(playerList, particle, new Vec3d(x2, y2, z1), new Vec3d(x2, y2, z2), density)+ + drawParticleLine(playerList, particle, new Vec3d(x2, y1, z1), new Vec3d(x2, y1, z2), density); + } + } + + public static class Line extends ExpiringShape + { + float x1, y1, z1; + float x2, y2, z2; + public Line(int duration, Vec3d from, Vec3d to, int color) + { + super(duration, color); + x1 = (float)from.x; + y1 = (float)from.y; + z1 = (float)from.z; + x2 = (float)to.x; + y2 = (float)to.y; + z2 = (float)to.z; + + } + @Override + public CompoundTag toTag() + { + CompoundTag tag = super.toTag(); + tag.putFloat("x1", x1); + tag.putFloat("y1", y1); + tag.putFloat("z1", z1); + tag.putFloat("x2", x2); + tag.putFloat("y2", y2); + tag.putFloat("z2", z2); + tag.putString("type", "debugLine"); + return tag; + } + + public static ExpiringShape fromTag(CompoundTag tag) + { + return new Line(tag.getInt("duration"), + new Vec3d(tag.getFloat("x1"), tag.getFloat("y1"), tag.getFloat("z1")), + new Vec3d(tag.getFloat("x2"), tag.getFloat("y2"), tag.getFloat("z2")), + tag.getInt("color") + ); + } + @Override + public Consumer alternative() + { + String particleName = String.format(Locale.ROOT , "dust %.1f %.1f %.1f 1.0", r, g, b); + ParticleEffect particle = getParticleData(particleName); + Vec3d pos1 = new Vec3d(x1, y1, z1); + Vec3d pos2 = new Vec3d(x2, y2, z2); + double dx = x1-x2; + double dy = y1-y2; + double dz = z1-z2; + double density = Math.max(2.0, Math.sqrt(dx*dx+dy*dy+dz*dz) /50) / (a+0.1); + return p -> drawParticleLine(Collections.singletonList(p), particle, pos1, pos2, density); + } + } + + private static boolean isStraight(Vec3d from, Vec3d to, double density) + { + if ( (from.x == to.x && from.y == to.y) || (from.x == to.x && from.z == to.z) || (from.y == to.y && from.z == to.z)) + return from.distanceTo(to) / density > 20; + return false; + } + + private static int drawOptimizedParticleLine(List playerList, ParticleEffect particle, Vec3d from, Vec3d to, double density) + { + double distance = from.distanceTo(to); + int particles = (int)(distance/density); + Vec3d towards = to.subtract(from); + int parts = 0; + for (ServerPlayerEntity player : playerList) + { + ServerWorld world = player.getServerWorld(); + world.spawnParticles(player, particle, true, + (towards.x)/2+from.x, (towards.y)/2+from.y, (towards.z)/2+from.z, particles/3, + towards.x/6, towards.y/6, towards.z/6, 0.0); + world.spawnParticles(player, particle, true, + from.x, from.y, from.z,1,0.0,0.0,0.0,0.0); + world.spawnParticles(player, particle, true, + to.x, to.y, to.z,1,0.0,0.0,0.0,0.0); + parts += particles/3+2; + } + int divider = 6; + while (particles/divider > 1) + { + int center = (divider*2)/3; + int dev = 2*divider; + for (ServerPlayerEntity player : playerList) + { + ServerWorld world = player.getServerWorld(); + world.spawnParticles(player, particle, true, + (towards.x)/center+from.x, (towards.y)/center+from.y, (towards.z)/center+from.z, particles/divider, + towards.x/dev, towards.y/dev, towards.z/dev, 0.0); + world.spawnParticles(player, particle, true, + (towards.x)*(1.0-1.0/center)+from.x, (towards.y)*(1.0-1.0/center)+from.y, (towards.z)*(1.0-1.0/center)+from.z, particles/divider, + towards.x/dev, towards.y/dev, towards.z/dev, 0.0); + } + parts += 2*particles/divider; + divider = 2*divider; + } + return parts; + } + + public static int drawParticleLine(List players, ParticleEffect particle, Vec3d from, Vec3d to, double density) + { + if (isStraight(from, to, density)) return drawOptimizedParticleLine(players, particle, from, to, density); + double lineLengthSq = from.squaredDistanceTo(to); + if (lineLengthSq == 0) return 0; + Vec3d incvec = to.subtract(from).multiply(2*density/sqrt(lineLengthSq)); + int pcount = 0; + for (Vec3d delta = new Vec3d(0.0,0.0,0.0); + delta.lengthSquared() shapes; + private final Map>> shapes; + private MinecraftClient client; - void render(MatrixStack matrices, VertexConsumerProvider vertexConsumers, double cameraX, double cameraY, double cameraZ){ + private Map>> renderedShapes + = new HashMap>>() + {{ + put("debugBox", RenderedBox::new); + put("debugLine", RenderedLine::new); + }}; - } - void addShape() {} - - - public abstract static class ExpiringShape + public ShapesRenderer(MinecraftClient minecraftClient) { - protected int r; - protected int g; - protected int b; - protected int a; - protected int expiryTick = 0; - public abstract void render(MatrixStack matrix, VertexConsumer vertexConsumer); - public ExpiringShape expiresIn(int ticks) + this.client = minecraftClient; + shapes = new HashMap<>(); + shapes.put(DimensionType.OVERWORLD, new ArrayList<>()); + shapes.put(DimensionType.THE_NETHER, new ArrayList<>()); + shapes.put(DimensionType.THE_END, new ArrayList<>()); + } + + public void render(MatrixStack matrices, VertexConsumerProvider vertexConsumers, double cameraX, double cameraY, double cameraZ) + { + //Camera camera = this.client.gameRenderer.getCamera(); + IWorld iWorld = this.client.world; + DimensionType dimensionType = iWorld.getDimension().getType(); + if (shapes.get(dimensionType).isEmpty()) return; + //BlockPos blockPos = new BlockPos(camera.getPos().x, 0.0D, camera.getPos().z); + VertexConsumer vertexConsumer = vertexConsumers.getBuffer(RenderLayer.getLines()); + long currentTime = client.world.getTime(); + + synchronized (shapes) { - expiryTick = ticks; - return this; + Iterator> it = shapes.get(dimensionType).iterator(); + while (it.hasNext()) + { + RenderedShape shape = it.next(); + if (shape.isExpired(currentTime)) it.remove(); + shape.render(matrices, vertexConsumer, (float) cameraX, (float) cameraY, (float) cameraZ); + } + } + } + public void addShape(String type, DimensionType dim, CompoundTag tag) + { + BiFunction> shapeFactory; + shapeFactory = renderedShapes.get(type); + if (shapeFactory == null) + { + CarpetSettings.LOG.error("Unrecognized shape: "+type); + } + else + { + synchronized (shapes) { shapes.get(dim).add(shapeFactory.apply(client, tag)); } + } + } + public void reset() + { + synchronized (shapes) + { + shapes.values().forEach(List::clear); + } + } + + + public abstract static class RenderedShape + { + T shape; + long expiryTick; + public abstract void render(MatrixStack matrices, VertexConsumer vertexConsumer, float cx, float cy, float cz ); + protected RenderedShape(MinecraftClient client, T shape) + { + this.shape = shape; + expiryTick = client.world.getTime()+shape.getExpiry(); } + public boolean isExpired(long currentTick) + { + return expiryTick < currentTick; + } } - public static class SolidLine extends ExpiringShape + public static class RenderedBox extends RenderedShape { - public SolidLine(Vec3d from, Vec3d to, int r, int g, int b, int a) + public RenderedBox(MinecraftClient client, CompoundTag boxData) { - this.r = r; - this.g = g; - this.b = b; - this.a = a; - + super(client, (ShapeDispatcher.Box)ShapeDispatcher.Box.fromTag(boxData)); } @Override - public void render(MatrixStack matrix, VertexConsumer vertexConsumer) + public void render(MatrixStack matrices, VertexConsumer vertexConsumer, float cx, float cy, float cz) { - + drawBox(matrices, vertexConsumer, + shape.x1-cx, shape.y1-cy, shape.z1-cz, + shape.x2-cx, shape.y2-cy, shape.z2-cz, + shape.r, shape.g, shape.b, shape.a, shape.r, shape.g, shape.b + ); } } + public static class RenderedLine extends RenderedShape + { + public RenderedLine(MinecraftClient client, CompoundTag boxData) + { + super(client, (ShapeDispatcher.Line)ShapeDispatcher.Line.fromTag(boxData)); + } + @Override + public void render(MatrixStack matrices, VertexConsumer vertexConsumer, float cx, float cy, float cz) + { + drawLine(matrices, vertexConsumer, + shape.x1-cx, shape.y1-cy, shape.z1-cz, + shape.x2-cx, shape.y2-cy, shape.z2-cz, + shape.r, shape.g, shape.b, shape.a + ); + } + } + + // some raw shit + + public static void drawLine(MatrixStack matrix, VertexConsumer vertexConsumer, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha) { + Matrix4f matrix4f = matrix.peek().getModel(); + vertexConsumer.vertex(matrix4f, x1, y1, z1).color(red1, grn1, blu1, alpha).next(); + vertexConsumer.vertex(matrix4f, x2, y2, z2).color(red1, grn1, blu1, alpha).next(); + } + + public static void drawBox(MatrixStack matrix, VertexConsumer vertexConsumer, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha, float red2, float grn2, float blu2) { + Matrix4f matrix4f = matrix.peek().getModel(); + vertexConsumer.vertex(matrix4f, x1, y1, z1).color(red1, grn2, blu2, alpha).next(); + vertexConsumer.vertex(matrix4f, x2, y1, z1).color(red1, grn2, blu2, alpha).next(); + vertexConsumer.vertex(matrix4f, x1, y1, z1).color(red2, grn1, blu2, alpha).next(); + vertexConsumer.vertex(matrix4f, x1, y2, z1).color(red2, grn1, blu2, alpha).next(); + vertexConsumer.vertex(matrix4f, x1, y1, z1).color(red2, grn2, blu1, alpha).next(); + vertexConsumer.vertex(matrix4f, x1, y1, z2).color(red2, grn2, blu1, alpha).next(); + vertexConsumer.vertex(matrix4f, x2, y1, z1).color(red1, grn1, blu1, alpha).next(); + vertexConsumer.vertex(matrix4f, x2, y2, z1).color(red1, grn1, blu1, alpha).next(); + vertexConsumer.vertex(matrix4f, x2, y2, z1).color(red1, grn1, blu1, alpha).next(); + vertexConsumer.vertex(matrix4f, x1, y2, z1).color(red1, grn1, blu1, alpha).next(); + vertexConsumer.vertex(matrix4f, x1, y2, z1).color(red1, grn1, blu1, alpha).next(); + vertexConsumer.vertex(matrix4f, x1, y2, z2).color(red1, grn1, blu1, alpha).next(); + vertexConsumer.vertex(matrix4f, x1, y2, z2).color(red1, grn1, blu1, alpha).next(); + vertexConsumer.vertex(matrix4f, x1, y1, z2).color(red1, grn1, blu1, alpha).next(); + vertexConsumer.vertex(matrix4f, x1, y1, z2).color(red1, grn1, blu1, alpha).next(); + vertexConsumer.vertex(matrix4f, x2, y1, z2).color(red1, grn1, blu1, alpha).next(); + vertexConsumer.vertex(matrix4f, x2, y1, z2).color(red1, grn1, blu1, alpha).next(); + vertexConsumer.vertex(matrix4f, x2, y1, z1).color(red1, grn1, blu1, alpha).next(); + vertexConsumer.vertex(matrix4f, x1, y2, z2).color(red1, grn1, blu1, alpha).next(); + vertexConsumer.vertex(matrix4f, x2, y2, z2).color(red1, grn1, blu1, alpha).next(); + vertexConsumer.vertex(matrix4f, x2, y1, z2).color(red1, grn1, blu1, alpha).next(); + vertexConsumer.vertex(matrix4f, x2, y2, z2).color(red1, grn1, blu1, alpha).next(); + vertexConsumer.vertex(matrix4f, x2, y2, z1).color(red1, grn1, blu1, alpha).next(); + vertexConsumer.vertex(matrix4f, x2, y2, z2).color(red1, grn1, blu1, alpha).next(); + } } diff --git a/src/main/resources/assets/carpet/scripts/overlay.sc b/src/main/resources/assets/carpet/scripts/overlay.sc index a2909b04..45be90a4 100644 --- a/src/main/resources/assets/carpet/scripts/overlay.sc +++ b/src/main/resources/assets/carpet/scripts/overlay.sc @@ -94,17 +94,24 @@ __structure_renderer(player_name) -> l(from, to) = structure_data; total_size = _euclidean(from, to); density = max(10, total_size/10); - particle_rect('dust 0 1 1 2', from, to+1, density); + //particle_box('dust 0 1 1 2', from, to+1, density); + marker_box(from, to+1, 10, 0x00FFFFFF ); structure_pieces = slice(sort_key(structure_pieces, _euclidean_sq((_:2+_:3)/2,ppos)), 0, config:'max_pieces'); for (structure_pieces, l(piece, direction, from, to) = _; - factor = 1- _i / config:'max_pieces' / 2; - total_size = _euclidean(from, to); - density = max(_i+1, total_size/10); - particle_rect(str('dust %.2f %.2f 1 1',factor, factor), from, to+1, density); + //factor = 1- _i / config:'max_pieces' / 2; + //total_size = _euclidean(from, to); + //density = max(_i+1, total_size/10); + //particle_box(str('dust %.2f %.2f 1 1',factor, factor), from, to+1, density); + r = 255 - 128 * _i/config:'max_pieces'; + g = r; + b = 255; + a = 255; + color = a+256*(b+256*(g+256*r)); + marker_box(from, to+1, 10, color); ) ) ); - schedule(3, '__structure_renderer', player_name); + schedule(5, '__structure_renderer', player_name); ); __chunk_renderer(player_name) -> @@ -128,15 +135,27 @@ __chunk_renderer(player_name) -> top_01 = ref_pos + l(0, top('terrain', ref_pos+l(0, 0, 15))+10, 16); part = 'dust 0.2 0.8 0.2 2'; density = 2+player_distance/2; - particle_line(part, top_00, top_10, density); - particle_line(part, top_10, top_11, density); - particle_line(part, top_11, top_01, density); - particle_line(part, top_01, top_00, density); - particle_line(part, top_00, top_11, density); - particle_line(part, top_01, top_10, density); + r = 30; + g = 220; + b = 30; + a = max(0, 255-player_distance); + color = a+256*(b+256*(g+256*r)); + marker_line(top_00, top_10, 10, color); + marker_line(top_10, top_11, 10, color); + marker_line(top_11, top_01, 10, color); + marker_line(top_01, top_00, 10, color); + marker_line(top_00, top_11, 10, color); + marker_line(top_01, top_10, 10, color); + + //particle_line(part, top_00, top_10, density); + //particle_line(part, top_10, top_11, density); + //particle_line(part, top_11, top_01, density); + //particle_line(part, top_01, top_00, density); + //particle_line(part, top_00, top_11, density); + //particle_line(part, top_01, top_10, density); ) ) ) ); - schedule(3, '__chunk_renderer', player_name); + schedule(5, '__chunk_renderer', player_name); ) \ No newline at end of file diff --git a/src/main/resources/carpet.mixins.json b/src/main/resources/carpet.mixins.json index 247b24d1..4b63eb8e 100644 --- a/src/main/resources/carpet.mixins.json +++ b/src/main/resources/carpet.mixins.json @@ -181,8 +181,8 @@ "ClientPlayerEntity_clientCommandMixin", "WorldRenderer_fogOffMixin", "WorldRenderer_creativeNoClipMixin", - "ClientPlayNetworkHandlerMixin" - + "ClientPlayNetworkHandlerMixin", + "DebugRenderer_scarpetRenderMixin" ], "server": [ "MinecraftDedicatedServerMixin" From ec6cb9fa7ace0bf0a011c869e203926db25d0ca8 Mon Sep 17 00:00:00 2001 From: Forgot-Dream <56014859+Forgot-Dream@users.noreply.github.com> Date: Sun, 31 May 2020 14:21:03 +0800 Subject: [PATCH 154/198] update zh_cn.json and fix bugs in extra-finding process(by X-Green) (#300) * Add files via upload * fix extra-finding (by X-Green) * update zh_cn --- .../resources/assets/carpet/lang/zh_cn.json | 205 +++++++++++++++++- 1 file changed, 199 insertions(+), 6 deletions(-) diff --git a/src/main/resources/assets/carpet/lang/zh_cn.json b/src/main/resources/assets/carpet/lang/zh_cn.json index 9784f087..ef0c0124 100644 --- a/src/main/resources/assets/carpet/lang/zh_cn.json +++ b/src/main/resources/assets/carpet/lang/zh_cn.json @@ -1,12 +1,205 @@ { + "rule.antiCheatDisabled.name": "移动检测通杀", + "rule.antiCheatDisabled.desc": "防止玩家因为“本服务器未启用飞行”,“移动过快”等原因被踢出", + + "rule.carpets.name": "放置地毯执行功能", + "rule.carpets.desc": "通过放置地毯方块快捷执行部分功能", + + "rule.combineXPOrbs.name": "经验球合并", + "rule.combineXPOrbs.desc": "会将多个小经验球合并为更大的经验球", + + "rule.commandCameramode.name": "灵魂出窍模式", + "rule.commandCameramode.desc": "启用/c和/s命令使得玩家可以在生存模式和观察者模式间切换", + "rule.commandCameramode.extra.0": "/c和/s命令所有玩家(包括非OP玩家)都可以使用", + + "rule.commandDistance.name": "距离测量", + "rule.commandDistance.desc": "启用/distance命令以测量游戏中两点间距离", + "rule.commandDistance.extra.0": "可以通过放置棕色地毯的方式使用本功能,前提是“放置地毯执行功能”已启用", + + "rule.commandDraw.name": "画图", + "rule.commandDraw.desc": "启用/draw命令以允许绘制一些简单图形", + + "rule.commandInfo.name": "获取方块数据", + "rule.commandInfo.desc": "启用/info命令以获取方块数据", + "rule.commandInfo.extra.0": "可以通过放置灰色地毯的方式使用本功能,前提是“放置地毯执行功能”已启用", + + "rule.commandLog.name": "游戏数据监视器", + "rule.commandLog.desc": "启用/log命令以在聊天栏/Tab栏监视游戏部分数据", + + "rule.commandPerimeterInfo.name": "刷怪区域搜寻器", + "rule.commandPerimeterInfo.desc": "启用/perimeterinfo命令以搜寻周围的可刷怪区域", + + "rule.commandPlayer.name": "假人控制", + "rule.commandPlayer.desc": "启用/player命令以控制/召唤玩家", + + "rule.commandScript.name": "地毯脚本控制器", + "rule.commandScript.desc": "启用/script相关命令", + "rule.commandScript.extra.0": "一个Scarpet语言的游戏内API", + + "rule.commandSpawn.name": "刷怪追踪器", + "rule.commandSpawn.desc": "启用/spawn命令用于怪物生成追踪", + + "rule.commandTick.name": "游戏时钟控制器", + "rule.commandTick.desc": "启用/tick命令以控制游戏时钟", + + "rule.commandTrackAI.name": "AI追踪器", + "rule.commandTrackAI.desc": "启用/track命令以追踪生物的AI", + + "rule.ctrlQCraftingFix.name": "ctrlQ合成修复", + "rule.ctrlQCraftingFix.desc": "在合成时允许使用ctrl+Q快捷键扔出结果格内所有物品", + + "rule.customMOTD.name": "MOTD更改", + "rule.customMOTD.desc": "设置一个不同的MOTD信息", + "rule.customMOTD.extra.0": "使用'_'时将发送默认MOTD(从server.properties中读取)", + + "rule.defaultLoggers.name": "默认游戏监视器", + "rule.defaultLoggers.desc": "为所有新进入玩家设置部分监视器默认开启", + "rule.defaultLoggers.extra.0": "比如设置'tps,mobcaps'作为默认监视器", + + "rule.desertShrubs.name": "树苗在沙漠干枯", + "rule.desertShrubs.desc": "树苗将在附近无水源的沙漠群系枯萎", + + "rule.disableSpawnChunks.name": "允许出生点区块卸载", + "rule.disableSpawnChunks.desc": "允许出生点区块卸载", + + "rule.explosionNoBlockDamage.name": "防爆", + "rule.explosionNoBlockDamage.desc": "任何形式的爆炸都不会摧毁方块", + + "rule.extremeBehaviours.name": "随机极端情况", + "rule.extremeBehaviours.desc": "大幅度提升极端情况出现概率,仅用于测试", + "rule.extremeBehaviours.extra.0": "发射器和投掷器将使用最大随机刻", + + "rule.fastRedstoneDust.name": "红石粉卡顿优化", + "rule.fastRedstoneDust.desc": "红石粉卡顿优化 作者 Theosib", + + "rule.fillLimit.name": "fill/clone上限更改", + "rule.fillLimit.desc": "将fill/clone上限更改为自己需要的值", + "rule.fillLimit.extra.0": "你必须在1-20M之间取一个值", + + "rule.fillUpdates.name": "fill更新开关", + "rule.fillUpdates.desc": "fill/clone/setblock命令以及结构方块执行时是否产生更新", + "rule.fillUpdates.extra.0": "设置为true有更新 设置为false时为无更新", + + "rule.flatWorldStructureSpawning.name": "结构怪在超平坦世界生成", + "rule.flatWorldStructureSpawning.desc": "允许结构怪在超平坦世界生成", + + "rule.flippinCactus.name": "仙人掌扳手", + "rule.flippinCactus.desc": "允许使用仙人掌调整方块朝向,并且不会产生更新", + + "rule.hardcodeTNTangle.name": "硬编码TNT角度", + "rule.hardcodeTNTangle.desc": "把TNT水平随机角度设为固定值,可用于测试机器", + "rule.hardcodeTNTangle.extra.0": "默认为-1,必须在0与360之间,或者-1", + + "rule.hopperCounters.name": "漏斗计数器", + "rule.hopperCounters.desc": "漏斗指向的羊毛会计算经过的物品", + "rule.hopperCounters.extra.0": "在羊毛上放置红色或绿色地毯,使用/counter命令可启用", + "rule.hopperCounters.extra.1": "使用 /counter reset重置计数器,使用/counter 查询", + "rule.hopperCounters.extra.2": "在生存模式,在同色羊毛上放绿地毯可以查询,放红地毯重置", + "rule.hopperCounters.extra.3": "数据是全局性在玩家间共享的,并且有16颜色可用", + "rule.hopperCounters.extra.4": "物品会被销毁,每个漏斗每tick销毁一组物品", + + "rule.huskSpawningInTemples.name": "尸壳在神殿里生成", + "rule.huskSpawningInTemples.desc": "只有尸壳会在沙漠神殿生成", + + "rule.lagFreeSpawning.name": "延迟自然生成", + "rule.lagFreeSpawning.desc": "生物生成需要更少的CPU和内存", + + "rule.leadFix.name": "栓绳修复", + "rule.leadFix.desc": "修复栓绳在未加载区块中,变得不可见的问题", + + "rule.maxEntityCollisions.name": "最大实体挤压数", + "rule.maxEntityCollisions.desc": "设定最大实体挤压限制,0表示无限大", + + "rule.mergeTNT.name": "合并TNT", + "rule.mergeTNT.desc": "合并静止的点燃的tnt实体", + + "rule.missingTools.name": "工具缺失修复", + "rule.missingTools.desc": "活塞,玻璃和海绵可以用合适的工具更快地破坏", + + "rule.movableBlockEntities.name": "容器移动", + "rule.movableBlockEntities.desc": "活塞可推动方块实体,比如箱子,漏斗", + + "rule.onePlayerSleeping.name": "单个玩家睡觉", + "rule.onePlayerSleeping.desc": "服务器里一个玩家睡觉可跳过夜晚", + + "rule.optimizedTNT.name": "TNT优化", + "rule.optimizedTNT.desc": "tnt在相同的地点或在流体里,爆炸造成更小的延迟", + + "rule.persistentParrots.name": "鹦鹉停留", + "rule.persistentParrots.desc": "鹦鹉不会离开你的肩膀,除非你收到伤害", + + "rule.placementRotationFix.name": "放置旋转修复", + "rule.placementRotationFix.desc": "修复了玩家放置方块时快速转身造成的问题", + + "rule.pushLimit.name": "自定义推动上限", + "rule.pushLimit.desc": "自定义活塞推动上限", + "rule.pushLimit.extra.0": "你必须在1-1024中选取一个值", + + "rule.quasiConnectivity.name": "qC激活开关", + "rule.quasiConnectivity.desc": "活塞,发射器和投掷器在他们上方方块激活时是否响应", + "rule.quasiConnectivity.extra.0": "设置为true为开启 设置为false为禁用", + + "rule.railPowerLimit.name": "自定义动力铁轨激活距离", + "rule.railPowerLimit.desc": "动力铁轨激活上限可自定义", + "rule.railPowerLimit.extra.0": "你必须在1-1024中选取一个值", + + "rule.renewableCoral.name": "珊瑚可再生", + "rule.renewableCoral.desc": "使用骨粉可催熟珊瑚以生成珊瑚结构", + + "rule.renewableSponges.name": "海绵可再生", + "rule.renewableSponges.desc": "守卫者将在被雷击后会变为远古守卫者", + + "rule.rotatorBlock.name": "仙人掌扳手发射器版", + "rule.rotatorBlock.desc": "发射器中的仙人掌可以旋转方块(尽可能以逆时针)", + + "rule.scriptsAutoload.name": "Scarpet脚本自动加载", + "rule.scriptsAutoload.desc": "在服务器/世界加载的时候将会自动从世界文件中加载Scarpet脚本文件", + "rule.scriptsAutoload.extra.0": "/script命令必须启用", + + "rule.shulkerSpawningInEndCities.name": "潜影贝重生", + "rule.shulkerSpawningInEndCities.desc": "潜影贝将会在末地城中重生", + + "rule.silverFishDropGravel.name": "蠹虫钻出方块掉落沙砾", + "rule.silverFishDropGravel.desc": "蠹虫钻出方块时会掉落沙砾", + + "rule.smoothClientAnimations.name": "平滑客户端动画", + "rule.smoothClientAnimations.desc": "低TPS设置时可以使客户端动画更加平滑", + "rule.smoothClientAnimations.extra.0": "仅在单人游戏中生效,并且会降低客户端运行速度", + + "rule.stackableShulkerBoxes.name": "潜影盒堆叠", + "rule.stackableShulkerBoxes.desc": "空潜影盒仍在地上时将自动堆叠,直至堆叠为1组", + "rule.stackableShulkerBoxes.extra.0": "在物品GUI中,请使用shift键+单击以移动整组潜影盒", + + "rule.summonNaturalLightning.name": "召唤闪电自然化", + "rule.summonNaturalLightning.desc": "召唤的闪电将拥有所有自然生成闪电拥有的特性", + + "rule.tntDoNotUpdate.name": "TNT放置时不产生更新", + "rule.tntDoNotUpdate.desc": "TNT在放置时不会产生任何方块更新(不会激活)", + + "rule.tntPrimerMomentumRemoved.name": "移除TNT点燃时随机动量", + "rule.tntPrimerMomentumRemoved.desc": "TNT点燃时的随机动量将被移除", + + "rule.tntRandomRange.name": "TNT爆炸范围设置", + "rule.tntRandomRange.desc": "设置TNT随机爆炸范围为一个固定的值,设为-1以禁用", + "rule.tntRandomRange.extra.0": "必须启用optimizedTNT功能", + "rule.tntRandomRange.extra.1": "不能为负值,除了-1", + + "rule.unloadedEntityFix.name": "未加载实体修复", + "rule.unloadedEntityFix.desc": "进入或者被推入未加载区块的实体不会消失", + + "rule.viewDistance.name": "自定义视距", + "rule.viewDistance.desc": "改变服务器视距,设为0以使用默认值", + "rule.viewDistance.extra.0": "你必须在0(使用服务器默认设置)-32取一个整数", + + "rule.xpNoCooldown.name": "经验吸收无冷却", + "rule.xpNoCooldown.desc": "玩家吸收经验球时不会有冷却时间", + "rule.portalSuffocationFix.name": "传送门窒息修复", - - "rule.portalSuffocationFix.desc": "使下界传送门正确地传送实体", - - - "rule.portalSuffocationFix.extra.0": "0000000", - "rule.portalSuffocationFix.extra.1": "1111111", + "rule.portalSuffocationFix.extra.0": "传送的实体将不再卡在黑曜石里面", + + "rule.portalCreativeDelay.name": "创造玩家不被地狱门传送", + "rule.portalCreativeDelay.desc": "创造模式的玩家将不会立即被地狱门传送", "category.bugfix": "BUG修复", From b29896858ef1241b6e12b7ff1d552137cfc0b76b Mon Sep 17 00:00:00 2001 From: gnembon Date: Sun, 31 May 2020 14:29:51 -0300 Subject: [PATCH 155/198] much better, fixes #301 --- .../carpet/script/utils/ShapesRenderer.java | 111 +++++++++++------- 1 file changed, 69 insertions(+), 42 deletions(-) diff --git a/src/main/java/carpet/script/utils/ShapesRenderer.java b/src/main/java/carpet/script/utils/ShapesRenderer.java index 99de0c31..a4590182 100644 --- a/src/main/java/carpet/script/utils/ShapesRenderer.java +++ b/src/main/java/carpet/script/utils/ShapesRenderer.java @@ -1,15 +1,18 @@ package carpet.script.utils; import carpet.CarpetSettings; +import com.mojang.blaze3d.systems.RenderSystem; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.render.RenderLayer; -import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.BufferBuilder; +import net.minecraft.client.render.Tessellator; import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.util.math.Matrix4f; +import net.minecraft.client.render.VertexFormats; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.Entity; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.IWorld; import net.minecraft.world.dimension.DimensionType; +import org.lwjgl.opengl.GL11; import java.util.ArrayList; import java.util.HashMap; @@ -41,14 +44,26 @@ public class ShapesRenderer public void render(MatrixStack matrices, VertexConsumerProvider vertexConsumers, double cameraX, double cameraY, double cameraZ) { - //Camera camera = this.client.gameRenderer.getCamera(); IWorld iWorld = this.client.world; DimensionType dimensionType = iWorld.getDimension().getType(); if (shapes.get(dimensionType).isEmpty()) return; - //BlockPos blockPos = new BlockPos(camera.getPos().x, 0.0D, camera.getPos().z); - VertexConsumer vertexConsumer = vertexConsumers.getBuffer(RenderLayer.getLines()); long currentTime = client.world.getTime(); + RenderSystem.enableDepthTest(); + RenderSystem.shadeModel(7425); + RenderSystem.enableAlphaTest(); + RenderSystem.defaultAlphaFunc(); + Entity entity = this.client.gameRenderer.getCamera().getFocusedEntity(); + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferBuilder = tessellator.getBuffer(); + double d = 0.0D - cameraY; + double e = 256.0D - cameraY; + RenderSystem.disableTexture(); + RenderSystem.disableBlend(); + double f = (double)(entity.chunkX << 4) - cameraX; + double g = (double)(entity.chunkZ << 4) - cameraZ; + + // render synchronized (shapes) { Iterator> it = shapes.get(dimensionType).iterator(); @@ -56,10 +71,16 @@ public class ShapesRenderer { RenderedShape shape = it.next(); if (shape.isExpired(currentTime)) it.remove(); - shape.render(matrices, vertexConsumer, (float) cameraX, (float) cameraY, (float) cameraZ); + shape.render(tessellator, bufferBuilder, (float) cameraX, (float) cameraY, (float) cameraZ); } } + + RenderSystem.lineWidth(1.0F); + RenderSystem.enableBlend(); + RenderSystem.enableTexture(); + RenderSystem.shadeModel(7424); } + public void addShape(String type, DimensionType dim, CompoundTag tag) { BiFunction> shapeFactory; @@ -86,7 +107,7 @@ public class ShapesRenderer { T shape; long expiryTick; - public abstract void render(MatrixStack matrices, VertexConsumer vertexConsumer, float cx, float cy, float cz ); + public abstract void render(Tessellator tessellator, BufferBuilder builder, float cx, float cy, float cz ); protected RenderedShape(MinecraftClient client, T shape) { this.shape = shape; @@ -106,14 +127,18 @@ public class ShapesRenderer super(client, (ShapeDispatcher.Box)ShapeDispatcher.Box.fromTag(boxData)); } @Override - public void render(MatrixStack matrices, VertexConsumer vertexConsumer, float cx, float cy, float cz) + public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) { - drawBox(matrices, vertexConsumer, + RenderSystem.lineWidth(2.0F); + bufferBuilder.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR); // 3 + drawBox(bufferBuilder, shape.x1-cx, shape.y1-cy, shape.z1-cz, shape.x2-cx, shape.y2-cy, shape.z2-cz, shape.r, shape.g, shape.b, shape.a, shape.r, shape.g, shape.b ); + tessellator.draw(); } + } public static class RenderedLine extends RenderedShape @@ -123,49 +148,51 @@ public class ShapesRenderer super(client, (ShapeDispatcher.Line)ShapeDispatcher.Line.fromTag(boxData)); } @Override - public void render(MatrixStack matrices, VertexConsumer vertexConsumer, float cx, float cy, float cz) + public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) { - drawLine(matrices, vertexConsumer, + RenderSystem.lineWidth(2.0F); + bufferBuilder.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR); // 3 + drawLine(bufferBuilder, shape.x1-cx, shape.y1-cy, shape.z1-cz, shape.x2-cx, shape.y2-cy, shape.z2-cz, shape.r, shape.g, shape.b, shape.a ); + tessellator.draw(); } } // some raw shit - public static void drawLine(MatrixStack matrix, VertexConsumer vertexConsumer, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha) { - Matrix4f matrix4f = matrix.peek().getModel(); - vertexConsumer.vertex(matrix4f, x1, y1, z1).color(red1, grn1, blu1, alpha).next(); - vertexConsumer.vertex(matrix4f, x2, y2, z2).color(red1, grn1, blu1, alpha).next(); + public static void drawLine(BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha) { + + builder.vertex(x1, y1, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); } - public static void drawBox(MatrixStack matrix, VertexConsumer vertexConsumer, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha, float red2, float grn2, float blu2) { - Matrix4f matrix4f = matrix.peek().getModel(); - vertexConsumer.vertex(matrix4f, x1, y1, z1).color(red1, grn2, blu2, alpha).next(); - vertexConsumer.vertex(matrix4f, x2, y1, z1).color(red1, grn2, blu2, alpha).next(); - vertexConsumer.vertex(matrix4f, x1, y1, z1).color(red2, grn1, blu2, alpha).next(); - vertexConsumer.vertex(matrix4f, x1, y2, z1).color(red2, grn1, blu2, alpha).next(); - vertexConsumer.vertex(matrix4f, x1, y1, z1).color(red2, grn2, blu1, alpha).next(); - vertexConsumer.vertex(matrix4f, x1, y1, z2).color(red2, grn2, blu1, alpha).next(); - vertexConsumer.vertex(matrix4f, x2, y1, z1).color(red1, grn1, blu1, alpha).next(); - vertexConsumer.vertex(matrix4f, x2, y2, z1).color(red1, grn1, blu1, alpha).next(); - vertexConsumer.vertex(matrix4f, x2, y2, z1).color(red1, grn1, blu1, alpha).next(); - vertexConsumer.vertex(matrix4f, x1, y2, z1).color(red1, grn1, blu1, alpha).next(); - vertexConsumer.vertex(matrix4f, x1, y2, z1).color(red1, grn1, blu1, alpha).next(); - vertexConsumer.vertex(matrix4f, x1, y2, z2).color(red1, grn1, blu1, alpha).next(); - vertexConsumer.vertex(matrix4f, x1, y2, z2).color(red1, grn1, blu1, alpha).next(); - vertexConsumer.vertex(matrix4f, x1, y1, z2).color(red1, grn1, blu1, alpha).next(); - vertexConsumer.vertex(matrix4f, x1, y1, z2).color(red1, grn1, blu1, alpha).next(); - vertexConsumer.vertex(matrix4f, x2, y1, z2).color(red1, grn1, blu1, alpha).next(); - vertexConsumer.vertex(matrix4f, x2, y1, z2).color(red1, grn1, blu1, alpha).next(); - vertexConsumer.vertex(matrix4f, x2, y1, z1).color(red1, grn1, blu1, alpha).next(); - vertexConsumer.vertex(matrix4f, x1, y2, z2).color(red1, grn1, blu1, alpha).next(); - vertexConsumer.vertex(matrix4f, x2, y2, z2).color(red1, grn1, blu1, alpha).next(); - vertexConsumer.vertex(matrix4f, x2, y1, z2).color(red1, grn1, blu1, alpha).next(); - vertexConsumer.vertex(matrix4f, x2, y2, z2).color(red1, grn1, blu1, alpha).next(); - vertexConsumer.vertex(matrix4f, x2, y2, z1).color(red1, grn1, blu1, alpha).next(); - vertexConsumer.vertex(matrix4f, x2, y2, z2).color(red1, grn1, blu1, alpha).next(); + public static void drawBox(BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha, float red2, float grn2, float blu2) { + builder.vertex(x1, y1, z1).color(red1, grn2, blu2, alpha).next(); + builder.vertex(x2, y1, z1).color(red1, grn2, blu2, alpha).next(); + builder.vertex(x1, y1, z1).color(red2, grn1, blu2, alpha).next(); + builder.vertex(x1, y2, z1).color(red2, grn1, blu2, alpha).next(); + builder.vertex(x1, y1, z1).color(red2, grn2, blu1, alpha).next(); + builder.vertex(x1, y1, z2).color(red2, grn2, blu1, alpha).next(); + builder.vertex(x2, y1, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x1, y2, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x1, y2, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x1, y2, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x1, y2, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x1, y1, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x1, y1, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y1, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y1, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y1, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x1, y2, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y1, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); } } From 6e4b5ebaf640b5abef43becab98f037f0de60758 Mon Sep 17 00:00:00 2001 From: gnembon Date: Sun, 31 May 2020 19:42:49 -0300 Subject: [PATCH 156/198] detecting refreshed shapes --- .../carpet/script/utils/ShapeDispatcher.java | 44 ++++++- .../carpet/script/utils/ShapesRenderer.java | 120 ++++++++++++++---- .../assets/carpet/scripts/overlay.sc | 22 ++-- 3 files changed, 147 insertions(+), 39 deletions(-) diff --git a/src/main/java/carpet/script/utils/ShapeDispatcher.java b/src/main/java/carpet/script/utils/ShapeDispatcher.java index 4a6c8c7c..e898974d 100644 --- a/src/main/java/carpet/script/utils/ShapeDispatcher.java +++ b/src/main/java/carpet/script/utils/ShapeDispatcher.java @@ -74,6 +74,7 @@ public class ShapeDispatcher protected float r, g, b, a; protected int color; protected int duration = 0; + private int key; public ExpiringShape(int duration, int color) { this.r = (float)(color >> 24 & 0xFF) / 255.0F; @@ -82,7 +83,8 @@ public class ShapeDispatcher this.a = (float)(color & 0xFF) / 255.0F; this.color = color; this.duration = duration; - }; + key = 0; + } public int getExpiry() { return duration; }; public CompoundTag toTag() @@ -93,6 +95,18 @@ public class ShapeDispatcher return tag; }; public abstract Consumer alternative(); + public int key() + { + if (key!=0) return key; + key = calcKey(); + return key; + } + protected int calcKey() + { + int hash = 17; + hash = 31*hash + color; + return hash; + }; } public static class Box extends ExpiringShape @@ -146,6 +160,20 @@ public class ShapeDispatcher return p -> mesh(Collections.singletonList(p), particle, density, x1, y1, z1, x2, y2, z2); } + @Override + public int calcKey() + { + int hash = super.calcKey(); + hash = 31*hash + 1; + hash = 31*hash + Float.hashCode(x1); + hash = 31*hash + Float.hashCode(y1); + hash = 31*hash + Float.hashCode(z1); + hash = 31*hash + Float.hashCode(x2); + hash = 31*hash + Float.hashCode(y2); + hash = 31*hash + Float.hashCode(z2); + return hash; + } + public static int mesh(List playerList, ParticleEffect particle, double density, double x1, double y1, double z1, double x2, double y2, double z2 ) { @@ -217,6 +245,20 @@ public class ShapeDispatcher double density = Math.max(2.0, Math.sqrt(dx*dx+dy*dy+dz*dz) /50) / (a+0.1); return p -> drawParticleLine(Collections.singletonList(p), particle, pos1, pos2, density); } + + @Override + public int calcKey() + { + int hash = super.calcKey(); + hash = 31*hash + 2; + hash = 31*hash + Float.hashCode(x1); + hash = 31*hash + Float.hashCode(y1); + hash = 31*hash + Float.hashCode(z1); + hash = 31*hash + Float.hashCode(x2); + hash = 31*hash + Float.hashCode(y2); + hash = 31*hash + Float.hashCode(z2); + return hash; + } } private static boolean isStraight(Vec3d from, Vec3d to, double density) diff --git a/src/main/java/carpet/script/utils/ShapesRenderer.java b/src/main/java/carpet/script/utils/ShapesRenderer.java index a4590182..d6db7387 100644 --- a/src/main/java/carpet/script/utils/ShapesRenderer.java +++ b/src/main/java/carpet/script/utils/ShapesRenderer.java @@ -2,6 +2,7 @@ package carpet.script.utils; import carpet.CarpetSettings; import com.mojang.blaze3d.systems.RenderSystem; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.BufferBuilder; import net.minecraft.client.render.Tessellator; @@ -14,16 +15,13 @@ import net.minecraft.world.IWorld; import net.minecraft.world.dimension.DimensionType; import org.lwjgl.opengl.GL11; -import java.util.ArrayList; import java.util.HashMap; -import java.util.Iterator; -import java.util.List; import java.util.Map; import java.util.function.BiFunction; public class ShapesRenderer { - private final Map>> shapes; + private final Map>> shapes; private MinecraftClient client; private Map>> renderedShapes @@ -37,9 +35,9 @@ public class ShapesRenderer { this.client = minecraftClient; shapes = new HashMap<>(); - shapes.put(DimensionType.OVERWORLD, new ArrayList<>()); - shapes.put(DimensionType.THE_NETHER, new ArrayList<>()); - shapes.put(DimensionType.THE_END, new ArrayList<>()); + shapes.put(DimensionType.OVERWORLD, new Int2ObjectOpenHashMap<>()); + shapes.put(DimensionType.THE_NETHER, new Int2ObjectOpenHashMap<>()); + shapes.put(DimensionType.THE_END, new Int2ObjectOpenHashMap<>()); } public void render(MatrixStack matrices, VertexConsumerProvider vertexConsumers, double cameraX, double cameraY, double cameraZ) @@ -48,8 +46,10 @@ public class ShapesRenderer DimensionType dimensionType = iWorld.getDimension().getType(); if (shapes.get(dimensionType).isEmpty()) return; long currentTime = client.world.getTime(); - RenderSystem.enableDepthTest(); + RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); + //RenderSystem.blendFuncSeparate(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE, GlStateManager.SrcFactor.ONE, GlStateManager.DstFactor.ZERO); RenderSystem.shadeModel(7425); RenderSystem.enableAlphaTest(); RenderSystem.defaultAlphaFunc(); @@ -59,20 +59,21 @@ public class ShapesRenderer double d = 0.0D - cameraY; double e = 256.0D - cameraY; RenderSystem.disableTexture(); - RenderSystem.disableBlend(); + //RenderSystem.disableBlend(); double f = (double)(entity.chunkX << 4) - cameraX; double g = (double)(entity.chunkZ << 4) - cameraZ; - // render synchronized (shapes) { - Iterator> it = shapes.get(dimensionType).iterator(); - while (it.hasNext()) - { - RenderedShape shape = it.next(); - if (shape.isExpired(currentTime)) it.remove(); - shape.render(tessellator, bufferBuilder, (float) cameraX, (float) cameraY, (float) cameraZ); - } + shapes.get(dimensionType).int2ObjectEntrySet().removeIf( + entry -> entry.getValue().isExpired(currentTime) + ); + shapes.get(dimensionType).values().forEach( + s -> s.render(tessellator, bufferBuilder, (float) cameraX, (float) cameraY, (float) cameraZ) + ); + shapes.get(dimensionType).values().forEach( + s -> s.render2pass(tessellator, bufferBuilder, (float) cameraX, (float) cameraY, (float) cameraZ) + ); } RenderSystem.lineWidth(1.0F); @@ -91,54 +92,87 @@ public class ShapesRenderer } else { - synchronized (shapes) { shapes.get(dim).add(shapeFactory.apply(client, tag)); } + RenderedShape rshape = shapeFactory.apply(client, tag); + int key = rshape.key(); + synchronized (shapes) + { + RenderedShape existing = shapes.get(dim).get(key); + if (existing != null) + { // promoting previous shape + existing.expiryTick = rshape.expiryTick; + } + else + { + shapes.get(dim).put(key, rshape); + } + } } } public void reset() { synchronized (shapes) { - shapes.values().forEach(List::clear); + shapes.values().forEach(Int2ObjectOpenHashMap::clear); } } public abstract static class RenderedShape { - T shape; + protected T shape; long expiryTick; + float renderEpsilon = 0; public abstract void render(Tessellator tessellator, BufferBuilder builder, float cx, float cy, float cz ); + public void render2pass(Tessellator tessellator, BufferBuilder builder, float cx, float cy, float cz ) {}; protected RenderedShape(MinecraftClient client, T shape) { this.shape = shape; expiryTick = client.world.getTime()+shape.getExpiry(); + renderEpsilon = (2+((float)shape.key())/Integer.MAX_VALUE)/1000; } public boolean isExpired(long currentTick) { return expiryTick < currentTick; } + public int key() + { + return shape.key(); + }; } public static class RenderedBox extends RenderedShape { + public RenderedBox(MinecraftClient client, CompoundTag boxData) { super(client, (ShapeDispatcher.Box)ShapeDispatcher.Box.fromTag(boxData)); + } @Override public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) { RenderSystem.lineWidth(2.0F); bufferBuilder.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR); // 3 - drawBox(bufferBuilder, - shape.x1-cx, shape.y1-cy, shape.z1-cz, - shape.x2-cx, shape.y2-cy, shape.z2-cz, + drawBoxWireGLLines(bufferBuilder, + shape.x1 - cx-renderEpsilon, shape.y1 - cy-renderEpsilon, shape.z1 - cz-renderEpsilon, + shape.x2 - cx+renderEpsilon, shape.y2 - cy+renderEpsilon, shape.z2 - cz+renderEpsilon, shape.r, shape.g, shape.b, shape.a, shape.r, shape.g, shape.b ); tessellator.draw(); } - + @Override + public void render2pass(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) + { + RenderSystem.lineWidth(1.0F); + bufferBuilder.begin(GL11.GL_QUADS, VertexFormats.POSITION_COLOR); // 3 + drawBox(bufferBuilder, + shape.x1-cx-renderEpsilon, shape.y1-cy-renderEpsilon, shape.z1-cz-renderEpsilon, + shape.x2-cx+renderEpsilon, shape.y2-cy+renderEpsilon, shape.z2-cz+renderEpsilon, + shape.r, shape.g, shape.b, shape.a/6 + ); + tessellator.draw(); + } } public static class RenderedLine extends RenderedShape @@ -153,8 +187,8 @@ public class ShapesRenderer RenderSystem.lineWidth(2.0F); bufferBuilder.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR); // 3 drawLine(bufferBuilder, - shape.x1-cx, shape.y1-cy, shape.z1-cz, - shape.x2-cx, shape.y2-cy, shape.z2-cz, + shape.x1-cx-renderEpsilon, shape.y1-cy-renderEpsilon, shape.z1-cz-renderEpsilon, + shape.x2-cx+renderEpsilon, shape.y2-cy+renderEpsilon, shape.z2-cz+renderEpsilon, shape.r, shape.g, shape.b, shape.a ); tessellator.draw(); @@ -169,7 +203,7 @@ public class ShapesRenderer builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); } - public static void drawBox(BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha, float red2, float grn2, float blu2) { + public static void drawBoxWireGLLines(BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha, float red2, float grn2, float blu2) { builder.vertex(x1, y1, z1).color(red1, grn2, blu2, alpha).next(); builder.vertex(x2, y1, z1).color(red1, grn2, blu2, alpha).next(); builder.vertex(x1, y1, z1).color(red2, grn1, blu2, alpha).next(); @@ -195,4 +229,36 @@ public class ShapesRenderer builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); } + + public static void drawBox(BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha) { + builder.vertex(x1, y1, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y1, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x1, y2, z1).color(red1, grn1, blu1, alpha).next(); + + builder.vertex(x1, y1, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y1, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x1, y2, z2).color(red1, grn1, blu1, alpha).next(); + + builder.vertex(x1, y1, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x1, y1, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x1, y2, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x1, y2, z1).color(red1, grn1, blu1, alpha).next(); + + builder.vertex(x2, y1, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y1, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); + + builder.vertex(x1, y1, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y1, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y1, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x1, y1, z2).color(red1, grn1, blu1, alpha).next(); + + builder.vertex(x1, y2, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x1, y2, z2).color(red1, grn1, blu1, alpha).next(); + } } diff --git a/src/main/resources/assets/carpet/scripts/overlay.sc b/src/main/resources/assets/carpet/scripts/overlay.sc index 45be90a4..95d4fca5 100644 --- a/src/main/resources/assets/carpet/scripts/overlay.sc +++ b/src/main/resources/assets/carpet/scripts/overlay.sc @@ -95,7 +95,7 @@ __structure_renderer(player_name) -> total_size = _euclidean(from, to); density = max(10, total_size/10); //particle_box('dust 0 1 1 2', from, to+1, density); - marker_box(from, to+1, 10, 0x00FFFFFF ); + marker_box(from, to+1, 15, 0x00FFFFFF ); structure_pieces = slice(sort_key(structure_pieces, _euclidean_sq((_:2+_:3)/2,ppos)), 0, config:'max_pieces'); for (structure_pieces, l(piece, direction, from, to) = _; //factor = 1- _i / config:'max_pieces' / 2; @@ -107,11 +107,11 @@ __structure_renderer(player_name) -> b = 255; a = 255; color = a+256*(b+256*(g+256*r)); - marker_box(from, to+1, 10, color); + marker_box(from, to+1, 15, color); ) ) ); - schedule(5, '__structure_renderer', player_name); + schedule(10, '__structure_renderer', player_name); ); __chunk_renderer(player_name) -> @@ -128,7 +128,7 @@ __chunk_renderer(player_name) -> for (range(-r,r), cz = _; ref_pos = ppos + l(16*cx,0,16*cz); if(has(config:'tasks':'slime_chunks') && in_slime_chunk(ref_pos), - player_distance = _euclidean(ppos, ref_pos+8); + player_distance = _euclidean(ppos, ref_pos); top_00 = ref_pos + l(0, top('terrain', ref_pos)+10, 0); top_11 = ref_pos + l(16, top('terrain', ref_pos+l(15,0,15))+10, 16); top_10 = ref_pos + l(16, top('terrain', ref_pos+l(15, 0, 0))+10, 0); @@ -140,12 +140,12 @@ __chunk_renderer(player_name) -> b = 30; a = max(0, 255-player_distance); color = a+256*(b+256*(g+256*r)); - marker_line(top_00, top_10, 10, color); - marker_line(top_10, top_11, 10, color); - marker_line(top_11, top_01, 10, color); - marker_line(top_01, top_00, 10, color); - marker_line(top_00, top_11, 10, color); - marker_line(top_01, top_10, 10, color); + marker_line(top_00, top_10, 15, color); + marker_line(top_10, top_11, 15, color); + marker_line(top_11, top_01, 15, color); + marker_line(top_01, top_00, 15, color); + marker_line(top_00, top_11, 15, color); + marker_line(top_01, top_10, 15, color); //particle_line(part, top_00, top_10, density); //particle_line(part, top_10, top_11, density); @@ -157,5 +157,5 @@ __chunk_renderer(player_name) -> ) ) ); - schedule(5, '__chunk_renderer', player_name); + schedule(10, '__chunk_renderer', player_name); ) \ No newline at end of file From a86c127c72a31cd44676fec26afeb062a093e88a Mon Sep 17 00:00:00 2001 From: gnembon Date: Mon, 1 Jun 2020 03:01:39 -0300 Subject: [PATCH 157/198] added params and changed syntax for draw_shape --- .../carpet/network/ClientNetworkHandler.java | 10 +- .../java/carpet/script/CarpetExpression.java | 108 ++-- .../carpet/script/utils/ShapeDispatcher.java | 473 +++++++++++++++--- .../carpet/script/utils/ShapesRenderer.java | 35 +- .../carpet/script/value/NumericValue.java | 4 + .../assets/carpet/scripts/overlay.sc | 20 +- 6 files changed, 461 insertions(+), 189 deletions(-) diff --git a/src/main/java/carpet/network/ClientNetworkHandler.java b/src/main/java/carpet/network/ClientNetworkHandler.java index 7c1336c3..96524117 100644 --- a/src/main/java/carpet/network/ClientNetworkHandler.java +++ b/src/main/java/carpet/network/ClientNetworkHandler.java @@ -11,7 +11,6 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; import net.minecraft.network.packet.c2s.play.CustomPayloadC2SPacket; import net.minecraft.util.PacketByteBuf; -import net.minecraft.world.dimension.DimensionType; import java.util.HashMap; import java.util.Map; @@ -38,14 +37,7 @@ public class ClientNetworkHandler put("TickRate", (p, t) -> TickSpeed.tickrate(((AbstractNumberTag)t).getFloat(), false)); put("renderShape", (p, t) -> { if (CarpetClient.shapes != null) - { - CompoundTag boxData = (CompoundTag)t; - CarpetClient.shapes.addShape( - boxData.getString("type"), - DimensionType.byRawId(boxData.getInt("dim")), - boxData - ); - } + CarpetClient.shapes.addShape((CompoundTag)t); }); }}; diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 42bad5a4..d9198cb1 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -2651,94 +2651,46 @@ public class CarpetExpression this.expr.alias("particle_rect", "particle_box"); - this.expr.addLazyFunction("marker_box", -1, (c, t, lv) -> + this.expr.addLazyFunction("draw_shape", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; - Vector3Argument from = Vector3Argument.findIn(cc, lv, 0); - Vector3Argument to = Vector3Argument.findIn(cc, lv, from.offset); - int duration = 10; - int color = -1; // hwite - ServerPlayerEntity player = null; - - if (lv.size() > to.offset+0 ) + if (lv.size() < 3) throw new InternalExpressionException("'draw_shape' takes at least three parameters, shape name, duration, and its params"); + String shapeType = lv.get(0).evalValue(c).getString(); + Value duration = NumericValue.asNumber(lv.get(1).evalValue(c)); + Map params; + if (lv.size() == 3) { - duration = NumericValue.asNumber(lv.get(to.offset).evalValue(c)).getInt(); - if (duration <= 0) + Value paramValue = lv.get(2).evalValue(c); + if (paramValue instanceof MapValue) { - throw new InternalExpressionException("Particle density should be positive"); + params = new HashMap<>(); + ((MapValue) paramValue).getMap().entrySet().forEach(e -> params.put(e.getKey().getString(),e.getValue())); } - if (lv.size() > to.offset + 1) + else if (paramValue instanceof ListValue) { - color = NumericValue.asNumber(lv.get(to.offset+1).evalValue(c)).getInt(); - - - if (lv.size() > to.offset + 2) - { - Value playerValue = lv.get(to.offset + 2).evalValue(c); - if (playerValue instanceof EntityValue) - { - Entity e = ((EntityValue) playerValue).getEntity(); - if (!(e instanceof ServerPlayerEntity)) - throw new InternalExpressionException("'particle_box' player argument has to be a player"); - player = (ServerPlayerEntity) e; - } - else - { - player = cc.s.getMinecraftServer().getPlayerManager().getPlayer(playerValue.getString()); - } - } + params = ShapeDispatcher.parseParams(((ListValue) paramValue).getItems()); } + else throw new InternalExpressionException("Parameters for 'draw_shape' need to be defined either in a list or a map"); + } + else + { + List paramList = new ArrayList<>(); + for (int i=2; i < lv.size(); i++) paramList.add(lv.get(i).evalValue(c)); + params = ShapeDispatcher.parseParams(paramList); + } + params.putIfAbsent("dim", new StringValue(cc.s.getWorld().getDimension().getType().toString())); + params.putIfAbsent("duration", duration); + + ShapeDispatcher.ExpiringShape shape = ShapeDispatcher.create(cc, shapeType, params); + ServerPlayerEntity player = null; + if (params.containsKey("player")) + { + player = (ServerPlayerEntity) ((EntityValue)params.get("player")).getEntity(); } ShapeDispatcher.sendShape( (player==null)?cc.s.getWorld().getPlayers():Collections.singletonList(player), - cc.s.getWorld().getDimension().getType(), - new ShapeDispatcher.Box(duration, from.vec, to.vec, color) - ); - return LazyValue.TRUE; - }); - - this.expr.addLazyFunction("marker_line", -1, (c, t, lv) -> - { - CarpetContext cc = (CarpetContext)c; - Vector3Argument from = Vector3Argument.findIn(cc, lv, 0); - Vector3Argument to = Vector3Argument.findIn(cc, lv, from.offset); - int duration = 10; - int color = -1; // hwite - ServerPlayerEntity player = null; - - if (lv.size() > to.offset+0 ) - { - duration = NumericValue.asNumber(lv.get(to.offset).evalValue(c)).getInt(); - if (duration <= 0) - { - throw new InternalExpressionException("Particle density should be positive"); - } - if (lv.size() > to.offset + 1) - { - color = NumericValue.asNumber(lv.get(to.offset+1).evalValue(c)).getInt(); - - - if (lv.size() > to.offset + 2) - { - Value playerValue = lv.get(to.offset + 2).evalValue(c); - if (playerValue instanceof EntityValue) - { - Entity e = ((EntityValue) playerValue).getEntity(); - if (!(e instanceof ServerPlayerEntity)) - throw new InternalExpressionException("'particle_box' player argument has to be a player"); - player = (ServerPlayerEntity) e; - } - else - { - player = cc.s.getMinecraftServer().getPlayerManager().getPlayer(playerValue.getString()); - } - } - } - } - ShapeDispatcher.sendShape( - (player==null)?cc.s.getWorld().getPlayers():Collections.singletonList(player), - cc.s.getWorld().getDimension().getType(), - new ShapeDispatcher.Line(duration, from.vec, to.vec, color) + shape, + params ); return LazyValue.TRUE; }); diff --git a/src/main/java/carpet/script/utils/ShapeDispatcher.java b/src/main/java/carpet/script/utils/ShapeDispatcher.java index e898974d..e37e5245 100644 --- a/src/main/java/carpet/script/utils/ShapeDispatcher.java +++ b/src/main/java/carpet/script/utils/ShapeDispatcher.java @@ -1,16 +1,34 @@ package carpet.script.utils; +import carpet.CarpetSettings; import carpet.network.ServerNetworkHandler; +import carpet.script.CarpetContext; import carpet.script.Expression; import carpet.script.exception.InternalExpressionException; +import carpet.script.value.BlockValue; +import carpet.script.value.EntityValue; +import carpet.script.value.ListValue; +import carpet.script.value.NumericValue; +import carpet.script.value.StringValue; +import carpet.script.value.Value; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.command.arguments.ParticleArgumentType; +import net.minecraft.entity.Entity; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.IntTag; +import net.minecraft.nbt.StringTag; +import net.minecraft.nbt.Tag; import net.minecraft.particle.ParticleEffect; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; +import net.minecraft.util.registry.Registry; import net.minecraft.world.dimension.DimensionType; import java.util.Collections; @@ -18,7 +36,11 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Optional; +import java.util.Set; import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; import static java.lang.Math.sqrt; @@ -26,7 +48,7 @@ public class ShapeDispatcher { private static final Map particleCache = new HashMap<>(); - public static void sendShape(List players, DimensionType dim, ExpiringShape shape) + public static void sendShape(List players, ExpiringShape shape, Map params) { Consumer alternative = null; CompoundTag tag = null; @@ -34,8 +56,7 @@ public class ShapeDispatcher { if (ServerNetworkHandler.validCarpetPlayers.contains(player)) { - if (tag == null) tag = shape.toTag(); - tag.putInt("dim", dim.getRawId()); + if (tag == null) tag = ExpiringShape.toTag(params); ServerNetworkHandler.sendCustomCommand(player,"renderShape", tag); } else @@ -46,11 +67,6 @@ public class ShapeDispatcher } } - public static void sendBox(ServerPlayerEntity player, int duration, Vec3d from, Vec3d to, int color) - { - - } - public static ParticleEffect getParticleData(String name) { ParticleEffect particle = particleCache.get(name); @@ -68,32 +84,134 @@ public class ShapeDispatcher return particle; } + public static Map parseParams(List items) + { + // parses params from API function + if (items.size()%2 == 1) throw new InternalExpressionException("Shape parameters list needs to be of even size"); + Map param = new HashMap<>(); + int i = 0; + while(i < items.size()) + { + String name = items.get(i).getString(); + Value val = items.get(i+1); + param.put(name, val); + i += 2; + } + return param; + } + + public static ExpiringShape create(CarpetContext cc, String shapeType, Map userParams) + { + userParams.put("shape", new StringValue(shapeType)); + Map validatedParams = new HashMap<>(); + userParams.forEach((key, value) -> + { + Param param = Param.coders.get(key); + if (param==null) throw new InternalExpressionException("Unknown feature for shape: "+key); + validatedParams.put(key, param.validate(cc, value)); + }); + Function,ExpiringShape> factory = ExpiringShape.shapeProviders.get(shapeType); + if (factory == null) throw new InternalExpressionException("Unknown shape: "+shapeType); + return factory.apply(validatedParams); + } + + // client + public static ExpiringShape fromTag(CompoundTag tag) + { + Map options = new HashMap<>(); + for (String key : tag.getKeys()) + { + Function decoder = Param.decoders.get(key); + if (decoder==null) + { + CarpetSettings.LOG.error("Unknown parameter for shape: "+key); + return null; + } + Value decodedValue = decoder.apply(tag.get(key)); + options.put(key, decodedValue); + } + Value shapeValue = options.get("shape"); + if (shapeValue == null) + { + CarpetSettings.LOG.error("Shape id missing in "+ String.join(", ", tag.getKeys())); + return null; + } + Function,ExpiringShape> factory = ExpiringShape.shapeProviders.get(shapeValue.getString()); + if (factory == null) + { + CarpetSettings.LOG.error("Unknown shape: "+shapeValue.getString()); + return null; + } + try + { + return factory.apply(options); + } + catch (InternalExpressionException exc) + { + CarpetSettings.LOG.error(exc.getMessage()); + } + return null; + } public abstract static class ExpiringShape { + public static final Map,ExpiringShape>> shapeProviders = new HashMap, ExpiringShape>>(){{ + put("line", creator(Line::new)); + put("box", creator(Box::new)); + }}; + private static Function,ExpiringShape> creator(Supplier shapeFactory) + { + return o -> { + ExpiringShape shape = shapeFactory.get(); + shape.fromOptions(o); + return shape; + }; + } + protected float r, g, b, a; protected int color; protected int duration = 0; private int key; - public ExpiringShape(int duration, int color) + + protected ExpiringShape() { } + + public static CompoundTag toTag(Map params) { + CompoundTag tag = new CompoundTag(); + params.forEach((k, v) -> { + Tag valTag = Param.coders.get(k).toTag(v); + if (valTag != null) tag.put(k, valTag); + }); + return tag; + } + + private void fromOptions(Map options) + { + Set optional = optionalParams(); + Set required = requiredParams(); + Set all = Sets.union(optional, required); + if (!all.containsAll(options.keySet())) + throw new InternalExpressionException("Received unexpected parameters for shape: "+Sets.difference(options.keySet(), all)); + if (!options.keySet().containsAll(required)) + throw new InternalExpressionException("Missing required parameters for shape: "+Sets.difference(required, options.keySet())); + options.keySet().forEach(k ->{ + if (!Param.coders.get(k).appliesTo(this)) + throw new InternalExpressionException("Parameter "+k+" doesn't apply for shape "+options.get("shape").getString()); + }); + init(options); + } + + protected void init(Map options) + { + duration = NumericValue.asNumber(options.get("duration")).getInt(); + color = NumericValue.asNumber(options.getOrDefault("color", optional.get("color"))).getInt(); this.r = (float)(color >> 24 & 0xFF) / 255.0F; this.g = (float)(color >> 16 & 0xFF) / 255.0F; this.b = (float)(color >> 8 & 0xFF) / 255.0F; this.a = (float)(color & 0xFF) / 255.0F; - this.color = color; - this.duration = duration; key = 0; } - - public int getExpiry() { return duration; }; - public CompoundTag toTag() - { - CompoundTag tag = new CompoundTag(); - tag.putInt("color", color); - tag.putInt("duration", duration); - return tag; - }; + public int getExpiry() { return duration; } public abstract Consumer alternative(); public int key() { @@ -106,46 +224,40 @@ public class ShapeDispatcher int hash = 17; hash = 31*hash + color; return hash; - }; + } + // list of params that need to be there + private final Set required = ImmutableSet.of("duration", "shape", "dim"); + private final Map optional = ImmutableMap.of("color", new NumericValue(-1)); + protected Set requiredParams() {return required;} + // list of params that can be there, with defaults + protected Set optionalParams() {return optional.keySet();} } public static class Box extends ExpiringShape { + private final Set required = ImmutableSet.of("from", "to"); + private final Map optional = ImmutableMap.of(); + @Override + protected Set requiredParams() { return Sets.union(super.requiredParams(), required); } + @Override + protected Set optionalParams() { return Sets.union(super.optionalParams(), optional.keySet()); } + public Box() { } + float x1, y1, z1; float x2, y2, z2; - public Box(int duration, Vec3d from, Vec3d to, int color) - { - super(duration, color); - x1 = (float)from.x; - y1 = (float)from.y; - z1 = (float)from.z; - x2 = (float)to.x; - y2 = (float)to.y; - z2 = (float)to.z; - } - - - public static ExpiringShape fromTag(CompoundTag tag) - { - return new Box(tag.getInt("duration"), - new Vec3d(tag.getFloat("x1"), tag.getFloat("y1"), tag.getFloat("z1")), - new Vec3d(tag.getFloat("x2"), tag.getFloat("y2"), tag.getFloat("z2")), - tag.getInt("color") - ); - } @Override - public CompoundTag toTag() + protected void init(Map options) { - CompoundTag tag = super.toTag(); - tag.putFloat("x1", x1); - tag.putFloat("y1", y1); - tag.putFloat("z1", z1); - tag.putFloat("x2", x2); - tag.putFloat("y2", y2); - tag.putFloat("z2", z2); - tag.putString("type", "debugBox"); - return tag; + super.init(options); + List from = ((ListValue)options.get("from")).getItems(); + x1 = NumericValue.asNumber(from.get(0)).getFloat(); + y1 = NumericValue.asNumber(from.get(1)).getFloat(); + z1 = NumericValue.asNumber(from.get(2)).getFloat(); + List to = ((ListValue)options.get("to")).getItems(); + x2 = NumericValue.asNumber(to.get(0)).getFloat(); + y2 = NumericValue.asNumber(to.get(1)).getFloat(); + z2 = NumericValue.asNumber(to.get(2)).getFloat(); } @Override @@ -197,41 +309,35 @@ public class ShapeDispatcher public static class Line extends ExpiringShape { + private final Set required = ImmutableSet.of("from", "to"); + private final Map optional = ImmutableMap.of(); + @Override + protected Set requiredParams() { return Sets.union(super.requiredParams(), required); } + @Override + protected Set optionalParams() { return Sets.union(super.optionalParams(), optional.keySet()); } + + private Line() + { + super(); + } + float x1, y1, z1; float x2, y2, z2; - public Line(int duration, Vec3d from, Vec3d to, int color) - { - super(duration, color); - x1 = (float)from.x; - y1 = (float)from.y; - z1 = (float)from.z; - x2 = (float)to.x; - y2 = (float)to.y; - z2 = (float)to.z; - } @Override - public CompoundTag toTag() + protected void init(Map options) { - CompoundTag tag = super.toTag(); - tag.putFloat("x1", x1); - tag.putFloat("y1", y1); - tag.putFloat("z1", z1); - tag.putFloat("x2", x2); - tag.putFloat("y2", y2); - tag.putFloat("z2", z2); - tag.putString("type", "debugLine"); - return tag; + super.init(options); + List from = ((ListValue)options.get("from")).getItems(); + x1 = NumericValue.asNumber(from.get(0)).getFloat(); + y1 = NumericValue.asNumber(from.get(1)).getFloat(); + z1 = NumericValue.asNumber(from.get(2)).getFloat(); + List to = ((ListValue)options.get("to")).getItems(); + x2 = NumericValue.asNumber(to.get(0)).getFloat(); + y2 = NumericValue.asNumber(to.get(1)).getFloat(); + z2 = NumericValue.asNumber(to.get(2)).getFloat(); } - public static ExpiringShape fromTag(CompoundTag tag) - { - return new Line(tag.getInt("duration"), - new Vec3d(tag.getFloat("x1"), tag.getFloat("y1"), tag.getFloat("z1")), - new Vec3d(tag.getFloat("x2"), tag.getFloat("y2"), tag.getFloat("z2")), - tag.getInt("color") - ); - } @Override public Consumer alternative() { @@ -261,6 +367,215 @@ public class ShapeDispatcher } } + public interface Param + { + Map> decoders = new HashMap>(){{ + put("shape", StringParam::decode); + put("dim", StringParam::decode); + put("duration", ShapeDispatcher::decodeInt); + put("color", ShapeDispatcher::decodeInt); + put("from", Vec3Param::decode); + put("to", Vec3Param::decode); + + }}; + Map coders = new HashMap(){{ + put("shape", new ShapeParam()); + put("player", new PlayerParam()); + put("dim", new DimensionParam()); + put("duration", new DurationParam()); + put("color", new ColorParam()); + put("from", new FromParam()); + put("to", new ToParam()); + }}; + Tag toTag(Value value); //validates value, returning null if not necessary to keep it and serialize + Value validate(CarpetContext cc, Value value); // makes sure the value is proper + boolean appliesTo(ExpiringShape shape); // check if applies to the shape + String identify(); + } + public static class PlayerParam implements Param + { + @Override // doesn't need to be converted + public Tag toTag(Value value) { return null; } + + @Override + public Value validate(CarpetContext cc, Value value) + { + ServerPlayerEntity player = EntityValue.getPlayerByValue(cc.s.getMinecraftServer(), value); + if (player == null) + throw new InternalExpressionException("'player' parameter needs to represent an existing player"); + return new EntityValue(player); + } + + @Override + public boolean appliesTo(ExpiringShape shape) { return true; } + @Override + public String identify() { return "player"; } + + public static Value decode(Tag tag) { throw new RuntimeException("player tag should not be passed to the client"); } + } + public abstract static class StringParam implements Param + { + @Override + public Tag toTag(Value value) { return StringTag.of(value.getString()); } + @Override + public Value validate(CarpetContext cc, Value value) { return value; } + public static Value decode(Tag tag) { return new StringValue(tag.asString()); } + } + + public static class DimensionParam extends StringParam + { + @Override + public Value validate(CarpetContext cc, Value value) + { + String dimStr = value.getString(); + Optional dimOp = Registry.DIMENSION_TYPE.getOrEmpty(new Identifier(dimStr)); + if (!dimOp.isPresent()) throw new InternalExpressionException("Unknown dimension "+dimStr); + return value; + } + @Override + public boolean appliesTo(ExpiringShape shape) { return true; } + @Override + public String identify() { return "dim"; } + } + public static class ShapeParam extends StringParam + { + @Override + public Value validate(CarpetContext cc, Value value) + { + String shape = value.getString(); + if (!ExpiringShape.shapeProviders.containsKey(shape)) + throw new InternalExpressionException("Unknown shape: "+shape); + return value; + } + @Override + public boolean appliesTo(ExpiringShape shape) { return true; } + @Override + public String identify() { return "shape"; } + } + public static abstract class NumericParam implements Param + { + @Override + public Tag toTag(Value value) { return IntTag.of(NumericValue.asNumber(value).getInt()); } + @Override + public Value validate(CarpetContext cc, Value value) + { + if (!(value instanceof NumericValue)) + throw new InternalExpressionException("'" + identify() + "' needs to be a number"); + return value; + } + } + public static abstract class PositiveParam extends NumericParam + { + @Override public Value validate(CarpetContext cc, Value value) + { + Value ret = super.validate(cc, value); + if (((NumericValue)ret).getDouble()<=0) throw new InternalExpressionException("'"+identify()+"' should be positive"); + return ret; + } + } + + public static Value decodeInt(Tag tag) { return new NumericValue(((IntTag)tag).getInt()); } + public static class DurationParam extends PositiveParam + { + @Override + public boolean appliesTo(ExpiringShape shape) { return true; } + @Override + public String identify() { return "duration"; } + } + + public static abstract class Vec3Param implements Param + { + + public abstract boolean roundsUpForBlocks(); + public abstract String identify(); + + @Override + public Value validate(CarpetContext cc, Value value) + { + if (value instanceof BlockValue) + { + BlockPos pos = ((BlockValue) value).getPos(); + int offset = roundsUpForBlocks()?1:0; + return ListValue.of( + new NumericValue(pos.getX()+offset), + new NumericValue(pos.getY()+offset), + new NumericValue(pos.getZ()+offset) + ); + } + if (value instanceof ListValue) + { + List values = ((ListValue) value).getItems(); + if (values.size()!=3) throw new InternalExpressionException("'"+identify()+"' requires 3 numerical values"); + for (Value component : values) + { + if (!(component instanceof NumericValue)) + throw new InternalExpressionException("'"+identify()+"' requires 3 numerical values"); + } + return value; + } + if (value instanceof EntityValue) + { + Entity e = ((EntityValue) value).getEntity(); + return ListValue.of( + new NumericValue(e.getX()), + new NumericValue(e.getY()), + new NumericValue(e.getZ()) + ); + } + CarpetSettings.LOG.error("Value: "+value.getString()); + throw new InternalExpressionException("'"+identify()+"' requires a triple, block or entity to indicate position"); + } + + public static Value decode(Tag tag) + { + CompoundTag ctag = (CompoundTag)tag; + return ListValue.of( + new NumericValue(ctag.getFloat("x")), + new NumericValue(ctag.getFloat("y")), + new NumericValue(ctag.getFloat("z")) + ); + } + @Override + public Tag toTag(Value value) + { + List lv = ((ListValue)value).getItems(); + CompoundTag tag = new CompoundTag(); + tag.putFloat("x", NumericValue.asNumber(lv.get(0)).getFloat()); + tag.putFloat("y", NumericValue.asNumber(lv.get(1)).getFloat()); + tag.putFloat("z", NumericValue.asNumber(lv.get(2)).getFloat()); + return tag; + } + } + public static class ColorParam extends NumericParam + { + @Override + public boolean appliesTo(ExpiringShape shape) { return true; } + @Override + public String identify() { return "color"; } + } + + public static class FromParam extends Vec3Param + { + @Override + public boolean appliesTo(ExpiringShape shape) { return (shape instanceof Line) || (shape instanceof Box); } + @Override + public boolean roundsUpForBlocks() { return false; } + @Override + public String identify() { return "from"; } + } + + public static class ToParam extends Vec3Param + { + @Override + public boolean appliesTo(ExpiringShape shape) { return (shape instanceof Line) || (shape instanceof Box); } + @Override + public boolean roundsUpForBlocks() { return true; } + @Override + public String identify() { return "to"; } + } + + + private static boolean isStraight(Vec3d from, Vec3d to, double density) { if ( (from.x == to.x && from.y == to.y) || (from.x == to.x && from.z == to.z) || (from.y == to.y && from.z == to.z)) diff --git a/src/main/java/carpet/script/utils/ShapesRenderer.java b/src/main/java/carpet/script/utils/ShapesRenderer.java index d6db7387..4bb50aa7 100644 --- a/src/main/java/carpet/script/utils/ShapesRenderer.java +++ b/src/main/java/carpet/script/utils/ShapesRenderer.java @@ -11,6 +11,8 @@ import net.minecraft.client.render.VertexFormats; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.Entity; import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; import net.minecraft.world.IWorld; import net.minecraft.world.dimension.DimensionType; import org.lwjgl.opengl.GL11; @@ -24,11 +26,11 @@ public class ShapesRenderer private final Map>> shapes; private MinecraftClient client; - private Map>> renderedShapes - = new HashMap>>() + private Map>> renderedShapes + = new HashMap>>() {{ - put("debugBox", RenderedBox::new); - put("debugLine", RenderedLine::new); + put("line", RenderedLine::new); + put("box", RenderedBox::new); }}; public ShapesRenderer(MinecraftClient minecraftClient) @@ -82,17 +84,24 @@ public class ShapesRenderer RenderSystem.shadeModel(7424); } - public void addShape(String type, DimensionType dim, CompoundTag tag) + public void addShape(CompoundTag tag) { - BiFunction> shapeFactory; - shapeFactory = renderedShapes.get(type); + //CarpetSettings.LOG.error("Received tag: "+tag.asString()); + ShapeDispatcher.ExpiringShape shape = ShapeDispatcher.fromTag(tag); + if (shape == null) return; + BiFunction> shapeFactory; + shapeFactory = renderedShapes.get(tag.getString("shape")); + + + if (shapeFactory == null) { - CarpetSettings.LOG.error("Unrecognized shape: "+type); + CarpetSettings.LOG.error("Unrecognized shape: "+tag.getString("shape")); } else { - RenderedShape rshape = shapeFactory.apply(client, tag); + RenderedShape rshape = shapeFactory.apply(client, shape); + DimensionType dim = Registry.DIMENSION_TYPE.get(new Identifier(tag.getString("dim"))); int key = rshape.key(); synchronized (shapes) { @@ -144,9 +153,9 @@ public class ShapesRenderer public static class RenderedBox extends RenderedShape { - public RenderedBox(MinecraftClient client, CompoundTag boxData) + private RenderedBox(MinecraftClient client, ShapeDispatcher.ExpiringShape shape) { - super(client, (ShapeDispatcher.Box)ShapeDispatcher.Box.fromTag(boxData)); + super(client, (ShapeDispatcher.Box)shape); } @Override @@ -177,9 +186,9 @@ public class ShapesRenderer public static class RenderedLine extends RenderedShape { - public RenderedLine(MinecraftClient client, CompoundTag boxData) + public RenderedLine(MinecraftClient client, ShapeDispatcher.ExpiringShape shape) { - super(client, (ShapeDispatcher.Line)ShapeDispatcher.Line.fromTag(boxData)); + super(client, (ShapeDispatcher.Line)shape); } @Override public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) diff --git a/src/main/java/carpet/script/value/NumericValue.java b/src/main/java/carpet/script/value/NumericValue.java index 087d0f2e..fa6a58c9 100644 --- a/src/main/java/carpet/script/value/NumericValue.java +++ b/src/main/java/carpet/script/value/NumericValue.java @@ -56,6 +56,10 @@ public class NumericValue extends Value { return value; } + public float getFloat() + { + return value.floatValue(); + } public static long floor(double double_1) { long int_1 = (long)double_1; diff --git a/src/main/resources/assets/carpet/scripts/overlay.sc b/src/main/resources/assets/carpet/scripts/overlay.sc index 95d4fca5..3adebc96 100644 --- a/src/main/resources/assets/carpet/scripts/overlay.sc +++ b/src/main/resources/assets/carpet/scripts/overlay.sc @@ -95,7 +95,7 @@ __structure_renderer(player_name) -> total_size = _euclidean(from, to); density = max(10, total_size/10); //particle_box('dust 0 1 1 2', from, to+1, density); - marker_box(from, to+1, 15, 0x00FFFFFF ); + draw_shape('box', 15, 'from', from, 'to', to+1, 'color', 0x00FFFFFF); structure_pieces = slice(sort_key(structure_pieces, _euclidean_sq((_:2+_:3)/2,ppos)), 0, config:'max_pieces'); for (structure_pieces, l(piece, direction, from, to) = _; //factor = 1- _i / config:'max_pieces' / 2; @@ -107,7 +107,7 @@ __structure_renderer(player_name) -> b = 255; a = 255; color = a+256*(b+256*(g+256*r)); - marker_box(from, to+1, 15, color); + draw_shape('box', 15, 'from', from, 'to', to+1, 'color', color); ) ) ); @@ -133,20 +133,20 @@ __chunk_renderer(player_name) -> top_11 = ref_pos + l(16, top('terrain', ref_pos+l(15,0,15))+10, 16); top_10 = ref_pos + l(16, top('terrain', ref_pos+l(15, 0, 0))+10, 0); top_01 = ref_pos + l(0, top('terrain', ref_pos+l(0, 0, 15))+10, 16); - part = 'dust 0.2 0.8 0.2 2'; - density = 2+player_distance/2; r = 30; g = 220; b = 30; a = max(0, 255-player_distance); color = a+256*(b+256*(g+256*r)); - marker_line(top_00, top_10, 15, color); - marker_line(top_10, top_11, 15, color); - marker_line(top_11, top_01, 15, color); - marker_line(top_01, top_00, 15, color); - marker_line(top_00, top_11, 15, color); - marker_line(top_01, top_10, 15, color); + draw_shape('box', 15, 'from', top_00, 'to', top_10, 'color', color); + draw_shape('box', 15, 'from', top_10, 'to', top_11, 'color', color); + draw_shape('box', 15, 'from', top_11, 'to', top_01, 'color', color); + draw_shape('box', 15, 'from', top_01, 'to', top_00, 'color', color); + draw_shape('box', 15, 'from', top_00, 'to', top_11, 'color', color); + draw_shape('box', 15, 'from', top_01, 'to', top_10, 'color', color); + //part = 'dust 0.2 0.8 0.2 2'; + //density = 2+player_distance/2; //particle_line(part, top_00, top_10, density); //particle_line(part, top_10, top_11, density); //particle_line(part, top_11, top_01, density); From 0d341a13625385d720a22221cd08c620688ce248 Mon Sep 17 00:00:00 2001 From: gnembon Date: Mon, 1 Jun 2020 03:27:34 -0300 Subject: [PATCH 158/198] overlay fixes --- src/main/resources/assets/carpet/scripts/overlay.sc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/resources/assets/carpet/scripts/overlay.sc b/src/main/resources/assets/carpet/scripts/overlay.sc index 3adebc96..366d0a7a 100644 --- a/src/main/resources/assets/carpet/scripts/overlay.sc +++ b/src/main/resources/assets/carpet/scripts/overlay.sc @@ -138,12 +138,12 @@ __chunk_renderer(player_name) -> b = 30; a = max(0, 255-player_distance); color = a+256*(b+256*(g+256*r)); - draw_shape('box', 15, 'from', top_00, 'to', top_10, 'color', color); - draw_shape('box', 15, 'from', top_10, 'to', top_11, 'color', color); - draw_shape('box', 15, 'from', top_11, 'to', top_01, 'color', color); - draw_shape('box', 15, 'from', top_01, 'to', top_00, 'color', color); - draw_shape('box', 15, 'from', top_00, 'to', top_11, 'color', color); - draw_shape('box', 15, 'from', top_01, 'to', top_10, 'color', color); + draw_shape('line', 15, 'from', top_00, 'to', top_10, 'color', color); + draw_shape('line', 15, 'from', top_10, 'to', top_11, 'color', color); + draw_shape('line', 15, 'from', top_11, 'to', top_01, 'color', color); + draw_shape('line', 15, 'from', top_01, 'to', top_00, 'color', color); + draw_shape('line', 15, 'from', top_00, 'to', top_11, 'color', color); + draw_shape('line', 15, 'from', top_01, 'to', top_10, 'color', color); //part = 'dust 0.2 0.8 0.2 2'; //density = 2+player_distance/2; From 59be8b3fb4d44fed4438098a4b2bb17665c52eeb Mon Sep 17 00:00:00 2001 From: gnembon Date: Mon, 1 Jun 2020 12:05:01 -0300 Subject: [PATCH 159/198] redocced to draw_shape --- docs/scarpet/api/Auxiliary.md | 42 ++++++++++++++----- .../java/carpet/script/CarpetExpression.java | 2 +- .../carpet/script/utils/ShapeDispatcher.java | 10 ++--- 3 files changed, 37 insertions(+), 17 deletions(-) diff --git a/docs/scarpet/api/Auxiliary.md b/docs/scarpet/api/Auxiliary.md index 7d9da627..a8b097dc 100644 --- a/docs/scarpet/api/Auxiliary.md +++ b/docs/scarpet/api/Auxiliary.md @@ -36,19 +36,41 @@ supplied, only that player will receive particles. ## Markers -### `marker_box(from, to, duration?, color?, player?)` +### `draw_shape(shape, duration, key?, value?, ... )`, `draw_shape(shape, duration, l(key?, value?, ... ))`, `draw_shape(shape, duration, attribute_map)` -Draws a box with `from` and `to` corners in the box. The boxes will dissipate after `duration` ticks (defaults to 10). -The color is an integer that indicate red, green, blue and alpha components in the form of `0xRRGGBBAA`, with the -default of `-1`, so white opaque, or `0xFFFFFFFF`. If player is specified, only displays for that player, otherwise all -players will see them. `marker_box` requires proper client synchronization to display these, and on non-supported -clients, the box will be replaced with close matching dust particles, so using of `marker_box` is safe to use for -scripts regardless who is targeted. The only consideration is that with vanilla clients, duration of particles cannot -be controlled, and last whatever the original particles do. +Draws a shape in the world that will expire in `duration` ticks. Other attributes of the shape should be provided as +consecutive key - value argument pairs, either as next arguments, or packed in a list, or supplied as a proper key-value +`map`. Arguments may include shared shape attributes, which are all optional, as well as shape-specific attributes, that +could be either optional or required. Shapes will draw properly on all carpet clients. Other connected players that don't +have carpet installed will still be able to see the required shapes in the form of dust particles. Replacement shapes +are not required to follow all attributes precisely, but will allow vanilla clients to receive some experience of your +apps. One of the attributes that will definitely not be honored is the duration - particles will be send once +per shape and last whatever they typically last in the game. -### `marker_line(from, to, duration?, color?, player?)` +Shapes will fail to draw and raise a runtime error if not all its required parameters +are specified and all available shapes have some parameters that are required, so make sure to have them in place: -Draws a marker line on client's screen. Uses similar setup as `marker_box`. +On the client, shapes can recognize that they are being redrawn again with the same parameters, disregarding the +duration parameter. This updates the expiry on the drawn shape to the new value, instead of adding new shape in its +place. This can be used for toggling the shapes on and off that has been send previously with very large durations, +or simply refresh the shapes periodically in more dynamic applications. + +Optional shared shape attributes: + * `color` - integer value indicating the main color of the shape in the form of red, green, blue and alpha components + in the form of `0xRRGGBBAA`, with the default of `-1`, so white opaque, or `0xFFFFFFFF`. + * `player` - name or player entity to send the shape to. If specified, the shapes will appear only for the specified + player, otherwise it will be send to all players in the dimension. + +Available shapes: + * `'line'` - draws a straight line between two points + * Required attributes: + * `from` - triple coordinates, entity, or block value indicating one end of the line + * `to` - other end of the line, same format as `from` + + * `'box'` - draws a box with corners in specified points + * Required attributes: + * `from` - triple coordinates, entity, or block value indicating one corner of the box + * `to` - other corner, same format as `from` ### `create_marker(text, pos, rotation?, block?)` diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index d9198cb1..e14eeb8b 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -2685,7 +2685,7 @@ public class CarpetExpression ServerPlayerEntity player = null; if (params.containsKey("player")) { - player = (ServerPlayerEntity) ((EntityValue)params.get("player")).getEntity(); + player = (ServerPlayerEntity)((EntityValue)params.get("player")).getEntity(); } ShapeDispatcher.sendShape( (player==null)?cc.s.getWorld().getPlayers():Collections.singletonList(player), diff --git a/src/main/java/carpet/script/utils/ShapeDispatcher.java b/src/main/java/carpet/script/utils/ShapeDispatcher.java index e37e5245..0aaadb12 100644 --- a/src/main/java/carpet/script/utils/ShapeDispatcher.java +++ b/src/main/java/carpet/script/utils/ShapeDispatcher.java @@ -103,16 +103,14 @@ public class ShapeDispatcher public static ExpiringShape create(CarpetContext cc, String shapeType, Map userParams) { userParams.put("shape", new StringValue(shapeType)); - Map validatedParams = new HashMap<>(); - userParams.forEach((key, value) -> - { + userParams.keySet().forEach(key -> { Param param = Param.coders.get(key); if (param==null) throw new InternalExpressionException("Unknown feature for shape: "+key); - validatedParams.put(key, param.validate(cc, value)); + userParams.put(key, param.validate(cc, userParams.get(key))); }); Function,ExpiringShape> factory = ExpiringShape.shapeProviders.get(shapeType); if (factory == null) throw new InternalExpressionException("Unknown shape: "+shapeType); - return factory.apply(validatedParams); + return factory.apply(userParams); } // client @@ -227,7 +225,7 @@ public class ShapeDispatcher } // list of params that need to be there private final Set required = ImmutableSet.of("duration", "shape", "dim"); - private final Map optional = ImmutableMap.of("color", new NumericValue(-1)); + private final Map optional = ImmutableMap.of("color", new NumericValue(-1), "player", Value.NULL); protected Set requiredParams() {return required;} // list of params that can be there, with defaults protected Set optionalParams() {return optional.keySet();} From 78e7d9618dcaab89cf505f58798cecec0e201060 Mon Sep 17 00:00:00 2001 From: whats2000 <60466660+whats2000@users.noreply.github.com> Date: Tue, 2 Jun 2020 03:39:08 +0800 Subject: [PATCH 160/198] Create zh_tw.json (#302) * Create zh_tw.json A traslate for traditonal Chinese * Update zh_tw.json Fixed some words is in wrong grammar * Update CarpetSettings.java --- src/main/java/carpet/CarpetSettings.java | 2 +- .../resources/assets/carpet/lang/zh_tw.json | 234 ++++++++++++++++++ 2 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 src/main/resources/assets/carpet/lang/zh_tw.json diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index a198b438..b66c7838 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -61,7 +61,7 @@ public class CarpetSettings @Rule( desc = "sets the language for carpet", category = FEATURE, - options = {"none", "zh_cn"}, + options = {"none", "zh_cn", "zh_tw"}, strict = false, validate = LanguageValidator.class ) diff --git a/src/main/resources/assets/carpet/lang/zh_tw.json b/src/main/resources/assets/carpet/lang/zh_tw.json new file mode 100644 index 00000000..a3ede4a1 --- /dev/null +++ b/src/main/resources/assets/carpet/lang/zh_tw.json @@ -0,0 +1,234 @@ +{ + "rule.antiCheatDisabled.name": "關閉伺服器作弊檢測", + "rule.antiCheatDisabled.desc": "防止玩家因為“本伺服器不允許飛行”,“移動速度過快”等原因被請出伺服器", + + "rule.carpets.name": "放置地毯顯示進階數據", + "rule.carpets.desc": "通過把地毯放置在地上取得更進階信息", + + "rule.combineXPOrbs.name": "合併小經驗球", + "rule.combineXPOrbs.desc": "會將大量的小經驗球合併成等效的大經驗球", + + "rule.commandCameramode.name": "旁觀者模式", + "rule.commandCameramode.desc": "允許玩家使用/c切換成旁觀者模式,利用/s切換回生存模式", + "rule.commandCameramode.extra.0": "/c及/s不需要op權限也可使用", + + "rule.commandDistance.name": "距離測定", + "rule.commandDistance.desc": "使用/distance指令測定兩點的距離", + "rule.commandDistance.extra.0": "可以使用放置棕色地毯來使用此功能,前提是“放置地毯顯示進階數據”已啟用", + + "rule.commandDraw.name": "繪製圖形", + "rule.commandDraw.desc": "使用/draw指令以允許繪製一些簡易圖形", + + "rule.commandInfo.name": "獲取方塊進階資訊", + "rule.commandInfo.desc": "允許使用/info指令以獲得方塊進階資訊", + "rule.commandInfo.extra.0": "可以使用放置灰色地毯來使用此功能,前提是“放置地毯顯示進階數據”已啟用", + + "rule.commandLog.name": "遊戲數據追蹤器", + "rule.commandLog.desc": "允許使用/log指令使在Tab欄位追蹤遊戲部分數據", + + "rule.commandPerimeterInfo.name": "刷怪區域追蹤器", + "rule.commandPerimeterInfo.desc": "允許使用/perimeterinfo指令以探查周圍可生怪區域", + + "rule.commandPlayer.name": "機器人控制", + "rule.commandPlayer.desc": "允許使用/player指令以控制/召喚已存在的玩家id作為機器人", + + "rule.commandScript.name": "地毯腳本控制器", + "rule.commandScript.desc": "允許使用/script相關指令", + "rule.commandScript.extra.0": "一個Scarpet程式語言的遊戲內API", + + "rule.commandSpawn.name": "刷怪追蹤器", + "rule.commandSpawn.desc": "允許使用/spawn指令用於怪物生成追蹤", + + "rule.commandTick.name": "遊戲時鐘控制器", + "rule.commandTick.desc": "允許使用/tick指令控制遊戲內的伺服器端運行速度", + + "rule.commandTrackAI.name": "AI追蹤器", + "rule.commandTrackAI.desc": "允許使用/track指令以追蹤生物的AI", + + "rule.ctrlQCraftingFix.name": "ctrlQ合成修復", + "rule.ctrlQCraftingFix.desc": "在合成時允許使用ctrl+Q快捷鍵扔出結果格內所有物品", + + "rule.customMOTD.name": "MOTD更改", + "rule.customMOTD.desc": "設置一個不同的MOTD信息", + "rule.customMOTD.extra.0": "設置成'_'時將採用默認的MOTD(從server.properties中讀取的)", + + "rule.defaultLoggers.name": "默認開啟的遊戲數據追蹤器", + "rule.defaultLoggers.desc": "為所有新加入的玩家設置部分遊戲數據追蹤器默認為開啟狀態", + "rule.defaultLoggers.extra.0": "比如設置'tps,mobcaps'最為默認遊戲數據追蹤", + + "rule.desertShrubs.name": "樹苗在沙漠中乾枯", + "rule.desertShrubs.desc": "樹苗將在附近無水源狀態的沙漠生態群系變成枯灌木", + + "rule.disableSpawnChunks.name": "允許出生點區塊被卸載", + "rule.disableSpawnChunks.desc": "允許出生點區塊被卸載", + + "rule.explosionNoBlockDamage.name": "爆炸不破壞方塊", + "rule.explosionNoBlockDamage.desc": "任何形式的爆炸都無法摧毀方塊", + + "rule.extremeBehaviours.name": "隨機參數極端化", + "rule.extremeBehaviours.desc": "大幅度提升極端情況出現的概率,僅用於測試", + "rule.extremeBehaviours.extra.0": "發射器和投擲器將使用最大隨機刻", + + "rule.fastRedstoneDust.name": "紅石粉卡頓優化", + "rule.fastRedstoneDust.desc": "紅石粉卡頓優化 作者 Theosib", + + "rule.fillLimit.name": "fill/clone上限更改", + "rule.fillLimit.desc": "將fill/clone上限更改為自己設定的值", + "rule.fillLimit.extra.0": "你必須在1-2千萬之間取一個整數值", + + "rule.fillUpdates.name": "fill更新設置", + "rule.fillUpdates.desc": "fill/clone/setblock指令以及結構方塊執行時是否產生更新", + "rule.fillUpdates.extra.0": "設置為true時有更新 設置為false時為無更新", + + "rule.flatWorldStructureSpawning.name": "特定建築怪在超平坦世界生成", + "rule.flatWorldStructureSpawning.desc": "允許特定建築的怪物在超平坦世界生成", + + "rule.flippinCactus.name": "仙人掌扳手", + "rule.flippinCactus.desc": "允許使用仙人掌調整方塊朝向,並且不會造成更新", + + "rule.hardcodeTNTangle.name": "強制TNT角度", + "rule.hardcodeTNTangle.desc": "把TNT水平隨機角度設定為固定值,可用於測試機器", + "rule.hardcodeTNTangle.extra.0": "默認為-1,必須在0與360之間,或者-1", + + "rule.hopperCounters.name": "漏斗計數器", + "rule.hopperCounters.desc": "漏斗指向的羊毛方塊會計算吸收的物品並清除", + "rule.hopperCounters.extra.0": "在羊毛方塊上放置紅色或綠色地毯,使用/counter指令可啟用", + "rule.hopperCounters.extra.1": "使用 /counter reset重置計數器,使用/counter 查詢資訊", + "rule.hopperCounters.extra.2": "在生存模式,在同色羊毛上放置綠色地毯可以查詢,放紅色地毯重置", + "rule.hopperCounters.extra.3": "數據是全伺服器玩家共享的,並且有16色可以使用", + "rule.hopperCounters.extra.4": "物品會被銷毀,每個漏斗每tick銷毀一組物品", + + "rule.huskSpawningInTemples.name": "屍殼在沙漠神殿裡生成", + "rule.huskSpawningInTemples.desc": "只有屍殼會在沙漠神殿生成", + + "rule.lagFreeSpawning.name": "延遲自然生成", + "rule.lagFreeSpawning.desc": "生物生成需要更少的CPU和RAM", + + "rule.leadFix.name": "栓繩修復", + "rule.leadFix.desc": "修復栓繩在未加載區塊中,變得不可見的問題", + + "rule.maxEntityCollisions.name": "最大實體擠壓數量", + "rule.maxEntityCollisions.desc": "設定最大實體擠壓限制,0表示無限大", + + "rule.mergeTNT.name": "合併TNT", + "rule.mergeTNT.desc": "合併靜止的點燃的tnt實體", + + "rule.missingTools.name": "工具缺失修復", + "rule.missingTools.desc": "活塞,玻璃和海綿可以使用合適的工具更快地破壞", + + "rule.movableBlockEntities.name": "容器方塊移動", + "rule.movableBlockEntities.desc": "活塞可以推動具有容器標籤的方塊,比如箱子,漏斗", + + "rule.onePlayerSleeping.name": "單個玩家睡覺跳過夜晚", + "rule.onePlayerSleeping.desc": "只要伺服器中其中一人睡覺即可跳過全伺服器夜晚", + + "rule.optimizedTNT.name": "TNT優化", + "rule.optimizedTNT.desc": "tnt在相同位置或者在流體裡,爆炸將造成更低延遲", + + "rule.persistentParrots.name": "鸚鵡停留", + "rule.persistentParrots.desc": "鸚鵡不會離開你的肩膀,除非你受到傷害", + + "rule.placementRotationFix.name": "放置旋轉問題修復", + "rule.placementRotationFix.desc": "修復玩家放置方塊時快速轉身造成的問題", + + "rule.pushLimit.name": "自訂義推動上限", + "rule.pushLimit.desc": "自訂義活塞推動上限", + "rule.pushLimit.extra.0": "你必須在1-1024中選取一個值,預設是12", + + "rule.quasiConnectivity.name": "半連接激活開關", + "rule.quasiConnectivity.desc": "活塞,發射器和投擲器在他們上方方塊激活時是否響應", + "rule.quasiConnectivity.extra.0": "設置為true為開啟 設置為false為禁用", + + "rule.railPowerLimit.name": "自訂義動力鐵軌激活距離", + "rule.railPowerLimit.desc": "動力鐵軌激活距離能在此更改", + "rule.railPowerLimit.extra.0": "你必須在1-1024中選取一個數值", + + "rule.renewableCoral.name": "可再生珊瑚", + "rule.renewableCoral.desc": "使用骨粉可催熟珊瑚以長成珊瑚方塊結構", + + "rule.renewableSponges.name": "可再生海綿", + "rule.renewableSponges.desc": "深海守衛將在被雷擊後變成遠古深海守衛", + + "rule.rotatorBlock.name": "仙人掌扳手發射器版", + "rule.rotatorBlock.desc": "發射器中的仙人掌可以旋轉方塊(盡可能以逆時針)", + + "rule.scriptsAutoload.name": "Scarpet腳本自動加載", + "rule.scriptsAutoload.desc": "在伺服器/世界加載的時候將會自動從世界文件中加載Scarpet腳本文件", + "rule.scriptsAutoload.extra.0": "/script指令必須為啟用狀態", + + "rule.shulkerSpawningInEndCities.name": "可重生界伏蚌", + "rule.shulkerSpawningInEndCities.desc": "界伏蚌將會在終界城市中重生", + + "rule.silverFishDropGravel.name": "蠹魚鑽出放塊掉落礫石", + "rule.silverFishDropGravel.desc": "蠹魚鑽出放塊時會掉落礫石", + + "rule.smoothClientAnimations.name": "更平暢玩家端動畫", + "rule.smoothClientAnimations.desc": "降低TPS設置時可以使玩家端動畫更加平暢", + "rule.smoothClientAnimations.extra.0": "僅在單人模式中生效,並且會降低玩家端運行速度", + + "rule.stackableShulkerBoxes.name": "可堆疊界伏盒", + "rule.stackableShulkerBoxes.desc": "空的界伏盒扔在地上時將會自動堆疊,直到堆疊為1組", + "rule.stackableShulkerBoxes.extra.0": "在物品GUI中,請使用shift鍵+單擊以移動整組界伏盒", + + "rule.summonNaturalLightning.name": "召喚閃電自然化", + "rule.summonNaturalLightning.desc": "召喚的閃電將具有自然生成時的特性", + + "rule.tntDoNotUpdate.name": "TNT放置時不會被更新", + "rule.tntDoNotUpdate.desc": "TNT在放置時不會產生任何方塊更新(不會激活)", + + "rule.tntPrimerMomentumRemoved.name": "移除TNT點燃時隨機動量", + "rule.tntPrimerMomentumRemoved.desc": "TNT點燃時的隨機動量將被移除", + + "rule.tntRandomRange.name": "TNT爆炸範圍設置", + "rule.tntRandomRange.desc": "設置TNT隨機爆炸範圍為一個固定的值,設為-1以禁用", + "rule.tntRandomRange.extra.0": "必須啟用optimizedTNT功能", + "rule.tntRandomRange.extra.1": "不能設置為負數,除了-1", + + "rule.unloadedEntityFix.name": "未加載實體修復", + "rule.unloadedEntityFix.desc": "進入或者被推入未加載區塊的實體不會消失", + + "rule.viewDistance.name": "自訂義視野", + "rule.viewDistance.desc": "改變伺服器端視野距離,設置為0以使用默認值", + "rule.viewDistance.extra.0": "你必須在0(使用伺服器默認設置)-32取一個整數", + + "rule.xpNoCooldown.name": "經驗球吸收無冷卻", + "rule.xpNoCooldown.desc": "玩家吸收經驗球不會有冷卻時間", + + "rule.portalSuffocationFix.name": "傳送門窒息修復", + "rule.portalSuffocationFix.desc": "使地獄傳送門正確地傳送實體", + "rule.portalSuffocationFix.extra.0": "傳送的實體將不再卡在黑曜石裡", + + "rule.portalCreativeDelay.name": "創造模式玩家地獄門傳送延遲", + "rule.portalCreativeDelay.desc": "創造模式下使用地獄傳送門將同生存時產生延遲", + + + "category.bugfix": "BUG修復", + "category.survival": "生存用", + "category.creative": "創造用", + "category.experimental": "實驗用", + "category.optimization": "優化", + "category.feature": "特性", + "category.command": "指令", + "category.tnt": "TNT", + "category.dispenser": "發射器", + "category.scarpet": "scarpet腳本程式語言", + "category.client": "玩家端", + + "ui.browse_categories": "瀏覽分類", + "ui.list_all_%(cat)s_settings": "列出所有 %s 選項", + "ui.version": "版本", + "ui.current_%(mod)s_settings": "目前啟用的 %s 選項", + "ui.switch_to": "切換至", + "ui.settings_are_locked": "選項被鎖定", + "ui.is_set_to": "被設置為", + "ui.unknown_rule": "未知的規則選項", + "ui.current_%(mod)s_startup_settings_from_%(conf)s": "目前啟用的%s選項,從%s中讀取得", + "ui.%(mod)s_settings_matching_'%(query)s'": "%s中符合\"%s\"的選項:", + "ui.all_%(mod)s_settings": "所有的%s選項", + "ui.tags": "分類", + "ui.change_permanently": "設為預設", + "ui.click_to_keep_the_settings_in_%(conf)s_to_save_across_restarts": "點擊此按鈕以使此選項保存於%s,重啟後依舊生效", + "ui.rule_%(rule)s_will_now_default_to_%(value)s": "規則%s將會被默認設置為%s", + "ui.current_value": "當前的值" + +} From 01a2d9ea6e231087b12fddfb0e89eb86f1dda7d1 Mon Sep 17 00:00:00 2001 From: gnembon Date: Mon, 1 Jun 2020 21:10:42 -0300 Subject: [PATCH 161/198] removed potential ConcurrentModificationException chance, part one for 304 --- src/main/java/carpet/script/CarpetEventServer.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/carpet/script/CarpetEventServer.java b/src/main/java/carpet/script/CarpetEventServer.java index 10ca5210..cd5d027d 100644 --- a/src/main/java/carpet/script/CarpetEventServer.java +++ b/src/main/java/carpet/script/CarpetEventServer.java @@ -126,7 +126,13 @@ public class CarpetEventServer List argv = argumentSupplier.get(); // empty for onTickDone ServerCommandSource source = cmdSourceSupplier.get(); assert argv.size() == reqArgs; - callList.removeIf(call -> !CarpetServer.scriptServer.runas(source, call.host, call.function, argv)); // this actually does the calls + List fails = new ArrayList<>(); + for (Callback call: callList) + { + if (!CarpetServer.scriptServer.runas(source, call.host, call.function, argv)) + fails.add(call); + } + for (Callback call : fails) callList.remove(call); } } public boolean addEventCall(ServerCommandSource source, String hostName, String funName, Function verifier) From 4271aa3a8ee453ab1be27c7063a723300e8f569c Mon Sep 17 00:00:00 2001 From: gnembon Date: Mon, 1 Jun 2020 22:11:37 -0300 Subject: [PATCH 162/198] removed ability to automatically register events by running imports code, part two for 304 --- src/main/java/carpet/script/CarpetScriptHost.java | 2 +- src/main/java/carpet/script/value/FunctionValue.java | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/carpet/script/CarpetScriptHost.java b/src/main/java/carpet/script/CarpetScriptHost.java index bd2b669e..94f3b2fc 100644 --- a/src/main/java/carpet/script/CarpetScriptHost.java +++ b/src/main/java/carpet/script/CarpetScriptHost.java @@ -96,7 +96,7 @@ public class CarpetScriptHost extends ScriptHost public void addUserDefinedFunction(Context ctx, Module module, String funName, FunctionValue function) { super.addUserDefinedFunction(ctx, module, funName, function); - // mcarpet + if (ctx.host.main != module) return; // not dealing with automatic imports / exports /configs / apps from imports if (funName.startsWith("__")) // potential fishy activity { if (funName.startsWith("__on_")) // here we can make a determination if we want to only accept events from main module. diff --git a/src/main/java/carpet/script/value/FunctionValue.java b/src/main/java/carpet/script/value/FunctionValue.java index 14f6498d..3b872ccf 100644 --- a/src/main/java/carpet/script/value/FunctionValue.java +++ b/src/main/java/carpet/script/value/FunctionValue.java @@ -5,6 +5,7 @@ import carpet.script.Expression; import carpet.script.Fluff; import carpet.script.LazyValue; import carpet.script.Tokenizer; +import carpet.script.bundled.Module; import carpet.script.exception.BreakStatement; import carpet.script.exception.ContinueStatement; import carpet.script.exception.ExitStatement; @@ -58,6 +59,8 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction return name; } + public Module getModule() {return expression.module;} + @Override public String getPrettyString() { From 46409c8daa348bee5a4574d9a0c47c2fed18d016 Mon Sep 17 00:00:00 2001 From: gnembon Date: Tue, 2 Jun 2020 11:58:14 -0300 Subject: [PATCH 163/198] added optional options for draw_shape and fixed docs --- docs/scarpet/Full.md | 64 +++++++++++++-- docs/scarpet/api/Auxiliary.md | 5 ++ docs/scarpet/resources/editors/idea/2.txt | 1 + .../scarpet/resources/editors/npp/scarpet.xml | 4 +- .../carpet/network/ClientNetworkHandler.java | 2 +- .../carpet/script/utils/ShapeDispatcher.java | 78 +++++++++++++++---- .../carpet/script/utils/ShapesRenderer.java | 12 ++- 7 files changed, 136 insertions(+), 30 deletions(-) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index 99523a4f..a8ab3b82 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -906,8 +906,11 @@ sleep(50) ### `time()` -Returns the number of milliseconds since 'some point', like Java's `System.nanoTime()`. -It returns a float, which has 1 microsecond precision (0.001 ms) +Returns the number of milliseconds since 'some point', like Java's `System.nanoTime()`, which varies from system to +system and from Java to Java. This measure should NOT be used to determine the current (date)time, but to measure +durations of things. +it returns a float with time in milliseconds (ms) for convenience and microsecond (μs) resolution for sanity. +
 start_time = time();
@@ -1513,7 +1516,7 @@ range(5,10)  => [5, 6, 7, 8, 9]
 range(20, 10, -2)  => [20, 18, 16, 14, 12]
 
-### `element(list, index)` (deprecated) +### `element(list, index)(deprecated)` Legacy support for older method that worked only on lists. Please use `get(...)` for equivalent support, or `.` operator. Also previous unique behaviours with `put` on lists has been removed to support all type of @@ -3103,24 +3106,69 @@ and `voice`. `pos` can be either a block, triple of coords, or a list of thee nu ## Particles -### `particle(name, pos, count?. spread?, speed?, playername?)` +### `particle(name, pos, count?. spread?, speed?, player?)` Renders a cloud of particles `name` centered around `pos` position, by default `count` 10 of them, default `speed` of 0, and to all players nearby, but these options can be changed via optional arguments. Follow vanilla `/particle` command on details on those options. Valid particle names are for example `'angry_villager', 'item diamond', 'block stone', 'dust 0.8 0.1 0.1 4'`. -### `particle_line(name, pos, pos2, density?)` +### `particle_line(name, pos, pos2, density?, player?)` Renders a line of particles from point `pos` to `pos2` with supplied density (defaults to 1), which indicates how far -apart you would want particles to appear, so `0.1` means one every 10cm. +apart you would want particles to appear, so `0.1` means one every 10cm. If a player (or player name) is supplied, only +that player will receive particles. -### `particle_rect(name, pos, pos2, density?)` -Renders a cuboid of particles between points `pos` and `pos2` with supplied density. +### `particle_box(name, pos, pos2, density?, player?)` +### `particle_rect` (deprecated) + +Renders a cuboid of particles between points `pos` and `pos2` with supplied density. If a player (or player name) is +supplied, only that player will receive particles. ## Markers +### `draw_shape(shape, duration, key?, value?, ... )`, `draw_shape(shape, duration, l(key?, value?, ... ))`, `draw_shape(shape, duration, attribute_map)` + +Draws a shape in the world that will expire in `duration` ticks. Other attributes of the shape should be provided as +consecutive key - value argument pairs, either as next arguments, or packed in a list, or supplied as a proper key-value +`map`. Arguments may include shared shape attributes, which are all optional, as well as shape-specific attributes, that +could be either optional or required. Shapes will draw properly on all carpet clients. Other connected players that don't +have carpet installed will still be able to see the required shapes in the form of dust particles. Replacement shapes +are not required to follow all attributes precisely, but will allow vanilla clients to receive some experience of your +apps. One of the attributes that will definitely not be honored is the duration - particles will be send once +per shape and last whatever they typically last in the game. + +Shapes will fail to draw and raise a runtime error if not all its required parameters +are specified and all available shapes have some parameters that are required, so make sure to have them in place: + +On the client, shapes can recognize that they are being redrawn again with the same parameters, disregarding the +duration parameter. This updates the expiry on the drawn shape to the new value, instead of adding new shape in its +place. This can be used for toggling the shapes on and off that has been send previously with very large durations, +or simply refresh the shapes periodically in more dynamic applications. + +Optional shared shape attributes: + * `color` - integer value indicating the main color of the shape in the form of red, green, blue and alpha components + in the form of `0xRRGGBBAA`, with the default of `-1`, so white opaque, or `0xFFFFFFFF`. + * `player` - name or player entity to send the shape to. If specified, the shapes will appear only for the specified + player, otherwise it will be send to all players in the dimension. + +Available shapes: + * `'line'` - draws a straight line between two points + * Required attributes: + * `from` - triple coordinates, entity, or block value indicating one end of the line + * `to` - other end of the line, same format as `from` + * Optional attributes: + * `width` - line thickness, defaults to 2.0pt + + * `'box'` - draws a box with corners in specified points + * Required attributes: + * `from` - triple coordinates, entity, or block value indicating one corner of the box + * `to` - other corner, same format as `from` + * Optional attributes: + * `width` - mesh line thickness, defaults to 2.0pt + * `fill` - color for the box faces, defaults to no fill, use shared color attribute format + ### `create_marker(text, pos, rotation?, block?)` Spawns a (permanent) marker entity with text or block at position. Returns that entity for further manipulations. diff --git a/docs/scarpet/api/Auxiliary.md b/docs/scarpet/api/Auxiliary.md index a8b097dc..993620f7 100644 --- a/docs/scarpet/api/Auxiliary.md +++ b/docs/scarpet/api/Auxiliary.md @@ -66,11 +66,16 @@ Available shapes: * Required attributes: * `from` - triple coordinates, entity, or block value indicating one end of the line * `to` - other end of the line, same format as `from` + * Optional attributes: + * `width` - line thickness, defaults to 2.0pt * `'box'` - draws a box with corners in specified points * Required attributes: * `from` - triple coordinates, entity, or block value indicating one corner of the box * `to` - other corner, same format as `from` + * Optional attributes: + * `width` - mesh line thickness, defaults to 2.0pt + * `fill` - color for the box faces, defaults to no fill, use shared color attribute format ### `create_marker(text, pos, rotation?, block?)` diff --git a/docs/scarpet/resources/editors/idea/2.txt b/docs/scarpet/resources/editors/idea/2.txt index 81803965..279adc94 100644 --- a/docs/scarpet/resources/editors/idea/2.txt +++ b/docs/scarpet/resources/editors/idea/2.txt @@ -17,6 +17,7 @@ current_dimension day_time destroy diamond +draw_shape drop_item emitted_light entity_area diff --git a/docs/scarpet/resources/editors/npp/scarpet.xml b/docs/scarpet/resources/editors/npp/scarpet.xml index c17b3811..64158b61 100644 --- a/docs/scarpet/resources/editors/npp/scarpet.xml +++ b/docs/scarpet/resources/editors/npp/scarpet.xml @@ -70,7 +70,9 @@ run save tick_time world_time day_time last_tick_times game_tick seed current_dimension in_dimension - plop harvest destroy schedule nbt create_marker remove_all_markers load_app_data store_app_data escape_nbt statistic + plop harvest destroy schedule nbt draw_shape create_marker remove_all_markers + + load_app_data store_app_data escape_nbt statistic euler pi null true false x y z p diff --git a/src/main/java/carpet/network/ClientNetworkHandler.java b/src/main/java/carpet/network/ClientNetworkHandler.java index 96524117..07ec99df 100644 --- a/src/main/java/carpet/network/ClientNetworkHandler.java +++ b/src/main/java/carpet/network/ClientNetworkHandler.java @@ -35,7 +35,7 @@ public class ClientNetworkHandler } }); put("TickRate", (p, t) -> TickSpeed.tickrate(((AbstractNumberTag)t).getFloat(), false)); - put("renderShape", (p, t) -> { + put("scShape", (p, t) -> { if (CarpetClient.shapes != null) CarpetClient.shapes.addShape((CompoundTag)t); }); diff --git a/src/main/java/carpet/script/utils/ShapeDispatcher.java b/src/main/java/carpet/script/utils/ShapeDispatcher.java index 0aaadb12..a1d1f071 100644 --- a/src/main/java/carpet/script/utils/ShapeDispatcher.java +++ b/src/main/java/carpet/script/utils/ShapeDispatcher.java @@ -19,6 +19,7 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.command.arguments.ParticleArgumentType; import net.minecraft.entity.Entity; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.FloatTag; import net.minecraft.nbt.IntTag; import net.minecraft.nbt.StringTag; import net.minecraft.nbt.Tag; @@ -57,7 +58,7 @@ public class ShapeDispatcher if (ServerNetworkHandler.validCarpetPlayers.contains(player)) { if (tag == null) tag = ExpiringShape.toTag(params); - ServerNetworkHandler.sendCustomCommand(player,"renderShape", tag); + ServerNetworkHandler.sendCustomCommand(player,"scShape", tag); } else { @@ -122,7 +123,7 @@ public class ShapeDispatcher Function decoder = Param.decoders.get(key); if (decoder==null) { - CarpetSettings.LOG.error("Unknown parameter for shape: "+key); + CarpetSettings.LOG.info("Unknown parameter for shape: "+key); return null; } Value decodedValue = decoder.apply(tag.get(key)); @@ -131,13 +132,13 @@ public class ShapeDispatcher Value shapeValue = options.get("shape"); if (shapeValue == null) { - CarpetSettings.LOG.error("Shape id missing in "+ String.join(", ", tag.getKeys())); + CarpetSettings.LOG.info("Shape id missing in "+ String.join(", ", tag.getKeys())); return null; } Function,ExpiringShape> factory = ExpiringShape.shapeProviders.get(shapeValue.getString()); if (factory == null) { - CarpetSettings.LOG.error("Unknown shape: "+shapeValue.getString()); + CarpetSettings.LOG.info("Unknown shape: "+shapeValue.getString()); return null; } try @@ -146,7 +147,7 @@ public class ShapeDispatcher } catch (InternalExpressionException exc) { - CarpetSettings.LOG.error(exc.getMessage()); + CarpetSettings.LOG.info(exc.getMessage()); } return null; } @@ -225,7 +226,10 @@ public class ShapeDispatcher } // list of params that need to be there private final Set required = ImmutableSet.of("duration", "shape", "dim"); - private final Map optional = ImmutableMap.of("color", new NumericValue(-1), "player", Value.NULL); + private final Map optional = ImmutableMap.of( + "color", new NumericValue(-1), + "player", Value.NULL + ); protected Set requiredParams() {return required;} // list of params that can be there, with defaults protected Set optionalParams() {return optional.keySet();} @@ -234,7 +238,10 @@ public class ShapeDispatcher public static class Box extends ExpiringShape { private final Set required = ImmutableSet.of("from", "to"); - private final Map optional = ImmutableMap.of(); + private final Map optional = ImmutableMap.of( + "width", new NumericValue(2.0), + "fill", new NumericValue(0xffffff00) + ); @Override protected Set requiredParams() { return Sets.union(super.requiredParams(), required); } @Override @@ -243,6 +250,10 @@ public class ShapeDispatcher float x1, y1, z1; float x2, y2, z2; + float lineWidth; + + protected float fr, fg, fb, fa; + protected int fillColor; @Override protected void init(Map options) @@ -256,6 +267,12 @@ public class ShapeDispatcher x2 = NumericValue.asNumber(to.get(0)).getFloat(); y2 = NumericValue.asNumber(to.get(1)).getFloat(); z2 = NumericValue.asNumber(to.get(2)).getFloat(); + lineWidth = NumericValue.asNumber(options.getOrDefault("width", optional.get("width"))).getFloat(); + fillColor = NumericValue.asNumber(options.getOrDefault("fill", optional.get("fill"))).getInt(); + this.fr = (float)(fillColor >> 24 & 0xFF) / 255.0F; + this.fg = (float)(fillColor >> 16 & 0xFF) / 255.0F; + this.fb = (float)(fillColor >> 8 & 0xFF) / 255.0F; + this.fa = (float)(fillColor & 0xFF) / 255.0F; } @Override @@ -281,6 +298,8 @@ public class ShapeDispatcher hash = 31*hash + Float.hashCode(x2); hash = 31*hash + Float.hashCode(y2); hash = 31*hash + Float.hashCode(z2); + hash = 31*hash + Float.hashCode(lineWidth); + if (fa != 0.0) hash = 31*hash + fillColor; return hash; } @@ -308,7 +327,7 @@ public class ShapeDispatcher public static class Line extends ExpiringShape { private final Set required = ImmutableSet.of("from", "to"); - private final Map optional = ImmutableMap.of(); + private final Map optional = ImmutableMap.of("width", new NumericValue(2.0)); @Override protected Set requiredParams() { return Sets.union(super.requiredParams(), required); } @Override @@ -321,6 +340,7 @@ public class ShapeDispatcher float x1, y1, z1; float x2, y2, z2; + float lineWidth; @Override protected void init(Map options) @@ -334,6 +354,7 @@ public class ShapeDispatcher x2 = NumericValue.asNumber(to.get(0)).getFloat(); y2 = NumericValue.asNumber(to.get(1)).getFloat(); z2 = NumericValue.asNumber(to.get(2)).getFloat(); + lineWidth = NumericValue.asNumber(options.getOrDefault("width", optional.get("width"))).getFloat(); } @Override @@ -361,6 +382,7 @@ public class ShapeDispatcher hash = 31*hash + Float.hashCode(x2); hash = 31*hash + Float.hashCode(y2); hash = 31*hash + Float.hashCode(z2); + hash = 31*hash + Float.hashCode(lineWidth); return hash; } } @@ -374,16 +396,19 @@ public class ShapeDispatcher put("color", ShapeDispatcher::decodeInt); put("from", Vec3Param::decode); put("to", Vec3Param::decode); - + put("width", ShapeDispatcher::decodeFloat); + put("fill", ShapeDispatcher::decodeInt); }}; Map coders = new HashMap(){{ - put("shape", new ShapeParam()); put("player", new PlayerParam()); + put("shape", new ShapeParam()); put("dim", new DimensionParam()); put("duration", new DurationParam()); put("color", new ColorParam()); put("from", new FromParam()); put("to", new ToParam()); + put("width", new WidthParam()); + put("fill", new FillColorParam()); }}; Tag toTag(Value value); //validates value, returning null if not necessary to keep it and serialize Value validate(CarpetContext cc, Value value); // makes sure the value is proper @@ -452,8 +477,6 @@ public class ShapeDispatcher } public static abstract class NumericParam implements Param { - @Override - public Tag toTag(Value value) { return IntTag.of(NumericValue.asNumber(value).getInt()); } @Override public Value validate(CarpetContext cc, Value value) { @@ -471,15 +494,34 @@ public class ShapeDispatcher return ret; } } + public static abstract class PositiveFloatParam extends PositiveParam + { + @Override + public Tag toTag(Value value) { return FloatTag.of(NumericValue.asNumber(value).getFloat()); } + } + public static abstract class PositiveIntParam extends PositiveParam + { + @Override + public Tag toTag(Value value) { return IntTag.of(NumericValue.asNumber(value).getInt()); } + + } public static Value decodeInt(Tag tag) { return new NumericValue(((IntTag)tag).getInt()); } - public static class DurationParam extends PositiveParam + public static Value decodeFloat(Tag tag) { return new NumericValue(((FloatTag)tag).getFloat()); } + public static class DurationParam extends PositiveIntParam { @Override public boolean appliesTo(ExpiringShape shape) { return true; } @Override public String identify() { return "duration"; } } + public static class WidthParam extends PositiveFloatParam + { + @Override + public boolean appliesTo(ExpiringShape shape) { return shape instanceof Box || shape instanceof Line; } + @Override + public String identify() { return "width"; } + } public static abstract class Vec3Param implements Param { @@ -546,12 +588,22 @@ public class ShapeDispatcher } public static class ColorParam extends NumericParam { + @Override + public Tag toTag(Value value) { return IntTag.of(NumericValue.asNumber(value).getInt()); } @Override public boolean appliesTo(ExpiringShape shape) { return true; } @Override public String identify() { return "color"; } } + public static class FillColorParam extends ColorParam + { + @Override + public boolean appliesTo(ExpiringShape shape) { return shape instanceof Box; } + @Override + public String identify() { return "fill"; } + } + public static class FromParam extends Vec3Param { @Override diff --git a/src/main/java/carpet/script/utils/ShapesRenderer.java b/src/main/java/carpet/script/utils/ShapesRenderer.java index 4bb50aa7..46ee549b 100644 --- a/src/main/java/carpet/script/utils/ShapesRenderer.java +++ b/src/main/java/carpet/script/utils/ShapesRenderer.java @@ -91,12 +91,9 @@ public class ShapesRenderer if (shape == null) return; BiFunction> shapeFactory; shapeFactory = renderedShapes.get(tag.getString("shape")); - - - if (shapeFactory == null) { - CarpetSettings.LOG.error("Unrecognized shape: "+tag.getString("shape")); + CarpetSettings.LOG.info("Unrecognized shape: "+tag.getString("shape")); } else { @@ -161,7 +158,7 @@ public class ShapesRenderer @Override public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) { - RenderSystem.lineWidth(2.0F); + RenderSystem.lineWidth(shape.lineWidth); bufferBuilder.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR); // 3 drawBoxWireGLLines(bufferBuilder, shape.x1 - cx-renderEpsilon, shape.y1 - cy-renderEpsilon, shape.z1 - cz-renderEpsilon, @@ -173,12 +170,13 @@ public class ShapesRenderer @Override public void render2pass(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) { + if (shape.fa == 0.0) return; RenderSystem.lineWidth(1.0F); bufferBuilder.begin(GL11.GL_QUADS, VertexFormats.POSITION_COLOR); // 3 drawBox(bufferBuilder, shape.x1-cx-renderEpsilon, shape.y1-cy-renderEpsilon, shape.z1-cz-renderEpsilon, shape.x2-cx+renderEpsilon, shape.y2-cy+renderEpsilon, shape.z2-cz+renderEpsilon, - shape.r, shape.g, shape.b, shape.a/6 + shape.fr, shape.fg, shape.fb, shape.fa ); tessellator.draw(); } @@ -193,7 +191,7 @@ public class ShapesRenderer @Override public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) { - RenderSystem.lineWidth(2.0F); + RenderSystem.lineWidth(shape.lineWidth); bufferBuilder.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR); // 3 drawLine(bufferBuilder, shape.x1-cx-renderEpsilon, shape.y1-cy-renderEpsilon, shape.z1-cz-renderEpsilon, From 681d6ec9ee5a4ce13c989e9c094d182b987aaabd Mon Sep 17 00:00:00 2001 From: gnembon Date: Tue, 2 Jun 2020 11:58:33 -0300 Subject: [PATCH 164/198] fixed overlay --- .../assets/carpet/scripts/overlay.sc | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/main/resources/assets/carpet/scripts/overlay.sc b/src/main/resources/assets/carpet/scripts/overlay.sc index 366d0a7a..fb6b5a52 100644 --- a/src/main/resources/assets/carpet/scripts/overlay.sc +++ b/src/main/resources/assets/carpet/scripts/overlay.sc @@ -12,7 +12,7 @@ global_renderers = m( l('active', false), l('handler', '__chunk_renderer'), l('tasks', m()), - l('range', 4) + l('range', 6) )), l('shapes', m( l('active', false), @@ -95,7 +95,7 @@ __structure_renderer(player_name) -> total_size = _euclidean(from, to); density = max(10, total_size/10); //particle_box('dust 0 1 1 2', from, to+1, density); - draw_shape('box', 15, 'from', from, 'to', to+1, 'color', 0x00FFFFFF); + draw_shape('box', 15, 'from', from, 'to', to+1, 'color', 0x00FFFFFF, 'width', 3); structure_pieces = slice(sort_key(structure_pieces, _euclidean_sq((_:2+_:3)/2,ppos)), 0, config:'max_pieces'); for (structure_pieces, l(piece, direction, from, to) = _; //factor = 1- _i / config:'max_pieces' / 2; @@ -106,8 +106,8 @@ __structure_renderer(player_name) -> g = r; b = 255; a = 255; - color = a+256*(b+256*(g+256*r)); - draw_shape('box', 15, 'from', from, 'to', to+1, 'color', color); + color = 256*(b+256*(g+256*r)); // leaving out a + draw_shape('box', 15, 'from', from, 'to', to+1, 'color', color+a, 'fill', color+a/6); ) ) ); @@ -122,10 +122,9 @@ __chunk_renderer(player_name) -> // get lower corner of the chunk ppos = map(pos(p)/16, floor(_))*16; ppos:1 = 0; - - r = config:'range'; - for(range(-r,r), cx =_; - for (range(-r,r), cz = _; + rang = config:'range'; + for(range(-rang,rang), cx =_; + for (range(-rang,rang), cz = _; ref_pos = ppos + l(16*cx,0,16*cz); if(has(config:'tasks':'slime_chunks') && in_slime_chunk(ref_pos), player_distance = _euclidean(ppos, ref_pos); @@ -138,12 +137,12 @@ __chunk_renderer(player_name) -> b = 30; a = max(0, 255-player_distance); color = a+256*(b+256*(g+256*r)); - draw_shape('line', 15, 'from', top_00, 'to', top_10, 'color', color); - draw_shape('line', 15, 'from', top_10, 'to', top_11, 'color', color); - draw_shape('line', 15, 'from', top_11, 'to', top_01, 'color', color); - draw_shape('line', 15, 'from', top_01, 'to', top_00, 'color', color); - draw_shape('line', 15, 'from', top_00, 'to', top_11, 'color', color); - draw_shape('line', 15, 'from', top_01, 'to', top_10, 'color', color); + draw_shape('line', 15, 'from', top_00, 'to', top_10, 'color', color, 'width', 3); + draw_shape('line', 15, 'from', top_10, 'to', top_11, 'color', color, 'width', 3); + draw_shape('line', 15, 'from', top_11, 'to', top_01, 'color', color, 'width', 3); + draw_shape('line', 15, 'from', top_01, 'to', top_00, 'color', color, 'width', 3); + draw_shape('line', 15, 'from', top_00, 'to', top_11, 'color', color, 'width', 3); + draw_shape('line', 15, 'from', top_01, 'to', top_10, 'color', color, 'width', 3); //part = 'dust 0.2 0.8 0.2 2'; //density = 2+player_distance/2; From a7cd2c49cce0eeabb31ffa0dfa0a5c3af9fbd0d5 Mon Sep 17 00:00:00 2001 From: gnembon Date: Tue, 2 Jun 2020 18:44:23 -0300 Subject: [PATCH 165/198] added view_distance to API --- docs/scarpet/Full.md | 3 +++ docs/scarpet/api/Auxiliary.md | 3 +++ docs/scarpet/resources/editors/idea/2.txt | 1 + docs/scarpet/resources/editors/npp/scarpet.xml | 2 +- src/main/java/carpet/script/CarpetExpression.java | 6 ++++++ 5 files changed, 14 insertions(+), 1 deletion(-) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index a8ab3b82..9a537627 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -3350,6 +3350,9 @@ Returns current dimension that the script runs in. Evaluates the expression `expr` with different dimension execution context. `smth` can be an entity, world-localized block, so not `block('stone')`, or a string representing a dimension like: `'nether'`, `'the_nether'`, `'end'` or `'overworld'`, etc. + +### `view_distance()` +Returns the view distance of the server. ### `schedule(delay, function, args...)` diff --git a/docs/scarpet/api/Auxiliary.md b/docs/scarpet/api/Auxiliary.md index 993620f7..a668dfa3 100644 --- a/docs/scarpet/api/Auxiliary.md +++ b/docs/scarpet/api/Auxiliary.md @@ -258,6 +258,9 @@ Returns current dimension that the script runs in. Evaluates the expression `expr` with different dimension execution context. `smth` can be an entity, world-localized block, so not `block('stone')`, or a string representing a dimension like: `'nether'`, `'the_nether'`, `'end'` or `'overworld'`, etc. + +### `view_distance()` +Returns the view distance of the server. ### `schedule(delay, function, args...)` diff --git a/docs/scarpet/resources/editors/idea/2.txt b/docs/scarpet/resources/editors/idea/2.txt index 279adc94..7e2a8d8a 100644 --- a/docs/scarpet/resources/editors/idea/2.txt +++ b/docs/scarpet/resources/editors/idea/2.txt @@ -102,6 +102,7 @@ ticks_randomly top transparent update +view_distance volume without_updates world_time \ 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 64158b61..67ceb72a 100644 --- a/docs/scarpet/resources/editors/npp/scarpet.xml +++ b/docs/scarpet/resources/editors/npp/scarpet.xml @@ -68,7 +68,7 @@ format logger sound particle particle_line particle_rect - run save tick_time world_time day_time last_tick_times game_tick seed current_dimension in_dimension + run save tick_time world_time day_time last_tick_times game_tick seed current_dimension in_dimension view_distance plop harvest destroy schedule nbt draw_shape create_marker remove_all_markers diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index e14eeb8b..f3352d04 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -2968,6 +2968,12 @@ public class CarpetExpression return (cc, tt) -> retval; }); + this.expr.addLazyFunction("view_distance", 0, (c, t, lv) -> { + ServerCommandSource s = ((CarpetContext)c).s; + Value retval = new NumericValue(s.getMinecraftServer().getPlayerManager().getViewDistance()); + return (cc, tt) -> retval; + }); + this.expr.addLazyFunction("in_dimension", 2, (c, t, lv) -> { ServerCommandSource outerSource = ((CarpetContext)c).s; Value dimensionValue = lv.get(0).evalValue(c); From e2e45bb20d0afe1b3f720d06ed97e1c95f386c44 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 3 Jun 2020 00:09:34 -0300 Subject: [PATCH 166/198] added __on_player_connects and dis. fixes #294 --- docs/scarpet/Full.md | 2 ++ docs/scarpet/api/Events.md | 2 ++ docs/scarpet/resources/editors/idea/4.txt | 4 +++- docs/scarpet/resources/editors/npp/scarpet.xml | 2 ++ .../carpet/mixins/PlayerManager_coreMixin.java | 3 +++ .../ServerPlayNetworkHandler_coreMixin.java | 3 +++ .../java/carpet/script/CarpetEventServer.java | 18 ++++++++++++++++++ .../assets/carpet/scripts/event_test.sc | 16 +++++++++++++++- 8 files changed, 48 insertions(+), 2 deletions(-) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index 9a537627..fc2725cf 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -3047,6 +3047,8 @@ __on_player_starts_sprinting(player) __on_player_stops_sprinting(player) __on_player_drops_item(player) __on_player_drops_stack(player) +__on_player_connects(player) +__on_player_disconnects(player, reason) __on_statistic(player, category, event, value) // player statistic changes diff --git a/docs/scarpet/api/Events.md b/docs/scarpet/api/Events.md index 39992450..6a616f30 100644 --- a/docs/scarpet/api/Events.md +++ b/docs/scarpet/api/Events.md @@ -48,6 +48,8 @@ __on_player_starts_sprinting(player) __on_player_stops_sprinting(player) __on_player_drops_item(player) __on_player_drops_stack(player) +__on_player_connects(player) +__on_player_disconnects(player, reason) __on_statistic(player, category, event, value) // player statistic changes diff --git a/docs/scarpet/resources/editors/idea/4.txt b/docs/scarpet/resources/editors/idea/4.txt index 4799c846..faf87463 100644 --- a/docs/scarpet/resources/editors/idea/4.txt +++ b/docs/scarpet/resources/editors/idea/4.txt @@ -30,4 +30,6 @@ __on_tick_nether __on_player_takes_damage __on_player_deals_damage __on_player_dies -__on_player_respawns \ No newline at end of file +__on_player_respawns +__on_player_disconnects +__on_player_connects \ 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 67ceb72a..33416a05 100644 --- a/docs/scarpet/resources/editors/npp/scarpet.xml +++ b/docs/scarpet/resources/editors/npp/scarpet.xml @@ -112,6 +112,8 @@ __on_player_deals_damage __on_player_dies __on_player_respawns + __on_player_disconnects + __on_player_connects $ 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/PlayerManager_coreMixin.java b/src/main/java/carpet/mixins/PlayerManager_coreMixin.java index ecd2fe61..62eeefff 100644 --- a/src/main/java/carpet/mixins/PlayerManager_coreMixin.java +++ b/src/main/java/carpet/mixins/PlayerManager_coreMixin.java @@ -9,6 +9,8 @@ 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_CONNECTS; + @Mixin(PlayerManager.class) public class PlayerManager_coreMixin { @@ -16,5 +18,6 @@ public class PlayerManager_coreMixin private void onPlayerConnected(ClientConnection connection, ServerPlayerEntity player, CallbackInfo ci) { CarpetServer.onPlayerLoggedIn(player); + PLAYER_CONNECTS.onPlayerEvent(player); } } diff --git a/src/main/java/carpet/mixins/ServerPlayNetworkHandler_coreMixin.java b/src/main/java/carpet/mixins/ServerPlayNetworkHandler_coreMixin.java index 1dfbc237..43fabd5c 100644 --- a/src/main/java/carpet/mixins/ServerPlayNetworkHandler_coreMixin.java +++ b/src/main/java/carpet/mixins/ServerPlayNetworkHandler_coreMixin.java @@ -13,6 +13,8 @@ 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_DISCONNECTS; + @Mixin(ServerPlayNetworkHandler.class) public class ServerPlayNetworkHandler_coreMixin { @Shadow @@ -21,5 +23,6 @@ public class ServerPlayNetworkHandler_coreMixin { @Inject(method = "onDisconnected", at = @At("HEAD")) private void onPlayerDisconnect(Text reason, CallbackInfo ci) { CarpetServer.onPlayerLoggedOut(this.player); + if (PLAYER_DISCONNECTS.isNeeded()) PLAYER_DISCONNECTS.onPlayerMessage(player, reason.asString()); } } diff --git a/src/main/java/carpet/script/CarpetEventServer.java b/src/main/java/carpet/script/CarpetEventServer.java index cd5d027d..4d3eb8d2 100644 --- a/src/main/java/carpet/script/CarpetEventServer.java +++ b/src/main/java/carpet/script/CarpetEventServer.java @@ -553,6 +553,23 @@ public class CarpetEventServer ), player::getCommandSource); } }, + PLAYER_CONNECTS("player_connects", 1, false) { + @Override + public void onPlayerEvent(ServerPlayerEntity player) + { + handler.call( () -> Collections.singletonList(((c, t) -> new EntityValue(player))), player::getCommandSource); + } + }, + PLAYER_DISCONNECTS("player_disconnects", 2, false) { + @Override + public void onPlayerMessage(ServerPlayerEntity player, String message) + { + handler.call( () -> Arrays.asList( + ((c, t) -> new EntityValue(player)), + ((c, t) -> new StringValue(message)) + ), player::getCommandSource); + } + }, STATISTICS("statistic", 4, false) { private Identifier getStatId(Stat stat) @@ -617,6 +634,7 @@ public class CarpetEventServer public void onTick() { } public void onChunkGenerated(ServerWorld world, Chunk chunk) { } public void onPlayerEvent(ServerPlayerEntity player) { } + public void onPlayerMessage(ServerPlayerEntity player, String message) { } public void onPlayerStatistic(ServerPlayerEntity player, Stat stat, int amount) { } public void onMountControls(ServerPlayerEntity player, float strafeSpeed, float forwardSpeed, boolean jumping, boolean sneaking) { } public void onItemAction(ServerPlayerEntity player, Hand enumhand, ItemStack itemstack) { } diff --git a/src/main/resources/assets/carpet/scripts/event_test.sc b/src/main/resources/assets/carpet/scripts/event_test.sc index 036a0e38..1659d565 100644 --- a/src/main/resources/assets/carpet/scripts/event_test.sc +++ b/src/main/resources/assets/carpet/scripts/event_test.sc @@ -229,4 +229,18 @@ __on_player_changes_dimension(player, from_pos, from_dimension, to_pos, to_dimen print(' - player: '+player); print(' - from '+from_dimension+' at '+map(from_pos, str('%.2f',_))); print(' - to '+to_dimension+if(to_pos == null, '', ' at '+map(to_pos, str('%.2f',_)))); -) +); + +__on_player_connects(player) -> +( // you will never sees it + print(''); + print('__on_player_connects(player)'); + print('Player '+player+' connects.') +); + +__on_player_disconnects(player, reason) -> +( // you will never sees it either + print(''); + print('__on_player_disconnects(player)'); + print('Player '+player+' disconnects because: '+reason) +); From f14fcbba9fd8ffaf9fff19d0263274548b800293 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 3 Jun 2020 03:47:38 -0300 Subject: [PATCH 167/198] added spheres to draw_shape --- docs/scarpet/Full.md | 8 ++ docs/scarpet/api/Auxiliary.md | 8 ++ .../carpet/script/utils/ShapeDispatcher.java | 110 ++++++++++++++++++ .../carpet/script/utils/ShapesRenderer.java | 83 +++++++++++-- 4 files changed, 197 insertions(+), 12 deletions(-) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index fc2725cf..a0bac5ea 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -3170,6 +3170,14 @@ Available shapes: * Optional attributes: * `width` - mesh line thickness, defaults to 2.0pt * `fill` - color for the box faces, defaults to no fill, use shared color attribute format + * `'sphere'` - draws a sphere + * Required attributes: + * `center` - center of the sphere + * `radius` - radius of the sphere + * Optional attributes: + * `level` - level of details, or grid size. The more the denser your sphere. Default level of 0, means that the + level of detail will be selected automatically based on radius. + * `width` - line thickness ### `create_marker(text, pos, rotation?, block?)` diff --git a/docs/scarpet/api/Auxiliary.md b/docs/scarpet/api/Auxiliary.md index a668dfa3..90860cc9 100644 --- a/docs/scarpet/api/Auxiliary.md +++ b/docs/scarpet/api/Auxiliary.md @@ -76,6 +76,14 @@ Available shapes: * Optional attributes: * `width` - mesh line thickness, defaults to 2.0pt * `fill` - color for the box faces, defaults to no fill, use shared color attribute format + * `'sphere'` - draws a sphere + * Required attributes: + * `center` - center of the sphere + * `radius` - radius of the sphere + * Optional attributes: + * `level` - level of details, or grid size. The more the denser your sphere. Default level of 0, means that the + level of detail will be selected automatically based on radius. + * `width` - line thickness ### `create_marker(text, pos, rotation?, block?)` diff --git a/src/main/java/carpet/script/utils/ShapeDispatcher.java b/src/main/java/carpet/script/utils/ShapeDispatcher.java index a1d1f071..5202ddf7 100644 --- a/src/main/java/carpet/script/utils/ShapeDispatcher.java +++ b/src/main/java/carpet/script/utils/ShapeDispatcher.java @@ -28,6 +28,7 @@ import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.util.registry.Registry; import net.minecraft.world.dimension.DimensionType; @@ -38,6 +39,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Optional; +import java.util.Random; import java.util.Set; import java.util.function.Consumer; import java.util.function.Function; @@ -157,6 +159,7 @@ public class ShapeDispatcher public static final Map,ExpiringShape>> shapeProviders = new HashMap, ExpiringShape>>(){{ put("line", creator(Line::new)); put("box", creator(Box::new)); + put("sphere", creator(Sphere::new)); }}; private static Function,ExpiringShape> creator(Supplier shapeFactory) { @@ -387,6 +390,83 @@ public class ShapeDispatcher } } + public static class Sphere extends ExpiringShape + { + private final Set required = ImmutableSet.of("center", "radius"); + private final Map optional = ImmutableMap.of("width", new NumericValue(2.0), "level", Value.ZERO); + @Override + protected Set requiredParams() { return Sets.union(super.requiredParams(), required); } + @Override + protected Set optionalParams() { return Sets.union(super.optionalParams(), optional.keySet()); } + + private Sphere() + { + super(); + } + + float cx, cy, cz; + float radius; + int level; + int subdivisions; + float lineWidth; + + @Override + protected void init(Map options) + { + super.init(options); + List from = ((ListValue)options.get("center")).getItems(); + cx = NumericValue.asNumber(from.get(0)).getFloat(); + cy = NumericValue.asNumber(from.get(1)).getFloat(); + cz = NumericValue.asNumber(from.get(2)).getFloat(); + radius = NumericValue.asNumber(options.get("radius")).getFloat(); + level = NumericValue.asNumber(options.getOrDefault("level", optional.get("level"))).getInt(); + subdivisions = level; + if (subdivisions <= 0) + { + subdivisions = Math.max(10, (int)(10*Math.sqrt(radius))); + } + lineWidth = NumericValue.asNumber(options.getOrDefault("width", optional.get("width"))).getFloat(); + } + + @Override + public Consumer alternative() { return p -> + { + String particleName = String.format(Locale.ROOT , "dust %.1f %.1f %.1f 1.0", r, g, b); + ParticleEffect particle = getParticleData(particleName); + float pihalf = (float)(Math.PI / 180.0f); + int partno = Math.min(1000,20*subdivisions); + Random rand = p.world.getRandom(); + ServerWorld world = p.getServerWorld(); + for (int i=0; i> decoders = new HashMap>(){{ @@ -398,6 +478,9 @@ public class ShapeDispatcher put("to", Vec3Param::decode); put("width", ShapeDispatcher::decodeFloat); put("fill", ShapeDispatcher::decodeInt); + put("center", Vec3Param::decode); + put("radius", ShapeDispatcher::decodeFloat); + put("level", ShapeDispatcher::decodeInt); }}; Map coders = new HashMap(){{ put("player", new PlayerParam()); @@ -409,6 +492,9 @@ public class ShapeDispatcher put("to", new ToParam()); put("width", new WidthParam()); put("fill", new FillColorParam()); + put("center", new CenterParam()); + put("radius", new RadiusParam()); + put("level", new LevelParam()); }}; Tag toTag(Value value); //validates value, returning null if not necessary to keep it and serialize Value validate(CarpetContext cc, Value value); // makes sure the value is proper @@ -624,6 +710,30 @@ public class ShapeDispatcher public String identify() { return "to"; } } + public static class CenterParam extends Vec3Param + { + @Override + public boolean appliesTo(ExpiringShape shape) { return (shape instanceof Sphere); } + @Override + public boolean roundsUpForBlocks() { return false; } + @Override + public String identify() { return "center"; } + } + public static class RadiusParam extends PositiveFloatParam + { + @Override + public boolean appliesTo(ExpiringShape shape) { return shape instanceof Sphere; } + @Override + public String identify() { return "radius"; } + } + public static class LevelParam extends PositiveIntParam + { + @Override + public boolean appliesTo(ExpiringShape shape) { return shape instanceof Sphere; } + @Override + public String identify() { return "level"; } + } + private static boolean isStraight(Vec3d from, Vec3d to, double density) diff --git a/src/main/java/carpet/script/utils/ShapesRenderer.java b/src/main/java/carpet/script/utils/ShapesRenderer.java index 46ee549b..8552ca7a 100644 --- a/src/main/java/carpet/script/utils/ShapesRenderer.java +++ b/src/main/java/carpet/script/utils/ShapesRenderer.java @@ -12,6 +12,7 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.Entity; import net.minecraft.nbt.CompoundTag; import net.minecraft.util.Identifier; +import net.minecraft.util.math.MathHelper; import net.minecraft.util.registry.Registry; import net.minecraft.world.IWorld; import net.minecraft.world.dimension.DimensionType; @@ -31,6 +32,7 @@ public class ShapesRenderer {{ put("line", RenderedLine::new); put("box", RenderedBox::new); + put("sphere", RenderedSphere::new); }}; public ShapesRenderer(MinecraftClient minecraftClient) @@ -159,8 +161,8 @@ public class ShapesRenderer public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) { RenderSystem.lineWidth(shape.lineWidth); - bufferBuilder.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR); // 3 - drawBoxWireGLLines(bufferBuilder, + + drawBoxWireGLLines(tessellator, bufferBuilder, shape.x1 - cx-renderEpsilon, shape.y1 - cy-renderEpsilon, shape.z1 - cz-renderEpsilon, shape.x2 - cx+renderEpsilon, shape.y2 - cy+renderEpsilon, shape.z2 - cz+renderEpsilon, shape.r, shape.g, shape.b, shape.a, shape.r, shape.g, shape.b @@ -172,13 +174,13 @@ public class ShapesRenderer { if (shape.fa == 0.0) return; RenderSystem.lineWidth(1.0F); - bufferBuilder.begin(GL11.GL_QUADS, VertexFormats.POSITION_COLOR); // 3 - drawBox(bufferBuilder, + + drawBoxFaces(tessellator, bufferBuilder, shape.x1-cx-renderEpsilon, shape.y1-cy-renderEpsilon, shape.z1-cz-renderEpsilon, shape.x2-cx+renderEpsilon, shape.y2-cy+renderEpsilon, shape.z2-cz+renderEpsilon, shape.fr, shape.fg, shape.fb, shape.fa ); - tessellator.draw(); + } } @@ -192,25 +194,42 @@ public class ShapesRenderer public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) { RenderSystem.lineWidth(shape.lineWidth); - bufferBuilder.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR); // 3 - drawLine(bufferBuilder, + drawLine(tessellator, bufferBuilder, shape.x1-cx-renderEpsilon, shape.y1-cy-renderEpsilon, shape.z1-cz-renderEpsilon, shape.x2-cx+renderEpsilon, shape.y2-cy+renderEpsilon, shape.z2-cz+renderEpsilon, shape.r, shape.g, shape.b, shape.a ); - tessellator.draw(); + } + } + + public static class RenderedSphere extends RenderedShape + { + public RenderedSphere(MinecraftClient client, ShapeDispatcher.ExpiringShape shape) + { + super(client, (ShapeDispatcher.Sphere)shape); + } + @Override + public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) + { + RenderSystem.lineWidth(shape.lineWidth); + drawSphereWireframe(tessellator, bufferBuilder, + shape.cx-cx-renderEpsilon, shape.cy-cy-renderEpsilon, shape.cz-cz-renderEpsilon, + shape.radius, shape.subdivisions, + shape.r, shape.g, shape.b, shape.a); } } // some raw shit - public static void drawLine(BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha) { - + public static void drawLine(Tessellator tessellator, BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha) { + builder.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR); // 3 builder.vertex(x1, y1, z1).color(red1, grn1, blu1, alpha).next(); builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); + tessellator.draw(); } - public static void drawBoxWireGLLines(BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha, float red2, float grn2, float blu2) { + public static void drawBoxWireGLLines(Tessellator tessellator, BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha, float red2, float grn2, float blu2) { + builder.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR); // 3 builder.vertex(x1, y1, z1).color(red1, grn2, blu2, alpha).next(); builder.vertex(x2, y1, z1).color(red1, grn2, blu2, alpha).next(); builder.vertex(x1, y1, z1).color(red2, grn1, blu2, alpha).next(); @@ -237,7 +256,8 @@ public class ShapesRenderer builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); } - public static void drawBox(BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha) { + public static void drawBoxFaces(Tessellator tessellator, BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha) { + builder.begin(GL11.GL_QUADS, VertexFormats.POSITION_COLOR); // 3 builder.vertex(x1, y1, z1).color(red1, grn1, blu1, alpha).next(); builder.vertex(x2, y1, z1).color(red1, grn1, blu1, alpha).next(); builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); @@ -267,5 +287,44 @@ public class ShapesRenderer builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); builder.vertex(x1, y2, z2).color(red1, grn1, blu1, alpha).next(); + tessellator.draw(); + } + + public static void drawSphereWireframe(Tessellator tessellator, BufferBuilder builder, + float cx, float cy, float cz, + float r, int subd, + float red, float grn, float blu, float alpha) + { + float pihalf = (float)(Math.PI / 180.0f); + float step = 180f / (subd/2); + for (float i = 0f; i <= 360.0f; i+=step) + { + builder.begin(GL11.GL_LINE_STRIP, VertexFormats.POSITION_COLOR); + float theta = i * pihalf; + for (float j = 0f; j <= 180.0f; j+=step) { + float phi = j * pihalf; + float x = r * MathHelper.sin(phi) * MathHelper.cos(theta); + float z = r * MathHelper.sin(phi) * MathHelper.sin(theta); + float y = r * MathHelper.cos(phi); + builder.vertex(x+cx, y+cy, z+cz).color(red, grn, blu, alpha).next(); + } + tessellator.draw(); + } + for (float j = 0f; j <= 180.0f; j+=step) + { + builder.begin(GL11.GL_LINE_LOOP, VertexFormats.POSITION_COLOR); + float phi = j * pihalf; + + for (float i = 0f; i <= 360.0f; i+=step) + { + float theta = i * pihalf; + float x = r * MathHelper.sin(phi) * MathHelper.cos(theta); + float z = r * MathHelper.sin(phi) * MathHelper.sin(theta); + float y = r * MathHelper.cos(phi); + builder.vertex(x+cx, y+cy, z+cz).color(red, grn, blu, alpha).next(); + } + tessellator.draw(); + } + } } From 5285eb33d618a10d4c765d995f1a0ed9946e0d84 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 3 Jun 2020 22:49:23 -0300 Subject: [PATCH 168/198] tuning of shapes --- .../carpet/script/utils/ShapeDispatcher.java | 20 +++- .../carpet/script/utils/ShapesRenderer.java | 94 ++++++++++++++----- .../assets/carpet/scripts/overlay.sc | 23 +---- 3 files changed, 89 insertions(+), 48 deletions(-) diff --git a/src/main/java/carpet/script/utils/ShapeDispatcher.java b/src/main/java/carpet/script/utils/ShapeDispatcher.java index 5202ddf7..28a8943e 100644 --- a/src/main/java/carpet/script/utils/ShapeDispatcher.java +++ b/src/main/java/carpet/script/utils/ShapeDispatcher.java @@ -393,7 +393,11 @@ public class ShapeDispatcher public static class Sphere extends ExpiringShape { private final Set required = ImmutableSet.of("center", "radius"); - private final Map optional = ImmutableMap.of("width", new NumericValue(2.0), "level", Value.ZERO); + private final Map optional = ImmutableMap.of( + "width", new NumericValue(2.0), + "level", Value.ZERO, + "fill", new NumericValue(0xffffff00) + ); @Override protected Set requiredParams() { return Sets.union(super.requiredParams(), required); } @Override @@ -410,6 +414,9 @@ public class ShapeDispatcher int subdivisions; float lineWidth; + protected float fr, fg, fb, fa; + protected int fillColor; + @Override protected void init(Map options) { @@ -426,6 +433,11 @@ public class ShapeDispatcher subdivisions = Math.max(10, (int)(10*Math.sqrt(radius))); } lineWidth = NumericValue.asNumber(options.getOrDefault("width", optional.get("width"))).getFloat(); + fillColor = NumericValue.asNumber(options.getOrDefault("fill", optional.get("fill"))).getInt(); + this.fr = (float)(fillColor >> 24 & 0xFF) / 255.0F; + this.fg = (float)(fillColor >> 16 & 0xFF) / 255.0F; + this.fb = (float)(fillColor >> 8 & 0xFF) / 255.0F; + this.fa = (float)(fillColor & 0xFF) / 255.0F; } @Override @@ -461,7 +473,7 @@ public class ShapeDispatcher hash = 31*hash + Float.hashCode(radius); hash = 31*hash + level; hash = 31*hash + Float.hashCode(lineWidth); - + if (fa != 0.0) hash = 31*hash + fillColor; return hash; } } @@ -685,7 +697,7 @@ public class ShapeDispatcher public static class FillColorParam extends ColorParam { @Override - public boolean appliesTo(ExpiringShape shape) { return shape instanceof Box; } + public boolean appliesTo(ExpiringShape shape) { return shape instanceof Box || shape instanceof Sphere; } @Override public String identify() { return "fill"; } } @@ -693,7 +705,7 @@ public class ShapeDispatcher public static class FromParam extends Vec3Param { @Override - public boolean appliesTo(ExpiringShape shape) { return (shape instanceof Line) || (shape instanceof Box); } + public boolean appliesTo(ExpiringShape shape) { return shape instanceof Line || shape instanceof Box; } @Override public boolean roundsUpForBlocks() { return false; } @Override diff --git a/src/main/java/carpet/script/utils/ShapesRenderer.java b/src/main/java/carpet/script/utils/ShapesRenderer.java index 8552ca7a..2070567c 100644 --- a/src/main/java/carpet/script/utils/ShapesRenderer.java +++ b/src/main/java/carpet/script/utils/ShapesRenderer.java @@ -9,7 +9,6 @@ import net.minecraft.client.render.Tessellator; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexFormats; import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.Entity; import net.minecraft.nbt.CompoundTag; import net.minecraft.util.Identifier; import net.minecraft.util.math.MathHelper; @@ -50,45 +49,49 @@ public class ShapesRenderer DimensionType dimensionType = iWorld.getDimension().getType(); if (shapes.get(dimensionType).isEmpty()) return; long currentTime = client.world.getTime(); + RenderSystem.disableTexture(); RenderSystem.enableDepthTest(); + RenderSystem.depthFunc(515); RenderSystem.enableBlend(); RenderSystem.defaultBlendFunc(); //RenderSystem.blendFuncSeparate(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE, GlStateManager.SrcFactor.ONE, GlStateManager.DstFactor.ZERO); - RenderSystem.shadeModel(7425); + //RenderSystem.shadeModel(7425); + RenderSystem.shadeModel(GL11.GL_FLAT); RenderSystem.enableAlphaTest(); RenderSystem.defaultAlphaFunc(); - Entity entity = this.client.gameRenderer.getCamera().getFocusedEntity(); + //RenderSystem.alphaFunc(GL11.GL_GREATER, 0.005F); + RenderSystem.disableCull(); + RenderSystem.disableLighting(); + RenderSystem.depthMask(false); + RenderSystem.polygonOffset(-3f, -3f); + RenderSystem.enablePolygonOffset(); + //Entity entity = this.client.gameRenderer.getCamera().getFocusedEntity(); Tessellator tessellator = Tessellator.getInstance(); BufferBuilder bufferBuilder = tessellator.getBuffer(); - double d = 0.0D - cameraY; - double e = 256.0D - cameraY; - RenderSystem.disableTexture(); - //RenderSystem.disableBlend(); - double f = (double)(entity.chunkX << 4) - cameraX; - double g = (double)(entity.chunkZ << 4) - cameraZ; + // render synchronized (shapes) { shapes.get(dimensionType).int2ObjectEntrySet().removeIf( entry -> entry.getValue().isExpired(currentTime) ); - shapes.get(dimensionType).values().forEach( - s -> s.render(tessellator, bufferBuilder, (float) cameraX, (float) cameraY, (float) cameraZ) - ); shapes.get(dimensionType).values().forEach( s -> s.render2pass(tessellator, bufferBuilder, (float) cameraX, (float) cameraY, (float) cameraZ) ); + //lines + shapes.get(dimensionType).values().forEach( + s -> s.render(tessellator, bufferBuilder, (float) cameraX, (float) cameraY, (float) cameraZ) + ); } - RenderSystem.lineWidth(1.0F); RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); RenderSystem.enableTexture(); RenderSystem.shadeModel(7424); } public void addShape(CompoundTag tag) { - //CarpetSettings.LOG.error("Received tag: "+tag.asString()); ShapeDispatcher.ExpiringShape shape = ShapeDispatcher.fromTag(tag); if (shape == null) return; BiFunction> shapeFactory; @@ -160,14 +163,13 @@ public class ShapesRenderer @Override public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) { + if (shape.a == 0.0) return; RenderSystem.lineWidth(shape.lineWidth); - drawBoxWireGLLines(tessellator, bufferBuilder, shape.x1 - cx-renderEpsilon, shape.y1 - cy-renderEpsilon, shape.z1 - cz-renderEpsilon, shape.x2 - cx+renderEpsilon, shape.y2 - cy+renderEpsilon, shape.z2 - cz+renderEpsilon, shape.r, shape.g, shape.b, shape.a, shape.r, shape.g, shape.b ); - tessellator.draw(); } @Override public void render2pass(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) @@ -211,12 +213,23 @@ public class ShapesRenderer @Override public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) { + if (shape.a == 0.0) return; RenderSystem.lineWidth(shape.lineWidth); drawSphereWireframe(tessellator, bufferBuilder, shape.cx-cx-renderEpsilon, shape.cy-cy-renderEpsilon, shape.cz-cz-renderEpsilon, shape.radius, shape.subdivisions, shape.r, shape.g, shape.b, shape.a); } + @Override + public void render2pass(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) + { + if (shape.fa == 0.0) return; + RenderSystem.lineWidth(1.0f); + drawSphereFaces(tessellator, bufferBuilder, + shape.cx-cx-renderEpsilon, shape.cy-cy-renderEpsilon, shape.cz-cz-renderEpsilon, + shape.radius, shape.subdivisions, + shape.fr, shape.fg, shape.fb, shape.fa); + } } // some raw shit @@ -225,10 +238,10 @@ public class ShapesRenderer builder.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR); // 3 builder.vertex(x1, y1, z1).color(red1, grn1, blu1, alpha).next(); builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); - tessellator.draw(); } - public static void drawBoxWireGLLines(Tessellator tessellator, BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha, float red2, float grn2, float blu2) { + public static void drawBoxWireGLLines(Tessellator tessellator, BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha, float red2, float grn2, float blu2) + { builder.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR); // 3 builder.vertex(x1, y1, z1).color(red1, grn2, blu2, alpha).next(); builder.vertex(x2, y1, z1).color(red1, grn2, blu2, alpha).next(); @@ -254,24 +267,26 @@ public class ShapesRenderer builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); + tessellator.draw(); } - public static void drawBoxFaces(Tessellator tessellator, BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha) { - builder.begin(GL11.GL_QUADS, VertexFormats.POSITION_COLOR); // 3 + public static void drawBoxFaces(Tessellator tessellator, BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha) + { + builder.begin(GL11.GL_QUADS, VertexFormats.POSITION_COLOR); builder.vertex(x1, y1, z1).color(red1, grn1, blu1, alpha).next(); builder.vertex(x2, y1, z1).color(red1, grn1, blu1, alpha).next(); builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); builder.vertex(x1, y2, z1).color(red1, grn1, blu1, alpha).next(); builder.vertex(x1, y1, z2).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x2, y1, z2).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); builder.vertex(x1, y2, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y1, z2).color(red1, grn1, blu1, alpha).next(); builder.vertex(x1, y1, z1).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x1, y1, z2).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x1, y2, z2).color(red1, grn1, blu1, alpha).next(); builder.vertex(x1, y2, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x1, y2, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x1, y1, z2).color(red1, grn1, blu1, alpha).next(); builder.vertex(x2, y1, z1).color(red1, grn1, blu1, alpha).next(); builder.vertex(x2, y1, z2).color(red1, grn1, blu1, alpha).next(); @@ -279,9 +294,9 @@ public class ShapesRenderer builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); builder.vertex(x1, y1, z1).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x2, y1, z1).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x2, y1, z2).color(red1, grn1, blu1, alpha).next(); builder.vertex(x1, y1, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y1, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y1, z1).color(red1, grn1, blu1, alpha).next(); builder.vertex(x1, y2, z1).color(red1, grn1, blu1, alpha).next(); builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); @@ -327,4 +342,31 @@ public class ShapesRenderer } } + + public static void drawSphereFaces(Tessellator tessellator, BufferBuilder builder, + float cx, float cy, float cz, + float r, int subd, + float red, float grn, float blu, float alpha) + { + float pihalf = (float)(Math.PI / 180.0f); + float step = 180f / (subd/2); + for (float i = 0f; i < 359.99f; i += step) + { + float theta = i * pihalf; + float thetaprime = (i + step) * pihalf; + builder.begin(GL11.GL_QUAD_STRIP, VertexFormats.POSITION_COLOR); + for (float j = 0f; j < 179.9f; j += step) + { + float phi = j * pihalf; + float x = r * MathHelper.sin(phi) * MathHelper.cos(theta); + float z = r * MathHelper.sin(phi) * MathHelper.sin(theta); + float y = r * MathHelper.cos(phi); + float xp = r * MathHelper.sin(phi) * MathHelper.cos(thetaprime); + float zp = r * MathHelper.sin(phi) * MathHelper.sin(thetaprime); + builder.vertex(x + cx, y + cy, z + cz).color(red, grn, blu, alpha).next(); + builder.vertex(xp + cx, y + cy, zp + cz).color(red, grn, blu, alpha).next(); + } + tessellator.draw(); + } + } } diff --git a/src/main/resources/assets/carpet/scripts/overlay.sc b/src/main/resources/assets/carpet/scripts/overlay.sc index fb6b5a52..81b42749 100644 --- a/src/main/resources/assets/carpet/scripts/overlay.sc +++ b/src/main/resources/assets/carpet/scripts/overlay.sc @@ -6,7 +6,7 @@ global_renderers = m( l('handler', '__structure_renderer'), l('tasks', m()), l('range', 3), - l('max_pieces', 4) + l('max_pieces', 6) )), l('chunks', m( l('active', false), @@ -94,20 +94,16 @@ __structure_renderer(player_name) -> l(from, to) = structure_data; total_size = _euclidean(from, to); density = max(10, total_size/10); - //particle_box('dust 0 1 1 2', from, to+1, density); - draw_shape('box', 15, 'from', from, 'to', to+1, 'color', 0x00FFFFFF, 'width', 3); + draw_shape('box', 15, 'from', from, 'to', to+1, 'color', 0x00FFFFFF, 'width', 3, 'fill', 0x00FFFF22); structure_pieces = slice(sort_key(structure_pieces, _euclidean_sq((_:2+_:3)/2,ppos)), 0, config:'max_pieces'); for (structure_pieces, l(piece, direction, from, to) = _; - //factor = 1- _i / config:'max_pieces' / 2; - //total_size = _euclidean(from, to); - //density = max(_i+1, total_size/10); - //particle_box(str('dust %.2f %.2f 1 1',factor, factor), from, to+1, density); - r = 255 - 128 * _i/config:'max_pieces'; + r = 255 - floor(128 * _i/config:'max_pieces'); g = r; b = 255; a = 255; color = 256*(b+256*(g+256*r)); // leaving out a - draw_shape('box', 15, 'from', from, 'to', to+1, 'color', color+a, 'fill', color+a/6); + draw_shape('box', 15, 'from', from, 'to', to+1, 'color', color+a); + draw_shape('box', 15, 'from', from, 'to', to+1, 'color', 0xffffff00, 'fill', 0xffffff22); ) ) ); @@ -143,15 +139,6 @@ __chunk_renderer(player_name) -> draw_shape('line', 15, 'from', top_01, 'to', top_00, 'color', color, 'width', 3); draw_shape('line', 15, 'from', top_00, 'to', top_11, 'color', color, 'width', 3); draw_shape('line', 15, 'from', top_01, 'to', top_10, 'color', color, 'width', 3); - - //part = 'dust 0.2 0.8 0.2 2'; - //density = 2+player_distance/2; - //particle_line(part, top_00, top_10, density); - //particle_line(part, top_10, top_11, density); - //particle_line(part, top_11, top_01, density); - //particle_line(part, top_01, top_00, density); - //particle_line(part, top_00, top_11, density); - //particle_line(part, top_01, top_10, density); ) ) ) From bd29eef3e85e4233e1029e4cb201d61a31094368 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 3 Jun 2020 23:03:11 -0300 Subject: [PATCH 169/198] tuning of shapes --- src/main/java/carpet/script/utils/ShapesRenderer.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/carpet/script/utils/ShapesRenderer.java b/src/main/java/carpet/script/utils/ShapesRenderer.java index 2070567c..a9e610f3 100644 --- a/src/main/java/carpet/script/utils/ShapesRenderer.java +++ b/src/main/java/carpet/script/utils/ShapesRenderer.java @@ -63,8 +63,8 @@ public class ShapesRenderer RenderSystem.disableCull(); RenderSystem.disableLighting(); RenderSystem.depthMask(false); - RenderSystem.polygonOffset(-3f, -3f); - RenderSystem.enablePolygonOffset(); + //RenderSystem.polygonOffset(-3f, -3f); + //RenderSystem.enablePolygonOffset(); //Entity entity = this.client.gameRenderer.getCamera().getFocusedEntity(); Tessellator tessellator = Tessellator.getInstance(); BufferBuilder bufferBuilder = tessellator.getBuffer(); @@ -83,6 +83,8 @@ public class ShapesRenderer s -> s.render(tessellator, bufferBuilder, (float) cameraX, (float) cameraY, (float) cameraZ) ); } + RenderSystem.enableCull(); + RenderSystem.depthMask(true); RenderSystem.lineWidth(1.0F); RenderSystem.enableBlend(); RenderSystem.defaultBlendFunc(); From 2e8ebc402e5323a8ead16706cde333662901fd11 Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 4 Jun 2020 02:33:32 -0300 Subject: [PATCH 170/198] allowed 'follow' in draw_shape --- docs/scarpet/Full.md | 3 + docs/scarpet/api/Auxiliary.md | 3 + .../carpet/script/utils/ShapeDispatcher.java | 134 +++++++++++++++--- .../carpet/script/utils/ShapesRenderer.java | 94 ++++++++---- 4 files changed, 186 insertions(+), 48 deletions(-) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index a0bac5ea..717784c7 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -3162,6 +3162,9 @@ Available shapes: * `to` - other end of the line, same format as `from` * Optional attributes: * `width` - line thickness, defaults to 2.0pt + * `follow` - entity, or player name. Shape will follow an entity instead of being static. + Follow attribute requires all positional arguments to be relative to the entity and disallow + of using entity or block as position markers. You must specify positions as a triple. * `'box'` - draws a box with corners in specified points * Required attributes: diff --git a/docs/scarpet/api/Auxiliary.md b/docs/scarpet/api/Auxiliary.md index 90860cc9..37fd8323 100644 --- a/docs/scarpet/api/Auxiliary.md +++ b/docs/scarpet/api/Auxiliary.md @@ -68,6 +68,9 @@ Available shapes: * `to` - other end of the line, same format as `from` * Optional attributes: * `width` - line thickness, defaults to 2.0pt + * `follow` - entity, or player name. Shape will follow an entity instead of being static. + Follow attribute requires all positional arguments to be relative to the entity and disallow + of using entity or block as position markers. You must specify positions as a triple. * `'box'` - draws a box with corners in specified points * Required attributes: diff --git a/src/main/java/carpet/script/utils/ShapeDispatcher.java b/src/main/java/carpet/script/utils/ShapeDispatcher.java index 28a8943e..b636bafe 100644 --- a/src/main/java/carpet/script/utils/ShapeDispatcher.java +++ b/src/main/java/carpet/script/utils/ShapeDispatcher.java @@ -109,7 +109,7 @@ public class ShapeDispatcher userParams.keySet().forEach(key -> { Param param = Param.coders.get(key); if (param==null) throw new InternalExpressionException("Unknown feature for shape: "+key); - userParams.put(key, param.validate(cc, userParams.get(key))); + userParams.put(key, param.validate(userParams, cc, userParams.get(key))); }); Function,ExpiringShape> factory = ExpiringShape.shapeProviders.get(shapeType); if (factory == null) throw new InternalExpressionException("Unknown shape: "+shapeType); @@ -174,6 +174,9 @@ public class ShapeDispatcher protected int color; protected int duration = 0; private int key; + protected int followEntity; + protected DimensionType entityDimension; + protected ExpiringShape() { } @@ -212,8 +215,19 @@ public class ShapeDispatcher this.b = (float)(color >> 8 & 0xFF) / 255.0F; this.a = (float)(color & 0xFF) / 255.0F; key = 0; + followEntity = -1; + entityDimension = null; + if (options.containsKey("follow")) + { + followEntity = NumericValue.asNumber(options.getOrDefault("follow", optional.get("follow"))).getInt(); + entityDimension = Registry.DIMENSION_TYPE.get(new Identifier(options.get("dim").getString())); + } } public int getExpiry() { return duration; } + public Vec3d toAbsolute(Entity e, float x, float y, float z) + { + return e.getPos().add(x,y,z); + } public abstract Consumer alternative(); public int key() { @@ -225,13 +239,15 @@ public class ShapeDispatcher { int hash = 17; hash = 31*hash + color; + hash = 31*hash + followEntity; return hash; } // list of params that need to be there private final Set required = ImmutableSet.of("duration", "shape", "dim"); private final Map optional = ImmutableMap.of( "color", new NumericValue(-1), - "player", Value.NULL + "player", Value.NULL, + "follow", new NumericValue(-1) ); protected Set requiredParams() {return required;} // list of params that can be there, with defaults @@ -281,13 +297,26 @@ public class ShapeDispatcher @Override public Consumer alternative() { + String particleName = String.format(Locale.ROOT , "dust %.1f %.1f %.1f 1.0", r, g, b); ParticleEffect particle = getParticleData(particleName); double dx = x1-x2; double dy = y1-y2; double dz = z1-z2; double density = Math.max(2.0, Math.sqrt(dx*dx+dy*dy+dz*dz) /50) / (a+0.1); - return p -> mesh(Collections.singletonList(p), particle, density, x1, y1, z1, x2, y2, z2); + return p -> + { + if (followEntity == -1) + { + mesh(Collections.singletonList(p), particle, density, x1, y1, z1, x2, y2, z2); + return; + } + Entity e = p.getServer().getWorld(entityDimension).getEntityById(followEntity); + if (e == null) return; + Vec3d rel1 = toAbsolute(e, x1, y1, z1); + Vec3d rel2 = toAbsolute(e, x2, y2, z2); + mesh(Collections.singletonList(p), particle, density, rel1.x, rel1.y, rel1.z, rel2.x, rel2.y, rel2.z); + }; } @Override @@ -371,7 +400,20 @@ public class ShapeDispatcher double dy = y1-y2; double dz = z1-z2; double density = Math.max(2.0, Math.sqrt(dx*dx+dy*dy+dz*dz) /50) / (a+0.1); - return p -> drawParticleLine(Collections.singletonList(p), particle, pos1, pos2, density); + return p -> + { + if (followEntity == -1) + { + drawParticleLine(Collections.singletonList(p), particle, pos1, pos2, density); + return; + } + + Entity e = p.getServer().getWorld(entityDimension).getEntityById(followEntity); + if (e == null) return; + Vec3d rel1 = toAbsolute(e, x1, y1, z1); + Vec3d rel2 = toAbsolute(e, x2, y2, z2); + drawParticleLine(Collections.singletonList(p), particle, rel1, rel2, density); + }; } @Override @@ -449,15 +491,32 @@ public class ShapeDispatcher int partno = Math.min(1000,20*subdivisions); Random rand = p.world.getRandom(); ServerWorld world = p.getServerWorld(); + + float ccx, ccy, ccz; + if (followEntity == -1) + { + ccx = cx; ccy = cy; ccz = cz; + } + else + { + Entity e = p.getServer().getWorld(entityDimension).getEntityById(followEntity); + if (e == null) return; + Vec3d rel1 = toAbsolute(e, cx, cy, cz); + ccx = (float)rel1.x; ccy = (float)rel1.y; ccz = (float)rel1.z; + } + for (int i=0; i options, CarpetContext cc, Value value); // makes sure the value is proper boolean appliesTo(ExpiringShape shape); // check if applies to the shape String identify(); } @@ -519,7 +582,7 @@ public class ShapeDispatcher public Tag toTag(Value value) { return null; } @Override - public Value validate(CarpetContext cc, Value value) + public Value validate(Map options, CarpetContext cc, Value value) { ServerPlayerEntity player = EntityValue.getPlayerByValue(cc.s.getMinecraftServer(), value); if (player == null) @@ -538,15 +601,13 @@ public class ShapeDispatcher { @Override public Tag toTag(Value value) { return StringTag.of(value.getString()); } - @Override - public Value validate(CarpetContext cc, Value value) { return value; } public static Value decode(Tag tag) { return new StringValue(tag.asString()); } } public static class DimensionParam extends StringParam { @Override - public Value validate(CarpetContext cc, Value value) + public Value validate(Map options, CarpetContext cc, Value value) { String dimStr = value.getString(); Optional dimOp = Registry.DIMENSION_TYPE.getOrEmpty(new Identifier(dimStr)); @@ -561,7 +622,7 @@ public class ShapeDispatcher public static class ShapeParam extends StringParam { @Override - public Value validate(CarpetContext cc, Value value) + public Value validate(Map options, CarpetContext cc, Value value) { String shape = value.getString(); if (!ExpiringShape.shapeProviders.containsKey(shape)) @@ -576,7 +637,7 @@ public class ShapeDispatcher public static abstract class NumericParam implements Param { @Override - public Value validate(CarpetContext cc, Value value) + public Value validate(Map options, CarpetContext cc, Value value) { if (!(value instanceof NumericValue)) throw new InternalExpressionException("'" + identify() + "' needs to be a number"); @@ -585,9 +646,9 @@ public class ShapeDispatcher } public static abstract class PositiveParam extends NumericParam { - @Override public Value validate(CarpetContext cc, Value value) + @Override public Value validate(Map options, CarpetContext cc, Value value) { - Value ret = super.validate(cc, value); + Value ret = super.validate(options, cc, value); if (((NumericValue)ret).getDouble()<=0) throw new InternalExpressionException("'"+identify()+"' should be positive"); return ret; } @@ -628,10 +689,12 @@ public class ShapeDispatcher public abstract String identify(); @Override - public Value validate(CarpetContext cc, Value value) + public Value validate(Map options, CarpetContext cc, Value value) { if (value instanceof BlockValue) { + if (options.containsKey("follow")) + throw new InternalExpressionException(identify()+" parameter cannot use blocks as positions for relative positioning due to 'follow' attribute being present"); BlockPos pos = ((BlockValue) value).getPos(); int offset = roundsUpForBlocks()?1:0; return ListValue.of( @@ -653,6 +716,8 @@ public class ShapeDispatcher } if (value instanceof EntityValue) { + if (options.containsKey("follow")) + throw new InternalExpressionException(identify()+" parameter cannot use entity as positions for relative positioning due to 'follow' attribute being present"); Entity e = ((EntityValue) value).getEntity(); return ListValue.of( new NumericValue(e.getX()), @@ -745,6 +810,35 @@ public class ShapeDispatcher @Override public String identify() { return "level"; } } + public abstract static class EntityParam implements Param + { + + @Override + public Tag toTag(Value value) + { + return IntTag.of(NumericValue.asNumber(value).getInt()); + } + + @Override + public Value validate(Map options, CarpetContext cc, Value value) + { + if (value instanceof EntityValue) return new NumericValue(((EntityValue) value).getEntity().getEntityId()); + ServerPlayerEntity player = EntityValue.getPlayerByValue(cc.s.getMinecraftServer(), value); + if (player == null) + throw new InternalExpressionException(identify()+" parameter needs to represent an entity or player"); + return new NumericValue(player.getEntityId()); + } + + @Override + public boolean appliesTo(ExpiringShape shape) { return true; } + + public static Value decode(Tag tag) { return new NumericValue(((IntTag)tag).getInt()); } + } + public static class FollowParam extends EntityParam + { + @Override + public String identify() { return "follow"; } + } diff --git a/src/main/java/carpet/script/utils/ShapesRenderer.java b/src/main/java/carpet/script/utils/ShapesRenderer.java index a9e610f3..0567ef08 100644 --- a/src/main/java/carpet/script/utils/ShapesRenderer.java +++ b/src/main/java/carpet/script/utils/ShapesRenderer.java @@ -9,9 +9,11 @@ import net.minecraft.client.render.Tessellator; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexFormats; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.Entity; import net.minecraft.nbt.CompoundTag; import net.minecraft.util.Identifier; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.registry.Registry; import net.minecraft.world.IWorld; import net.minecraft.world.dimension.DimensionType; @@ -76,11 +78,17 @@ public class ShapesRenderer entry -> entry.getValue().isExpired(currentTime) ); shapes.get(dimensionType).values().forEach( - s -> s.render2pass(tessellator, bufferBuilder, (float) cameraX, (float) cameraY, (float) cameraZ) + s -> + { + if ( s.shouldRender(dimensionType)) s.render2pass(tessellator, bufferBuilder, (float) cameraX, (float) cameraY, (float) cameraZ); + } ); //lines shapes.get(dimensionType).values().forEach( - s -> s.render(tessellator, bufferBuilder, (float) cameraX, (float) cameraY, (float) cameraZ) + + s -> { + if ( s.shouldRender(dimensionType)) s.render(tessellator, bufferBuilder, (float) cameraX, (float) cameraY, (float) cameraZ); + } ); } RenderSystem.enableCull(); @@ -133,6 +141,7 @@ public class ShapesRenderer public abstract static class RenderedShape { protected T shape; + protected MinecraftClient client; long expiryTick; float renderEpsilon = 0; public abstract void render(Tessellator tessellator, BufferBuilder builder, float cx, float cy, float cz ); @@ -142,6 +151,7 @@ public class ShapesRenderer this.shape = shape; expiryTick = client.world.getTime()+shape.getExpiry(); renderEpsilon = (2+((float)shape.key())/Integer.MAX_VALUE)/1000; + this.client = client; } public boolean isExpired(long currentTick) @@ -152,6 +162,20 @@ public class ShapesRenderer { return shape.key(); }; + public boolean shouldRender(DimensionType dim) + { + if (shape.followEntity <=0 ) return true; + if (client.world == null) return false; + if (client.world.dimension.getType() != dim) return false; + if (client.world.getEntityById(shape.followEntity) == null) return false; + return true; + } + protected Vec3d relativiseRender(float x, float y, float z) + { + if (shape.followEntity <= 0) return new Vec3d(x,y,z); + Entity e = client.world.getEntityById(shape.followEntity); + return shape.toAbsolute(e, x, y, z); + } } public static class RenderedBox extends RenderedShape @@ -166,10 +190,12 @@ public class ShapesRenderer public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) { if (shape.a == 0.0) return; + Vec3d v1 = relativiseRender(shape.x1, shape.y1, shape.z1); + Vec3d v2 = relativiseRender(shape.x2, shape.y2, shape.z2); RenderSystem.lineWidth(shape.lineWidth); drawBoxWireGLLines(tessellator, bufferBuilder, - shape.x1 - cx-renderEpsilon, shape.y1 - cy-renderEpsilon, shape.z1 - cz-renderEpsilon, - shape.x2 - cx+renderEpsilon, shape.y2 - cy+renderEpsilon, shape.z2 - cz+renderEpsilon, + (float)v1.x-cx-renderEpsilon, (float)v1.y-cy-renderEpsilon, (float)v1.z-cz-renderEpsilon, + (float)v2.x-cx+renderEpsilon, (float)v2.y-cy+renderEpsilon, (float)v2.z-cz+renderEpsilon, shape.r, shape.g, shape.b, shape.a, shape.r, shape.g, shape.b ); } @@ -177,15 +203,17 @@ public class ShapesRenderer public void render2pass(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) { if (shape.fa == 0.0) return; + Vec3d v1 = relativiseRender(shape.x1, shape.y1, shape.z1); + Vec3d v2 = relativiseRender(shape.x2, shape.y2, shape.z2); RenderSystem.lineWidth(1.0F); - drawBoxFaces(tessellator, bufferBuilder, - shape.x1-cx-renderEpsilon, shape.y1-cy-renderEpsilon, shape.z1-cz-renderEpsilon, - shape.x2-cx+renderEpsilon, shape.y2-cy+renderEpsilon, shape.z2-cz+renderEpsilon, + (float)v1.x-cx-renderEpsilon, (float)v1.y-cy-renderEpsilon, (float)v1.z-cz-renderEpsilon, + (float)v2.x-cx+renderEpsilon, (float)v2.y-cy+renderEpsilon, (float)v2.z-cz+renderEpsilon, shape.fr, shape.fg, shape.fb, shape.fa ); } + } public static class RenderedLine extends RenderedShape @@ -197,10 +225,12 @@ public class ShapesRenderer @Override public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) { + Vec3d v1 = relativiseRender(shape.x1, shape.y1, shape.z1); + Vec3d v2 = relativiseRender(shape.x2, shape.y2, shape.z2); RenderSystem.lineWidth(shape.lineWidth); drawLine(tessellator, bufferBuilder, - shape.x1-cx-renderEpsilon, shape.y1-cy-renderEpsilon, shape.z1-cz-renderEpsilon, - shape.x2-cx+renderEpsilon, shape.y2-cy+renderEpsilon, shape.z2-cz+renderEpsilon, + (float)v1.x-cx-renderEpsilon, (float)v1.y-cy-renderEpsilon, (float)v1.z-cz-renderEpsilon, + (float)v2.x-cx+renderEpsilon, (float)v2.y-cy+renderEpsilon, (float)v2.z-cz+renderEpsilon, shape.r, shape.g, shape.b, shape.a ); } @@ -216,9 +246,11 @@ public class ShapesRenderer public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) { if (shape.a == 0.0) return; + Vec3d vc = relativiseRender(shape.cx, shape.cy, shape.cz); + RenderSystem.lineWidth(shape.lineWidth); drawSphereWireframe(tessellator, bufferBuilder, - shape.cx-cx-renderEpsilon, shape.cy-cy-renderEpsilon, shape.cz-cz-renderEpsilon, + (float)vc.x-cx-renderEpsilon, (float)vc.y-cy-renderEpsilon, (float)vc.z-cz-renderEpsilon, shape.radius, shape.subdivisions, shape.r, shape.g, shape.b, shape.a); } @@ -226,9 +258,10 @@ public class ShapesRenderer public void render2pass(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) { if (shape.fa == 0.0) return; + Vec3d vc = relativiseRender(shape.cx, shape.cy, shape.cz); RenderSystem.lineWidth(1.0f); drawSphereFaces(tessellator, bufferBuilder, - shape.cx-cx-renderEpsilon, shape.cy-cy-renderEpsilon, shape.cz-cz-renderEpsilon, + (float)vc.x-cx-renderEpsilon, (float)vc.y-cy-renderEpsilon, (float)vc.z-cz-renderEpsilon, shape.radius, shape.subdivisions, shape.fr, shape.fg, shape.fb, shape.fa); } @@ -240,6 +273,7 @@ public class ShapesRenderer builder.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR); // 3 builder.vertex(x1, y1, z1).color(red1, grn1, blu1, alpha).next(); builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); + tessellator.draw(); } public static void drawBoxWireGLLines(Tessellator tessellator, BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha, float red2, float grn2, float blu2) @@ -312,14 +346,16 @@ public class ShapesRenderer float r, int subd, float red, float grn, float blu, float alpha) { - float pihalf = (float)(Math.PI / 180.0f); - float step = 180f / (subd/2); - for (float i = 0f; i <= 360.0f; i+=step) + float step = (float)Math.PI / (subd/2); + int num_steps180 = (int)(Math.PI / step)+1; + int num_steps360 = (int)(2*Math.PI / step); + for (int i = 0; i <= num_steps360; i++) { builder.begin(GL11.GL_LINE_STRIP, VertexFormats.POSITION_COLOR); - float theta = i * pihalf; - for (float j = 0f; j <= 180.0f; j+=step) { - float phi = j * pihalf; + float theta = step * i ; + for (int j = 0; j <= num_steps180; j++) + { + float phi = step * j ; float x = r * MathHelper.sin(phi) * MathHelper.cos(theta); float z = r * MathHelper.sin(phi) * MathHelper.sin(theta); float y = r * MathHelper.cos(phi); @@ -327,14 +363,14 @@ public class ShapesRenderer } tessellator.draw(); } - for (float j = 0f; j <= 180.0f; j+=step) + for (int j = 0; j <= num_steps180; j++) { builder.begin(GL11.GL_LINE_LOOP, VertexFormats.POSITION_COLOR); - float phi = j * pihalf; + float phi = step * j ; - for (float i = 0f; i <= 360.0f; i+=step) + for (int i = 0; i <= num_steps360; i++) { - float theta = i * pihalf; + float theta = step * i; float x = r * MathHelper.sin(phi) * MathHelper.cos(theta); float z = r * MathHelper.sin(phi) * MathHelper.sin(theta); float y = r * MathHelper.cos(phi); @@ -350,16 +386,18 @@ public class ShapesRenderer float r, int subd, float red, float grn, float blu, float alpha) { - float pihalf = (float)(Math.PI / 180.0f); - float step = 180f / (subd/2); - for (float i = 0f; i < 359.99f; i += step) + + float step = (float)Math.PI / (subd/2); + int num_steps180 = (int)(Math.PI / step)+1; + int num_steps360 = (int)(2*Math.PI / step); + for (int i = 0; i <= num_steps360; i++) { - float theta = i * pihalf; - float thetaprime = (i + step) * pihalf; + float theta = i * step; + float thetaprime = theta+step; builder.begin(GL11.GL_QUAD_STRIP, VertexFormats.POSITION_COLOR); - for (float j = 0f; j < 179.9f; j += step) + for (int j = 0; j <= num_steps180; j++) { - float phi = j * pihalf; + float phi = j * step; float x = r * MathHelper.sin(phi) * MathHelper.cos(theta); float z = r * MathHelper.sin(phi) * MathHelper.sin(theta); float y = r * MathHelper.cos(phi); From 1c3d017e01ea0779b7c86cf772bc89dfd6628f88 Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 4 Jun 2020 12:52:36 -0300 Subject: [PATCH 171/198] keeping versions of connected clients --- .../java/carpet/network/ServerNetworkHandler.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main/java/carpet/network/ServerNetworkHandler.java b/src/main/java/carpet/network/ServerNetworkHandler.java index b609dd7d..ba6d1db0 100644 --- a/src/main/java/carpet/network/ServerNetworkHandler.java +++ b/src/main/java/carpet/network/ServerNetworkHandler.java @@ -11,12 +11,14 @@ import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.PacketByteBuf; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; public class ServerNetworkHandler { - public static Set remoteCarpetPlayers = new HashSet<>(); + public static Map remoteCarpetPlayers = new HashMap<>(); public static Set validCarpetPlayers = new HashSet<>(); public static void handleData(PacketByteBuf data, ServerPlayerEntity player) @@ -46,9 +48,10 @@ public class ServerNetworkHandler public static void onHello(ServerPlayerEntity playerEntity, PacketByteBuf packetData) { - remoteCarpetPlayers.add(playerEntity); + validCarpetPlayers.add(playerEntity); String clientVersion = packetData.readString(64); + remoteCarpetPlayers.put(playerEntity, clientVersion); if (clientVersion.equals(CarpetSettings.carpetVersion)) CarpetSettings.LOG.info("Player "+playerEntity.getName().getString()+" joined with a matching carpet client"); else @@ -60,7 +63,7 @@ public class ServerNetworkHandler public static void updateRuleWithConnectedClients(ParsedRule rule) { - for (ServerPlayerEntity player : remoteCarpetPlayers) + for (ServerPlayerEntity player : remoteCarpetPlayers.keySet()) { player.networkHandler.sendPacket(new CustomPayloadS2CPacket( CarpetClient.CARPET_CHANNEL, @@ -71,7 +74,7 @@ public class ServerNetworkHandler public static void updateTickSpeedToConnectedPlayers() { - for (ServerPlayerEntity player : remoteCarpetPlayers) + for (ServerPlayerEntity player : remoteCarpetPlayers.keySet()) { player.networkHandler.sendPacket(new CustomPayloadS2CPacket( CarpetClient.CARPET_CHANNEL, @@ -80,7 +83,7 @@ public class ServerNetworkHandler } } - public static void sendCustomCommand(String command, Tag data) + public static void broadcastCustomCommand(String command, Tag data) { for (ServerPlayerEntity player : validCarpetPlayers) { From 8b2e70312863d5e86e33adaf907c6ffe86335ec3 Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 4 Jun 2020 13:27:58 -0300 Subject: [PATCH 172/198] adding width as optional for Spheres --- src/main/java/carpet/script/utils/ShapeDispatcher.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/carpet/script/utils/ShapeDispatcher.java b/src/main/java/carpet/script/utils/ShapeDispatcher.java index b636bafe..a97fda6f 100644 --- a/src/main/java/carpet/script/utils/ShapeDispatcher.java +++ b/src/main/java/carpet/script/utils/ShapeDispatcher.java @@ -677,7 +677,7 @@ public class ShapeDispatcher public static class WidthParam extends PositiveFloatParam { @Override - public boolean appliesTo(ExpiringShape shape) { return shape instanceof Box || shape instanceof Line; } + public boolean appliesTo(ExpiringShape shape) { return shape instanceof Box || shape instanceof Line || shape instanceof Sphere; } @Override public String identify() { return "width"; } } From 0a924a3b5eeaf8f2d370735a38124596b747d487 Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 4 Jun 2020 16:01:29 -0300 Subject: [PATCH 173/198] 1.3.26 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 27ae8895..bf908cf3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ org.gradle.jvmargs=-Xmx1G loader_version=0.8.3+build.196 # Mod Properties - mod_version = 1.3.25+v200527 + mod_version = 1.3.26+v200604 maven_group = carpet archives_base_name = fabric-carpet From ec8344626dc58bf43f196bb8150261c4cfe7a0f3 Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 4 Jun 2020 16:01:41 -0300 Subject: [PATCH 174/198] 1.3.26 --- src/main/java/carpet/CarpetSettings.java | 2 +- src/main/resources/fabric.mod.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index b66c7838..6cba4ff3 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -34,7 +34,7 @@ import static carpet.settings.RuleCategory.CLIENT; @SuppressWarnings("CanBeFinal") public class CarpetSettings { - public static final String carpetVersion = "1.3.25+v200527"; + public static final String carpetVersion = "1.3.26+v200604"; public static final Logger LOG = LogManager.getLogger(); public static boolean skipGenerationChecks = false; public static boolean impendingFillSkipUpdates = false; diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 0e33c3ef..b9beb34b 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,7 +1,7 @@ { "schemaVersion": 1, "id": "carpet", - "version": "1.3.25", + "version": "1.3.26", "name": "Carpet Mod in Fabric", "description": "Carpet made out of fabric", From 50b414727c156e7636575410a98ed369c62075e2 Mon Sep 17 00:00:00 2001 From: gnembon Date: Fri, 5 Jun 2020 00:48:02 -0300 Subject: [PATCH 175/198] refactor --- docs/scarpet/api/Auxiliary.md | 15 +- .../java/carpet/script/CarpetExpression.java | 22 +- .../carpet/script/utils/ShapeDispatcher.java | 447 +++++++----------- .../carpet/script/utils/ShapesRenderer.java | 64 +-- 4 files changed, 209 insertions(+), 339 deletions(-) diff --git a/docs/scarpet/api/Auxiliary.md b/docs/scarpet/api/Auxiliary.md index 37fd8323..b55c9f5a 100644 --- a/docs/scarpet/api/Auxiliary.md +++ b/docs/scarpet/api/Auxiliary.md @@ -60,25 +60,23 @@ Optional shared shape attributes: in the form of `0xRRGGBBAA`, with the default of `-1`, so white opaque, or `0xFFFFFFFF`. * `player` - name or player entity to send the shape to. If specified, the shapes will appear only for the specified player, otherwise it will be send to all players in the dimension. + * `width` - line thickness, defaults to 2.0pt + * `fill` - color for the faces, defaults to no fill. Use `color` attribute format + * `follow` - entity, or player name. Shape will follow an entity instead of being static. + Follow attribute requires all positional arguments to be relative to the entity and disallow + of using entity or block as position markers. You must specify positions as a triple. Available shapes: * `'line'` - draws a straight line between two points * Required attributes: * `from` - triple coordinates, entity, or block value indicating one end of the line * `to` - other end of the line, same format as `from` - * Optional attributes: - * `width` - line thickness, defaults to 2.0pt - * `follow` - entity, or player name. Shape will follow an entity instead of being static. - Follow attribute requires all positional arguments to be relative to the entity and disallow - of using entity or block as position markers. You must specify positions as a triple. * `'box'` - draws a box with corners in specified points * Required attributes: * `from` - triple coordinates, entity, or block value indicating one corner of the box * `to` - other corner, same format as `from` - * Optional attributes: - * `width` - mesh line thickness, defaults to 2.0pt - * `fill` - color for the box faces, defaults to no fill, use shared color attribute format + * `'sphere'` - draws a sphere * Required attributes: * `center` - center of the sphere @@ -86,7 +84,6 @@ Available shapes: * Optional attributes: * `level` - level of details, or grid size. The more the denser your sphere. Default level of 0, means that the level of detail will be selected automatically based on radius. - * `width` - line thickness ### `create_marker(text, pos, rotation?, block?)` diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index f3352d04..6b9e45e8 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -2635,15 +2635,11 @@ public class CarpetExpression } Vec3d a = pos1.vec; Vec3d b = pos2.vec; - double ax = min(a.x, b.x); - double ay = min(a.y, b.y); - double az = min(a.z, b.z); - double bx = max(a.x, b.x); - double by = max(a.y, b.y); - double bz = max(a.z, b.z); - int particleCount = ShapeDispatcher.Box.mesh( + Vec3d from = new Vec3d(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z)); + Vec3d to = new Vec3d(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z)); + int particleCount = ShapeDispatcher.Box.particleMesh( player==null?world.getPlayers():Collections.singletonList(player), - particle, density, ax, ay, az, bx, by, bz + particle, density, from, to ); return (c_, t_) -> new NumericValue(particleCount); }); @@ -2680,13 +2676,17 @@ public class CarpetExpression } params.putIfAbsent("dim", new StringValue(cc.s.getWorld().getDimension().getType().toString())); params.putIfAbsent("duration", duration); - - ShapeDispatcher.ExpiringShape shape = ShapeDispatcher.create(cc, shapeType, params); ServerPlayerEntity player = null; if (params.containsKey("player")) { - player = (ServerPlayerEntity)((EntityValue)params.get("player")).getEntity(); + player = EntityValue.getPlayerByValue(cc.s.getMinecraftServer(), params.get("player")); + if (player == null) + throw new InternalExpressionException("'player' parameter needs to represent an existing player"); + params.remove("player"); } + + ShapeDispatcher.ExpiringShape shape = ShapeDispatcher.create(cc, shapeType, params); + ShapeDispatcher.sendShape( (player==null)?cc.s.getWorld().getPlayers():Collections.singletonList(player), shape, diff --git a/src/main/java/carpet/script/utils/ShapeDispatcher.java b/src/main/java/carpet/script/utils/ShapeDispatcher.java index a97fda6f..5a66f723 100644 --- a/src/main/java/carpet/script/utils/ShapeDispatcher.java +++ b/src/main/java/carpet/script/utils/ShapeDispatcher.java @@ -45,8 +45,6 @@ import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; -import static java.lang.Math.sqrt; - public class ShapeDispatcher { private static final Map particleCache = new HashMap<>(); @@ -107,7 +105,7 @@ public class ShapeDispatcher { userParams.put("shape", new StringValue(shapeType)); userParams.keySet().forEach(key -> { - Param param = Param.coders.get(key); + Param param = Param.of.get(key); if (param==null) throw new InternalExpressionException("Unknown feature for shape: "+key); userParams.put(key, param.validate(userParams, cc, userParams.get(key))); }); @@ -122,13 +120,13 @@ public class ShapeDispatcher Map options = new HashMap<>(); for (String key : tag.getKeys()) { - Function decoder = Param.decoders.get(key); + Param decoder = Param.of.get(key); if (decoder==null) { CarpetSettings.LOG.info("Unknown parameter for shape: "+key); return null; } - Value decodedValue = decoder.apply(tag.get(key)); + Value decodedValue = decoder.decode(tag.get(key)); options.put(key, decodedValue); } Value shapeValue = options.get("shape"); @@ -170,8 +168,11 @@ public class ShapeDispatcher }; } + float lineWidth; protected float r, g, b, a; protected int color; + protected float fr, fg, fb, fa; + protected int fillColor; protected int duration = 0; private int key; protected int followEntity; @@ -184,7 +185,7 @@ public class ShapeDispatcher { CompoundTag tag = new CompoundTag(); params.forEach((k, v) -> { - Tag valTag = Param.coders.get(k).toTag(v); + Tag valTag = Param.of.get(k).toTag(v); if (valTag != null) tag.put(k, valTag); }); return tag; @@ -200,20 +201,33 @@ public class ShapeDispatcher if (!options.keySet().containsAll(required)) throw new InternalExpressionException("Missing required parameters for shape: "+Sets.difference(required, options.keySet())); options.keySet().forEach(k ->{ - if (!Param.coders.get(k).appliesTo(this)) + if (!this.canTake(k)) throw new InternalExpressionException("Parameter "+k+" doesn't apply for shape "+options.get("shape").getString()); }); init(options); } + + protected void init(Map options) { + duration = NumericValue.asNumber(options.get("duration")).getInt(); + + lineWidth = NumericValue.asNumber(options.getOrDefault("width", optional.get("width"))).getFloat(); + + fillColor = NumericValue.asNumber(options.getOrDefault("fill", optional.get("fill"))).getInt(); + this.fr = (float)(fillColor >> 24 & 0xFF) / 255.0F; + this.fg = (float)(fillColor >> 16 & 0xFF) / 255.0F; + this.fb = (float)(fillColor >> 8 & 0xFF) / 255.0F; + this.fa = (float)(fillColor & 0xFF) / 255.0F; + color = NumericValue.asNumber(options.getOrDefault("color", optional.get("color"))).getInt(); this.r = (float)(color >> 24 & 0xFF) / 255.0F; this.g = (float)(color >> 16 & 0xFF) / 255.0F; this.b = (float)(color >> 8 & 0xFF) / 255.0F; this.a = (float)(color & 0xFF) / 255.0F; + key = 0; followEntity = -1; entityDimension = null; @@ -224,10 +238,21 @@ public class ShapeDispatcher } } public int getExpiry() { return duration; } - public Vec3d toAbsolute(Entity e, float x, float y, float z) + public Vec3d toAbsolute(Entity e, Vec3d vec) { - return e.getPos().add(x,y,z); + return e.getPos().add(vec); } + public Vec3d vecFromValue(Value value) + { + if (!(value instanceof ListValue)) throw new InternalExpressionException("decoded value of "+value.getPrettyString()+" is not a triple"); + List elements = ((ListValue) value).getItems(); + return new Vec3d( + NumericValue.asNumber( elements.get(0)).getDouble(), + NumericValue.asNumber( elements.get(1)).getDouble(), + NumericValue.asNumber( elements.get(2)).getDouble() + ); + } + public abstract Consumer alternative(); public int key() { @@ -240,82 +265,67 @@ public class ShapeDispatcher int hash = 17; hash = 31*hash + color; hash = 31*hash + followEntity; + hash = 31*hash + Float.hashCode(lineWidth); + if (fa != 0.0) hash = 31*hash + fillColor; return hash; } // list of params that need to be there private final Set required = ImmutableSet.of("duration", "shape", "dim"); private final Map optional = ImmutableMap.of( "color", new NumericValue(-1), - "player", Value.NULL, - "follow", new NumericValue(-1) + "follow", new NumericValue(-1), + "width", new NumericValue(2.0), + "fill", new NumericValue(0xffffff00) ); protected Set requiredParams() {return required;} // list of params that can be there, with defaults protected Set optionalParams() {return optional.keySet();} + + private boolean canTake(String param) + { + return requiredParams().contains(param) || optionalParams().contains(param); + } } public static class Box extends ExpiringShape { private final Set required = ImmutableSet.of("from", "to"); - private final Map optional = ImmutableMap.of( - "width", new NumericValue(2.0), - "fill", new NumericValue(0xffffff00) - ); + private final Map optional = ImmutableMap.of(); @Override protected Set requiredParams() { return Sets.union(super.requiredParams(), required); } @Override protected Set optionalParams() { return Sets.union(super.optionalParams(), optional.keySet()); } public Box() { } - float x1, y1, z1; - float x2, y2, z2; - float lineWidth; - - protected float fr, fg, fb, fa; - protected int fillColor; + Vec3d from; + Vec3d to; @Override protected void init(Map options) { super.init(options); - List from = ((ListValue)options.get("from")).getItems(); - x1 = NumericValue.asNumber(from.get(0)).getFloat(); - y1 = NumericValue.asNumber(from.get(1)).getFloat(); - z1 = NumericValue.asNumber(from.get(2)).getFloat(); - List to = ((ListValue)options.get("to")).getItems(); - x2 = NumericValue.asNumber(to.get(0)).getFloat(); - y2 = NumericValue.asNumber(to.get(1)).getFloat(); - z2 = NumericValue.asNumber(to.get(2)).getFloat(); - lineWidth = NumericValue.asNumber(options.getOrDefault("width", optional.get("width"))).getFloat(); - fillColor = NumericValue.asNumber(options.getOrDefault("fill", optional.get("fill"))).getInt(); - this.fr = (float)(fillColor >> 24 & 0xFF) / 255.0F; - this.fg = (float)(fillColor >> 16 & 0xFF) / 255.0F; - this.fb = (float)(fillColor >> 8 & 0xFF) / 255.0F; - this.fa = (float)(fillColor & 0xFF) / 255.0F; + from = vecFromValue(options.get("from")); + to = vecFromValue(options.get("to")); } @Override public Consumer alternative() { - String particleName = String.format(Locale.ROOT , "dust %.1f %.1f %.1f 1.0", r, g, b); ParticleEffect particle = getParticleData(particleName); - double dx = x1-x2; - double dy = y1-y2; - double dz = z1-z2; - double density = Math.max(2.0, Math.sqrt(dx*dx+dy*dy+dz*dz) /50) / (a+0.1); + double density = Math.max(2.0, from.distanceTo(to) /50) / (a+0.1); return p -> { if (followEntity == -1) { - mesh(Collections.singletonList(p), particle, density, x1, y1, z1, x2, y2, z2); + particleMesh(Collections.singletonList(p), particle, density, from, to); return; } Entity e = p.getServer().getWorld(entityDimension).getEntityById(followEntity); if (e == null) return; - Vec3d rel1 = toAbsolute(e, x1, y1, z1); - Vec3d rel2 = toAbsolute(e, x2, y2, z2); - mesh(Collections.singletonList(p), particle, density, rel1.x, rel1.y, rel1.z, rel2.x, rel2.y, rel2.z); + Vec3d rel1 = toAbsolute(e, from); + Vec3d rel2 = toAbsolute(e, to); + particleMesh(Collections.singletonList(p), particle, density, rel1, rel2); }; } @@ -324,20 +334,20 @@ public class ShapeDispatcher { int hash = super.calcKey(); hash = 31*hash + 1; - hash = 31*hash + Float.hashCode(x1); - hash = 31*hash + Float.hashCode(y1); - hash = 31*hash + Float.hashCode(z1); - hash = 31*hash + Float.hashCode(x2); - hash = 31*hash + Float.hashCode(y2); - hash = 31*hash + Float.hashCode(z2); - hash = 31*hash + Float.hashCode(lineWidth); - if (fa != 0.0) hash = 31*hash + fillColor; + hash = 31*hash + from.hashCode(); + hash = 31*hash + to.hashCode(); return hash; } - public static int mesh(List playerList, ParticleEffect particle, double density, - double x1, double y1, double z1, double x2, double y2, double z2 ) + public static int particleMesh(List playerList, ParticleEffect particle, double density, + Vec3d from, Vec3d to) { + double x1 = from.x; + double y1 = from.y; + double z1 = from.z; + double x2 = to.z; + double y2 = to.y; + double z2 = to.z; return drawParticleLine(playerList, particle, new Vec3d(x1, y1, z1), new Vec3d(x1, y2, z1), density)+ drawParticleLine(playerList, particle, new Vec3d(x1, y2, z1), new Vec3d(x2, y2, z1), density)+ @@ -359,7 +369,7 @@ public class ShapeDispatcher public static class Line extends ExpiringShape { private final Set required = ImmutableSet.of("from", "to"); - private final Map optional = ImmutableMap.of("width", new NumericValue(2.0)); + private final Map optional = ImmutableMap.of(); @Override protected Set requiredParams() { return Sets.union(super.requiredParams(), required); } @Override @@ -370,23 +380,15 @@ public class ShapeDispatcher super(); } - float x1, y1, z1; - float x2, y2, z2; - float lineWidth; + Vec3d from; + Vec3d to; @Override protected void init(Map options) { super.init(options); - List from = ((ListValue)options.get("from")).getItems(); - x1 = NumericValue.asNumber(from.get(0)).getFloat(); - y1 = NumericValue.asNumber(from.get(1)).getFloat(); - z1 = NumericValue.asNumber(from.get(2)).getFloat(); - List to = ((ListValue)options.get("to")).getItems(); - x2 = NumericValue.asNumber(to.get(0)).getFloat(); - y2 = NumericValue.asNumber(to.get(1)).getFloat(); - z2 = NumericValue.asNumber(to.get(2)).getFloat(); - lineWidth = NumericValue.asNumber(options.getOrDefault("width", optional.get("width"))).getFloat(); + from = vecFromValue(options.get("from")); + to = vecFromValue(options.get("to")); } @Override @@ -394,24 +396,19 @@ public class ShapeDispatcher { String particleName = String.format(Locale.ROOT , "dust %.1f %.1f %.1f 1.0", r, g, b); ParticleEffect particle = getParticleData(particleName); - Vec3d pos1 = new Vec3d(x1, y1, z1); - Vec3d pos2 = new Vec3d(x2, y2, z2); - double dx = x1-x2; - double dy = y1-y2; - double dz = z1-z2; - double density = Math.max(2.0, Math.sqrt(dx*dx+dy*dy+dz*dz) /50) / (a+0.1); + double density = Math.max(2.0, from.distanceTo(to) /50) / (a+0.1); return p -> { if (followEntity == -1) { - drawParticleLine(Collections.singletonList(p), particle, pos1, pos2, density); + drawParticleLine(Collections.singletonList(p), particle, from, to, density); return; } Entity e = p.getServer().getWorld(entityDimension).getEntityById(followEntity); if (e == null) return; - Vec3d rel1 = toAbsolute(e, x1, y1, z1); - Vec3d rel2 = toAbsolute(e, x2, y2, z2); + Vec3d rel1 = toAbsolute(e, from); + Vec3d rel2 = toAbsolute(e, to); drawParticleLine(Collections.singletonList(p), particle, rel1, rel2, density); }; } @@ -421,13 +418,8 @@ public class ShapeDispatcher { int hash = super.calcKey(); hash = 31*hash + 2; - hash = 31*hash + Float.hashCode(x1); - hash = 31*hash + Float.hashCode(y1); - hash = 31*hash + Float.hashCode(z1); - hash = 31*hash + Float.hashCode(x2); - hash = 31*hash + Float.hashCode(y2); - hash = 31*hash + Float.hashCode(z2); - hash = 31*hash + Float.hashCode(lineWidth); + hash = 31*hash + from.hashCode(); + hash = 31*hash + to.hashCode(); return hash; } } @@ -435,11 +427,7 @@ public class ShapeDispatcher public static class Sphere extends ExpiringShape { private final Set required = ImmutableSet.of("center", "radius"); - private final Map optional = ImmutableMap.of( - "width", new NumericValue(2.0), - "level", Value.ZERO, - "fill", new NumericValue(0xffffff00) - ); + private final Map optional = ImmutableMap.of("level", Value.ZERO); @Override protected Set requiredParams() { return Sets.union(super.requiredParams(), required); } @Override @@ -450,23 +438,16 @@ public class ShapeDispatcher super(); } - float cx, cy, cz; + Vec3d center; float radius; int level; int subdivisions; - float lineWidth; - - protected float fr, fg, fb, fa; - protected int fillColor; @Override protected void init(Map options) { super.init(options); - List from = ((ListValue)options.get("center")).getItems(); - cx = NumericValue.asNumber(from.get(0)).getFloat(); - cy = NumericValue.asNumber(from.get(1)).getFloat(); - cz = NumericValue.asNumber(from.get(2)).getFloat(); + center = vecFromValue(options.get("center")); radius = NumericValue.asNumber(options.get("radius")).getFloat(); level = NumericValue.asNumber(options.getOrDefault("level", optional.get("level"))).getInt(); subdivisions = level; @@ -474,12 +455,6 @@ public class ShapeDispatcher { subdivisions = Math.max(10, (int)(10*Math.sqrt(radius))); } - lineWidth = NumericValue.asNumber(options.getOrDefault("width", optional.get("width"))).getFloat(); - fillColor = NumericValue.asNumber(options.getOrDefault("fill", optional.get("fill"))).getInt(); - this.fr = (float)(fillColor >> 24 & 0xFF) / 255.0F; - this.fg = (float)(fillColor >> 16 & 0xFF) / 255.0F; - this.fb = (float)(fillColor >> 8 & 0xFF) / 255.0F; - this.fa = (float)(fillColor & 0xFF) / 255.0F; } @Override @@ -487,34 +462,31 @@ public class ShapeDispatcher { String particleName = String.format(Locale.ROOT , "dust %.1f %.1f %.1f 1.0", r, g, b); ParticleEffect particle = getParticleData(particleName); - float pihalf = (float)(Math.PI / 180.0f); int partno = Math.min(1000,20*subdivisions); Random rand = p.world.getRandom(); ServerWorld world = p.getServerWorld(); - float ccx, ccy, ccz; + double ccx, ccy, ccz; if (followEntity == -1) { - ccx = cx; ccy = cy; ccz = cz; + ccx = center.x; ccy = center.y; ccz = center.z; } else { Entity e = p.getServer().getWorld(entityDimension).getEntityById(followEntity); if (e == null) return; - Vec3d rel1 = toAbsolute(e, cx, cy, cz); + Vec3d rel1 = toAbsolute(e, center); ccx = (float)rel1.x; ccy = (float)rel1.y; ccz = (float)rel1.z; } for (int i=0; i> decoders = new HashMap>(){{ - put("shape", StringParam::decode); - put("dim", StringParam::decode); - put("duration", ShapeDispatcher::decodeInt); - put("color", ShapeDispatcher::decodeInt); - put("follow", EntityParam::decode); - - put("from", Vec3Param::decode); - put("to", Vec3Param::decode); - put("width", ShapeDispatcher::decodeFloat); - put("fill", ShapeDispatcher::decodeInt); - put("center", Vec3Param::decode); - put("radius", ShapeDispatcher::decodeFloat); - put("level", ShapeDispatcher::decodeInt); - }}; - Map coders = new HashMap(){{ - put("player", new PlayerParam()); + public static Map of = new HashMap(){{ put("shape", new ShapeParam()); put("dim", new DimensionParam()); - put("duration", new DurationParam()); - put("color", new ColorParam()); - put("follow", new FollowParam()); + put("duration", new PositiveIntParam("duration")); + put("color", new ColorParam("color")); + put("follow", new EntityParam("follow")); + put("width", new PositiveFloatParam("width")); + put("fill", new ColorParam("fill")); - put("from", new FromParam()); - put("to", new ToParam()); - put("width", new WidthParam()); - put("fill", new FillColorParam()); - put("center", new CenterParam()); - put("radius", new RadiusParam()); - put("level", new LevelParam()); + put("from", new Vec3Param("from", false)); + put("to", new Vec3Param("to", true)); + put("center", new Vec3Param("center", false)); + put("radius", new PositiveFloatParam("radius")); + put("level", new PositiveIntParam("level")); }}; - Tag toTag(Value value); //validates value, returning null if not necessary to keep it and serialize - Value validate(Map options, CarpetContext cc, Value value); // makes sure the value is proper - boolean appliesTo(ExpiringShape shape); // check if applies to the shape - String identify(); - } - public static class PlayerParam implements Param - { - @Override // doesn't need to be converted - public Tag toTag(Value value) { return null; } - - @Override - public Value validate(Map options, CarpetContext cc, Value value) + protected String id; + protected Param(String id) { - ServerPlayerEntity player = EntityValue.getPlayerByValue(cc.s.getMinecraftServer(), value); - if (player == null) - throw new InternalExpressionException("'player' parameter needs to represent an existing player"); - return new EntityValue(player); + this.id = id; } - @Override - public boolean appliesTo(ExpiringShape shape) { return true; } - @Override - public String identify() { return "player"; } - - public static Value decode(Tag tag) { throw new RuntimeException("player tag should not be passed to the client"); } + public abstract Tag toTag(Value value); //validates value, returning null if not necessary to keep it and serialize + public abstract Value validate(Map options, CarpetContext cc, Value value); // makes sure the value is proper + public abstract Value decode(Tag tag); } - public abstract static class StringParam implements Param + + public abstract static class StringParam extends Param { + protected StringParam(String id) { super(id); } + @Override public Tag toTag(Value value) { return StringTag.of(value.getString()); } - public static Value decode(Tag tag) { return new StringValue(tag.asString()); } + public Value decode(Tag tag) { return new StringValue(tag.asString()); } } public static class DimensionParam extends StringParam { + protected DimensionParam() { super("dim"); } + @Override public Value validate(Map options, CarpetContext cc, Value value) { @@ -614,13 +555,11 @@ public class ShapeDispatcher if (!dimOp.isPresent()) throw new InternalExpressionException("Unknown dimension "+dimStr); return value; } - @Override - public boolean appliesTo(ExpiringShape shape) { return true; } - @Override - public String identify() { return "dim"; } } public static class ShapeParam extends StringParam { + protected ShapeParam() { super("shape"); } + @Override public Value validate(Map options, CarpetContext cc, Value value) { @@ -629,74 +568,65 @@ public class ShapeDispatcher throw new InternalExpressionException("Unknown shape: "+shape); return value; } - @Override - public boolean appliesTo(ExpiringShape shape) { return true; } - @Override - public String identify() { return "shape"; } } - public static abstract class NumericParam implements Param + public static abstract class NumericParam extends Param { + protected NumericParam(String id) { super(id); } + @Override public Value validate(Map options, CarpetContext cc, Value value) { if (!(value instanceof NumericValue)) - throw new InternalExpressionException("'" + identify() + "' needs to be a number"); + throw new InternalExpressionException("'" + id + "' needs to be a number"); return value; } } public static abstract class PositiveParam extends NumericParam { + protected PositiveParam(String id) { super(id); } @Override public Value validate(Map options, CarpetContext cc, Value value) { Value ret = super.validate(options, cc, value); - if (((NumericValue)ret).getDouble()<=0) throw new InternalExpressionException("'"+identify()+"' should be positive"); + if (((NumericValue)ret).getDouble()<=0) throw new InternalExpressionException("'"+id+"' should be positive"); return ret; } } - public static abstract class PositiveFloatParam extends PositiveParam + public static class PositiveFloatParam extends PositiveParam { + protected PositiveFloatParam(String id) { super(id); } + @Override + public Value decode(Tag tag) { return new NumericValue(((FloatTag)tag).getFloat()); } @Override public Tag toTag(Value value) { return FloatTag.of(NumericValue.asNumber(value).getFloat()); } } - public static abstract class PositiveIntParam extends PositiveParam + public static class PositiveIntParam extends PositiveParam { + protected PositiveIntParam(String id) { super(id); } + @Override + public Value decode(Tag tag) { return new NumericValue(((IntTag)tag).getInt()); } @Override public Tag toTag(Value value) { return IntTag.of(NumericValue.asNumber(value).getInt()); } } - public static Value decodeInt(Tag tag) { return new NumericValue(((IntTag)tag).getInt()); } - public static Value decodeFloat(Tag tag) { return new NumericValue(((FloatTag)tag).getFloat()); } - public static class DurationParam extends PositiveIntParam - { - @Override - public boolean appliesTo(ExpiringShape shape) { return true; } - @Override - public String identify() { return "duration"; } - } - public static class WidthParam extends PositiveFloatParam - { - @Override - public boolean appliesTo(ExpiringShape shape) { return shape instanceof Box || shape instanceof Line || shape instanceof Sphere; } - @Override - public String identify() { return "width"; } - } - public static abstract class Vec3Param implements Param + public static class Vec3Param extends Param { - - public abstract boolean roundsUpForBlocks(); - public abstract String identify(); - + private boolean roundsUpForBlocks; + protected Vec3Param(String id, boolean doesRoundUpForBlocks) + { + super(id); + roundsUpForBlocks = doesRoundUpForBlocks; + } @Override public Value validate(Map options, CarpetContext cc, Value value) { if (value instanceof BlockValue) { if (options.containsKey("follow")) - throw new InternalExpressionException(identify()+" parameter cannot use blocks as positions for relative positioning due to 'follow' attribute being present"); + throw new InternalExpressionException(id+" parameter cannot use blocks as positions for relative positioning due to 'follow' attribute being present"); BlockPos pos = ((BlockValue) value).getPos(); - int offset = roundsUpForBlocks()?1:0; + int offset = roundsUpForBlocks?1:0; return ListValue.of( new NumericValue(pos.getX()+offset), new NumericValue(pos.getY()+offset), @@ -706,18 +636,18 @@ public class ShapeDispatcher if (value instanceof ListValue) { List values = ((ListValue) value).getItems(); - if (values.size()!=3) throw new InternalExpressionException("'"+identify()+"' requires 3 numerical values"); + if (values.size()!=3) throw new InternalExpressionException("'"+id+"' requires 3 numerical values"); for (Value component : values) { if (!(component instanceof NumericValue)) - throw new InternalExpressionException("'"+identify()+"' requires 3 numerical values"); + throw new InternalExpressionException("'"+id+"' requires 3 numerical values"); } return value; } if (value instanceof EntityValue) { if (options.containsKey("follow")) - throw new InternalExpressionException(identify()+" parameter cannot use entity as positions for relative positioning due to 'follow' attribute being present"); + throw new InternalExpressionException(id+" parameter cannot use entity as positions for relative positioning due to 'follow' attribute being present"); Entity e = ((EntityValue) value).getEntity(); return ListValue.of( new NumericValue(e.getX()), @@ -726,16 +656,16 @@ public class ShapeDispatcher ); } CarpetSettings.LOG.error("Value: "+value.getString()); - throw new InternalExpressionException("'"+identify()+"' requires a triple, block or entity to indicate position"); + throw new InternalExpressionException("'"+id+"' requires a triple, block or entity to indicate position"); } - public static Value decode(Tag tag) + public Value decode(Tag tag) { CompoundTag ctag = (CompoundTag)tag; return ListValue.of( - new NumericValue(ctag.getFloat("x")), - new NumericValue(ctag.getFloat("y")), - new NumericValue(ctag.getFloat("z")) + new NumericValue(ctag.getDouble("x")), + new NumericValue(ctag.getDouble("y")), + new NumericValue(ctag.getDouble("z")) ); } @Override @@ -743,75 +673,28 @@ public class ShapeDispatcher { List lv = ((ListValue)value).getItems(); CompoundTag tag = new CompoundTag(); - tag.putFloat("x", NumericValue.asNumber(lv.get(0)).getFloat()); - tag.putFloat("y", NumericValue.asNumber(lv.get(1)).getFloat()); - tag.putFloat("z", NumericValue.asNumber(lv.get(2)).getFloat()); + tag.putDouble("x", NumericValue.asNumber(lv.get(0)).getDouble()); + tag.putDouble("y", NumericValue.asNumber(lv.get(1)).getDouble()); + tag.putDouble("z", NumericValue.asNumber(lv.get(2)).getDouble()); return tag; } } public static class ColorParam extends NumericParam { + protected ColorParam(String id) + { + super(id); + } + + public Value decode(Tag tag) { return new NumericValue(((IntTag)tag).getInt()); } @Override public Tag toTag(Value value) { return IntTag.of(NumericValue.asNumber(value).getInt()); } - @Override - public boolean appliesTo(ExpiringShape shape) { return true; } - @Override - public String identify() { return "color"; } } - public static class FillColorParam extends ColorParam + public static class EntityParam extends Param { - @Override - public boolean appliesTo(ExpiringShape shape) { return shape instanceof Box || shape instanceof Sphere; } - @Override - public String identify() { return "fill"; } - } - public static class FromParam extends Vec3Param - { - @Override - public boolean appliesTo(ExpiringShape shape) { return shape instanceof Line || shape instanceof Box; } - @Override - public boolean roundsUpForBlocks() { return false; } - @Override - public String identify() { return "from"; } - } - - public static class ToParam extends Vec3Param - { - @Override - public boolean appliesTo(ExpiringShape shape) { return (shape instanceof Line) || (shape instanceof Box); } - @Override - public boolean roundsUpForBlocks() { return true; } - @Override - public String identify() { return "to"; } - } - - public static class CenterParam extends Vec3Param - { - @Override - public boolean appliesTo(ExpiringShape shape) { return (shape instanceof Sphere); } - @Override - public boolean roundsUpForBlocks() { return false; } - @Override - public String identify() { return "center"; } - } - public static class RadiusParam extends PositiveFloatParam - { - @Override - public boolean appliesTo(ExpiringShape shape) { return shape instanceof Sphere; } - @Override - public String identify() { return "radius"; } - } - public static class LevelParam extends PositiveIntParam - { - @Override - public boolean appliesTo(ExpiringShape shape) { return shape instanceof Sphere; } - @Override - public String identify() { return "level"; } - } - public abstract static class EntityParam implements Param - { + protected EntityParam(String id) { super(id); } @Override public Tag toTag(Value value) @@ -825,22 +708,12 @@ public class ShapeDispatcher if (value instanceof EntityValue) return new NumericValue(((EntityValue) value).getEntity().getEntityId()); ServerPlayerEntity player = EntityValue.getPlayerByValue(cc.s.getMinecraftServer(), value); if (player == null) - throw new InternalExpressionException(identify()+" parameter needs to represent an entity or player"); + throw new InternalExpressionException(id+" parameter needs to represent an entity or player"); return new NumericValue(player.getEntityId()); } - @Override - public boolean appliesTo(ExpiringShape shape) { return true; } - - public static Value decode(Tag tag) { return new NumericValue(((IntTag)tag).getInt()); } + public Value decode(Tag tag) { return new NumericValue(((IntTag)tag).getInt()); } } - public static class FollowParam extends EntityParam - { - @Override - public String identify() { return "follow"; } - } - - private static boolean isStraight(Vec3d from, Vec3d to, double density) { @@ -893,7 +766,7 @@ public class ShapeDispatcher if (isStraight(from, to, density)) return drawOptimizedParticleLine(players, particle, from, to, density); double lineLengthSq = from.squaredDistanceTo(to); if (lineLengthSq == 0) return 0; - Vec3d incvec = to.subtract(from).multiply(2*density/sqrt(lineLengthSq)); + Vec3d incvec = to.subtract(from).multiply(2*density/MathHelper.sqrt(lineLengthSq)); int pcount = 0; for (Vec3d delta = new Vec3d(0.0,0.0,0.0); delta.lengthSquared() { - if ( s.shouldRender(dimensionType)) s.render2pass(tessellator, bufferBuilder, (float) cameraX, (float) cameraY, (float) cameraZ); + if ( s.shouldRender(dimensionType)) + s.renderFaces(tessellator, bufferBuilder, cameraX, cameraY, cameraZ); } ); //lines shapes.get(dimensionType).values().forEach( s -> { - if ( s.shouldRender(dimensionType)) s.render(tessellator, bufferBuilder, (float) cameraX, (float) cameraY, (float) cameraZ); + if ( s.shouldRender(dimensionType)) + s.renderLines(tessellator, bufferBuilder, cameraX, cameraY, cameraZ); } ); } @@ -143,14 +145,14 @@ public class ShapesRenderer protected T shape; protected MinecraftClient client; long expiryTick; - float renderEpsilon = 0; - public abstract void render(Tessellator tessellator, BufferBuilder builder, float cx, float cy, float cz ); - public void render2pass(Tessellator tessellator, BufferBuilder builder, float cx, float cy, float cz ) {}; + double renderEpsilon = 0; + public abstract void renderLines(Tessellator tessellator, BufferBuilder builder, double cx, double cy, double cz ); + public void renderFaces(Tessellator tessellator, BufferBuilder builder, double cx, double cy, double cz ) {} protected RenderedShape(MinecraftClient client, T shape) { this.shape = shape; expiryTick = client.world.getTime()+shape.getExpiry(); - renderEpsilon = (2+((float)shape.key())/Integer.MAX_VALUE)/1000; + renderEpsilon = (2+((double)shape.key())/Integer.MAX_VALUE)/1000; this.client = client; } @@ -170,11 +172,11 @@ public class ShapesRenderer if (client.world.getEntityById(shape.followEntity) == null) return false; return true; } - protected Vec3d relativiseRender(float x, float y, float z) + protected Vec3d relativiseRender(Vec3d vec) { - if (shape.followEntity <= 0) return new Vec3d(x,y,z); + if (shape.followEntity <= 0) return vec; Entity e = client.world.getEntityById(shape.followEntity); - return shape.toAbsolute(e, x, y, z); + return shape.toAbsolute(e, vec); } } @@ -187,31 +189,30 @@ public class ShapesRenderer } @Override - public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) + public void renderLines(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz) { if (shape.a == 0.0) return; - Vec3d v1 = relativiseRender(shape.x1, shape.y1, shape.z1); - Vec3d v2 = relativiseRender(shape.x2, shape.y2, shape.z2); + Vec3d v1 = relativiseRender(shape.from); + Vec3d v2 = relativiseRender(shape.to); RenderSystem.lineWidth(shape.lineWidth); drawBoxWireGLLines(tessellator, bufferBuilder, - (float)v1.x-cx-renderEpsilon, (float)v1.y-cy-renderEpsilon, (float)v1.z-cz-renderEpsilon, - (float)v2.x-cx+renderEpsilon, (float)v2.y-cy+renderEpsilon, (float)v2.z-cz+renderEpsilon, + (float)(v1.x-cx-renderEpsilon), (float)(v1.y-cy-renderEpsilon), (float)(v1.z-cz-renderEpsilon), + (float)(v2.x-cx+renderEpsilon), (float)(v2.y-cy+renderEpsilon), (float)(v2.z-cz+renderEpsilon), shape.r, shape.g, shape.b, shape.a, shape.r, shape.g, shape.b ); } @Override - public void render2pass(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) + public void renderFaces(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz) { if (shape.fa == 0.0) return; - Vec3d v1 = relativiseRender(shape.x1, shape.y1, shape.z1); - Vec3d v2 = relativiseRender(shape.x2, shape.y2, shape.z2); + Vec3d v1 = relativiseRender(shape.from); + Vec3d v2 = relativiseRender(shape.to); RenderSystem.lineWidth(1.0F); drawBoxFaces(tessellator, bufferBuilder, - (float)v1.x-cx-renderEpsilon, (float)v1.y-cy-renderEpsilon, (float)v1.z-cz-renderEpsilon, - (float)v2.x-cx+renderEpsilon, (float)v2.y-cy+renderEpsilon, (float)v2.z-cz+renderEpsilon, + (float)(v1.x-cx-renderEpsilon), (float)(v1.y-cy-renderEpsilon), (float)(v1.z-cz-renderEpsilon), + (float)(v2.x-cx+renderEpsilon), (float)(v2.y-cy+renderEpsilon), (float)(v2.z-cz+renderEpsilon), shape.fr, shape.fg, shape.fb, shape.fa ); - } } @@ -223,14 +224,14 @@ public class ShapesRenderer super(client, (ShapeDispatcher.Line)shape); } @Override - public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) + public void renderLines(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz) { - Vec3d v1 = relativiseRender(shape.x1, shape.y1, shape.z1); - Vec3d v2 = relativiseRender(shape.x2, shape.y2, shape.z2); + Vec3d v1 = relativiseRender(shape.from); + Vec3d v2 = relativiseRender(shape.to); RenderSystem.lineWidth(shape.lineWidth); drawLine(tessellator, bufferBuilder, - (float)v1.x-cx-renderEpsilon, (float)v1.y-cy-renderEpsilon, (float)v1.z-cz-renderEpsilon, - (float)v2.x-cx+renderEpsilon, (float)v2.y-cy+renderEpsilon, (float)v2.z-cz+renderEpsilon, + (float)(v1.x-cx-renderEpsilon), (float)(v1.y-cy-renderEpsilon), (float)(v1.z-cz-renderEpsilon), + (float)(v2.x-cx+renderEpsilon), (float)(v2.y-cy+renderEpsilon), (float)(v2.z-cz+renderEpsilon), shape.r, shape.g, shape.b, shape.a ); } @@ -243,25 +244,24 @@ public class ShapesRenderer super(client, (ShapeDispatcher.Sphere)shape); } @Override - public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) + public void renderLines(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz) { if (shape.a == 0.0) return; - Vec3d vc = relativiseRender(shape.cx, shape.cy, shape.cz); - + Vec3d vc = relativiseRender(shape.center); RenderSystem.lineWidth(shape.lineWidth); drawSphereWireframe(tessellator, bufferBuilder, - (float)vc.x-cx-renderEpsilon, (float)vc.y-cy-renderEpsilon, (float)vc.z-cz-renderEpsilon, + (float)(vc.x-cx-renderEpsilon), (float)(vc.y-cy-renderEpsilon), (float)(vc.z-cz-renderEpsilon), shape.radius, shape.subdivisions, shape.r, shape.g, shape.b, shape.a); } @Override - public void render2pass(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) + public void renderFaces(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz) { if (shape.fa == 0.0) return; - Vec3d vc = relativiseRender(shape.cx, shape.cy, shape.cz); + Vec3d vc = relativiseRender(shape.center); RenderSystem.lineWidth(1.0f); drawSphereFaces(tessellator, bufferBuilder, - (float)vc.x-cx-renderEpsilon, (float)vc.y-cy-renderEpsilon, (float)vc.z-cz-renderEpsilon, + (float)(vc.x-cx-renderEpsilon), (float)(vc.y-cy-renderEpsilon), (float)(vc.z-cz-renderEpsilon), shape.radius, shape.subdivisions, shape.fr, shape.fg, shape.fb, shape.fa); } From 4dc8982009300be3333e6b97a8da50b34c4cfc74 Mon Sep 17 00:00:00 2001 From: gnembon Date: Fri, 5 Jun 2020 16:54:38 -0300 Subject: [PATCH 176/198] refactor --- gradle.properties | 2 +- src/main/java/carpet/CarpetSettings.java | 2 +- src/main/resources/fabric.mod.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index bf908cf3..88e44481 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ org.gradle.jvmargs=-Xmx1G loader_version=0.8.3+build.196 # Mod Properties - mod_version = 1.3.26+v200604 + mod_version = 1.3.27+v200605 maven_group = carpet archives_base_name = fabric-carpet diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index 6cba4ff3..d36d621b 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -34,7 +34,7 @@ import static carpet.settings.RuleCategory.CLIENT; @SuppressWarnings("CanBeFinal") public class CarpetSettings { - public static final String carpetVersion = "1.3.26+v200604"; + public static final String carpetVersion = "1.3.27+v200605"; public static final Logger LOG = LogManager.getLogger(); public static boolean skipGenerationChecks = false; public static boolean impendingFillSkipUpdates = false; diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index b9beb34b..cf4b596d 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,7 +1,7 @@ { "schemaVersion": 1, "id": "carpet", - "version": "1.3.26", + "version": "1.3.27", "name": "Carpet Mod in Fabric", "description": "Carpet made out of fabric", From 021e8a2bb7d4050371bda87eaa76d5a1154fa52a Mon Sep 17 00:00:00 2001 From: gnembon Date: Fri, 5 Jun 2020 23:47:17 -0300 Subject: [PATCH 177/198] mappings --- gradle.properties | 4 ++-- src/main/java/carpet/utils/BlockInfo.java | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/gradle.properties b/gradle.properties index 88e44481..06c8de17 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,8 +5,8 @@ org.gradle.jvmargs=-Xmx1G # check these on https://fabricmc.net/use # or better: https://modmuss50.me/fabric.html minecraft_version=1.15.2 - yarn_mappings=1.15.2+build.15 - loader_version=0.8.3+build.196 + yarn_mappings=1.15.2+build.17 + loader_version=0.8.7+build.201 # Mod Properties mod_version = 1.3.27+v200605 diff --git a/src/main/java/carpet/utils/BlockInfo.java b/src/main/java/carpet/utils/BlockInfo.java index f343d1b4..470ba512 100644 --- a/src/main/java/carpet/utils/BlockInfo.java +++ b/src/main/java/carpet/utils/BlockInfo.java @@ -110,20 +110,20 @@ public class BlockInfo put(Material.PLANT , "plant" ); put(Material.UNDERWATER_PLANT, "water_plant" ); put(Material.REPLACEABLE_PLANT, "vegetation" ); - put(Material.SEAGRASS , "sea_grass" ); + put(Material.REPLACEABLE_UNDERWATER_PLANT , "sea_grass" ); put(Material.WATER , "water" ); put(Material.BUBBLE_COLUMN , "bubble_column"); put(Material.LAVA , "lava" ); - put(Material.SNOW , "snow_layer" ); + put(Material.SNOW_LAYER , "snow_layer" ); put(Material.FIRE , "fire" ); - put(Material.PART , "decoration" ); + put(Material.SUPPORTED , "decoration" ); put(Material.COBWEB , "cobweb" ); put(Material.REDSTONE_LAMP , "redstone_lamp"); - put(Material.CLAY , "clay" ); - put(Material.EARTH , "dirt" ); - put(Material.ORGANIC , "grass" ); - put(Material.PACKED_ICE , "packed_ice" ); - put(Material.SAND , "sand" ); + put(Material.ORGANIC_PRODUCT , "clay" ); + put(Material.SOIL , "dirt" ); + put(Material.SOLID_ORGANIC , "grass" ); + put(Material.DENSE_ICE , "packed_ice" ); + put(Material.AGGREGATE , "sand" ); put(Material.SPONGE , "sponge" ); put(Material.SHULKER_BOX , "shulker" ); put(Material.WOOD , "wood" ); @@ -138,11 +138,11 @@ public class BlockInfo put(Material.STONE , "stone" ); put(Material.METAL , "metal" ); put(Material.SNOW_BLOCK , "snow" ); - put(Material.ANVIL , "anvil" ); + put(Material.REPAIR_STATION , "anvil" ); put(Material.BARRIER , "barrier" ); put(Material.PISTON , "piston" ); put(Material.UNUSED_PLANT , "coral" ); - put(Material.PUMPKIN , "gourd" ); + put(Material.GOURD , "gourd" ); put(Material.EGG , "dragon_egg" ); put(Material.CAKE , "cake" ); }}; From 7dc1fa5f415fc31b880cdec0cfd9118a2dd2e5a8 Mon Sep 17 00:00:00 2001 From: gnembon Date: Sat, 6 Jun 2020 16:25:35 -0300 Subject: [PATCH 178/198] grindstones are movable in bedrock --- .../carpet/mixins/PistonBlock_movableTEMixin.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/carpet/mixins/PistonBlock_movableTEMixin.java b/src/main/java/carpet/mixins/PistonBlock_movableTEMixin.java index a17f5dff..0df4236a 100644 --- a/src/main/java/carpet/mixins/PistonBlock_movableTEMixin.java +++ b/src/main/java/carpet/mixins/PistonBlock_movableTEMixin.java @@ -5,6 +5,7 @@ import carpet.fakes.PistonBlockEntityInterface; import com.google.common.collect.Lists; import net.minecraft.block.*; import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.piston.PistonBehavior; import net.minecraft.block.piston.PistonHandler; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; @@ -62,6 +63,17 @@ public abstract class PistonBlock_movableTEMixin extends FacingBlock return !(CarpetSettings.movableBlockEntities && isPushableBlockEntity(block)); } } + + @Redirect(method = "isMovable", at = @At( + value = "INVOKE", + target = "Lnet/minecraft/block/BlockState;getPistonBehavior()Lnet/minecraft/block/piston/PistonBehavior;" + )) + private static PistonBehavior moveGrindstones(BlockState blockState) + { + if (CarpetSettings.movableBlockEntities && blockState.getBlock() == Blocks.GRINDSTONE) return PistonBehavior.NORMAL; + return blockState.getPistonBehavior(); + } + @Inject(method = "move", at = @At(value = "INVOKE", shift = At.Shift.BEFORE, target = "Ljava/util/List;size()I", ordinal = 4),locals = LocalCapture.CAPTURE_FAILHARD) private void onMove(World world_1, BlockPos blockPos_1, Direction direction_1, boolean boolean_1, From 7bbae714ea3fbd0accb0c90a47126452e93789e1 Mon Sep 17 00:00:00 2001 From: X-Green <35984104+X-Green@users.noreply.github.com> Date: Sun, 7 Jun 2020 03:56:43 +0800 Subject: [PATCH 179/198] Adding Explosion Logger (#299) * Added Explosion Logger * Added Explosion Logger's Hook On Explosion.java * Update #2 * Add files via upload --- .../carpet/helpers/OptimizedExplosion.java | 12 +- .../java/carpet/logging/LoggerRegistry.java | 2 + .../logHelpers/ExplosionLogHelper.java | 156 ++++++++++++++++++ .../java/carpet/mixins/ExplosionMixin.java | 35 +++- 4 files changed, 203 insertions(+), 2 deletions(-) create mode 100644 src/main/java/carpet/logging/logHelpers/ExplosionLogHelper.java diff --git a/src/main/java/carpet/helpers/OptimizedExplosion.java b/src/main/java/carpet/helpers/OptimizedExplosion.java index a3d0e8ec..df6a463e 100644 --- a/src/main/java/carpet/helpers/OptimizedExplosion.java +++ b/src/main/java/carpet/helpers/OptimizedExplosion.java @@ -7,8 +7,10 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import carpet.logging.logHelpers.ExplosionLogHelper; import carpet.mixins.ExplosionAccessor; import carpet.CarpetSettings; +import carpet.mixins.ExplosionMixin; import carpet.utils.Messenger; import com.google.common.collect.Lists; import it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap; @@ -51,6 +53,7 @@ public class OptimizedExplosion private static List entitylist; private static Vec3d vec3dmem; private static long tickmem; + private static Vec3d vec3dZero = new Vec3d(0, 0, 0); // For disabling the explosion particles and sound public static int explosionSound = 0; @@ -66,7 +69,7 @@ public class OptimizedExplosion private static ArrayList chances = new ArrayList<>(); private static BlockPos blastChanceLocation; - public static void doExplosionA(Explosion e) { + public static void doExplosionA(Explosion e, ExplosionLogHelper eLogger) { ExplosionAccessor eAccess = (ExplosionAccessor) e; blastCalc(e); @@ -120,6 +123,9 @@ public class OptimizedExplosion entity.getX() == eAccess.getEntity().getX() && entity.getY() == eAccess.getEntity().getY() && entity.getZ() == eAccess.getEntity().getZ()) { + if (eLogger != null) { + eLogger.onEntityImpacted(entity, new Vec3d(0,-0.9923437498509884d, 0)); + } continue; } @@ -158,6 +164,10 @@ public class OptimizedExplosion d11 = ProtectionEnchantment.transformExplosionKnockback((LivingEntity) entity, d10); } + if (eLogger != null) { + eLogger.onEntityImpacted(entity, new Vec3d(d5 * d11, d7 * d11, d9 * d11)); + } + entity.setVelocity(entity.getVelocity().add(d5 * d11, d7 * d11, d9 * d11)); if (entity instanceof PlayerEntity) { diff --git a/src/main/java/carpet/logging/LoggerRegistry.java b/src/main/java/carpet/logging/LoggerRegistry.java index 6034a702..9d397c59 100644 --- a/src/main/java/carpet/logging/LoggerRegistry.java +++ b/src/main/java/carpet/logging/LoggerRegistry.java @@ -30,6 +30,7 @@ public class LoggerRegistry public static boolean __packets; public static boolean __weather; public static boolean __pathfinding; + public static boolean __explosions; public static void initLoggers() { @@ -52,6 +53,7 @@ public class LoggerRegistry registerLogger("packets", HUDLogger.stardardHUDLogger("packets", null, null)); registerLogger("counter",HUDLogger.stardardHUDLogger("counter","white", Arrays.stream(DyeColor.values()).map(Object::toString).toArray(String[]::new))); registerLogger("mobcaps", HUDLogger.stardardHUDLogger("mobcaps", "dynamic",new String[]{"dynamic", "overworld", "nether","end"})); + registerLogger("explosions", HUDLogger.stardardLogger("explosions", "brief",new String[]{"brief", "full"})); } diff --git a/src/main/java/carpet/logging/logHelpers/ExplosionLogHelper.java b/src/main/java/carpet/logging/logHelpers/ExplosionLogHelper.java new file mode 100644 index 00000000..c61b8771 --- /dev/null +++ b/src/main/java/carpet/logging/logHelpers/ExplosionLogHelper.java @@ -0,0 +1,156 @@ +package carpet.logging.logHelpers; + +import carpet.logging.LoggerRegistry; +import carpet.utils.Messenger; +import com.google.common.collect.Lists; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.text.BaseText; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.explosion.Explosion; + +import java.util.List; + +public class ExplosionLogHelper +{ + private final boolean createFire; + private final Explosion.DestructionType blockDestructionType; + public final double x; + public final double y; + public final double z; + public final Entity entity; + private final float power; + private boolean affectBlocks = false; + private List entityChangedStatusWithCount = Lists.newArrayList(); + + private static long lastGametime = 0; + private static int explosionCountInCurretGT = 0; + + public ExplosionLogHelper(Entity entity, double x, double y, double z, float power, boolean createFire, Explosion.DestructionType blockDestructionType) { + this.entity = entity; + this.power = power; + this.x = x; + this.y = y; + this.z = z; + this.createFire = createFire; + this.blockDestructionType = blockDestructionType; + } + + public void setAffectBlocks(boolean b) + { + affectBlocks = b; + } + + public void onExplosionDone(long gametime) + { + BaseText timeDisplay; + if (!(lastGametime == gametime)){ + explosionCountInCurretGT = 0; + lastGametime = gametime; + timeDisplay = Messenger.c("wb " + ">>>>>> CURRENT GAME TIME : ", "d " + gametime, "wb >>>>>>\n"); + } + else + { + timeDisplay = Messenger.s(""); + } + explosionCountInCurretGT++; + LoggerRegistry.getLogger("explosions").log( (option) -> { + switch (option) + { + case "brief": + return new BaseText[]{Messenger.c( + timeDisplay, "gb EXPLOSION", "d #" + explosionCountInCurretGT,"gb -> ", + "w P: ", "d ",Messenger.dblt("l",x ,y ,z), + "w affectBlocks: ", "m " + this.affectBlocks + )}; + case "full": + return new BaseText[]{Messenger.c( + timeDisplay, "gb EXPLOSION", "d #" + explosionCountInCurretGT,"gb -> ", + "w P: ", "d ",Messenger.dblt("l",x ,y ,z), + "w createFire: ", "m " + this.createFire, + "w power: ", "c " + this.power, + "w destructionType: ", "c " + this.blockDestructionType.name(), + "w affectBlocks: ", "m " + this.affectBlocks, + "b \n", ListToText() + )}; + } + return null; + }); + } + + public void onEntityImpacted(Entity entity, Vec3d deltaVelocity) + { + for (EntityChangedStatusWithCount e : entityChangedStatusWithCount) + { + if (e.checkIfEquals(entity, deltaVelocity)) + { + e.count++; + return; + } + } + entityChangedStatusWithCount.add(new EntityChangedStatusWithCount(entity.getPos(), entity.getType(), deltaVelocity)); + } + + public BaseText ListToText() + { + BaseText s = Messenger.s("Entities Impacted:\n"); + for (EntityChangedStatusWithCount entityChanges : entityChangedStatusWithCount) + { + s.append(entityChanges.asText()); + s.append("\n"); + } + return s; + } + + + public static class EntityChangedStatusWithCount + { + public final Vec3d entityPos; + public final EntityType entityType; + public final Vec3d deltaSpeed; + public int count; + public EntityChangedStatusWithCount(Vec3d entityPos, EntityType entityType, Vec3d deltaSpeed) + { + this.entityPos = entityPos; + this.entityType = entityType; + this.deltaSpeed = deltaSpeed; + this.count = 1; + } + + public boolean equals(EntityChangedStatusWithCount e) + { + return ( + e.entityType == this.entityType && + e.deltaSpeed.equals(this.deltaSpeed) && + e.entityPos.equals(this.entityPos) + ); + } + + public boolean checkIfEquals(Entity e, Vec3d deltaSpeed) + { + return ( + e.getType() == this.entityType && + deltaSpeed.equals(this.deltaSpeed) && + e.getPos().equals(this.entityPos) + ); + } + + public String toString() + { + return String.format("{EntityType: %s, EntityPos: %s ,DeltaSpeed: %s}", entityType.getName().asString(), entityPos.toString(), deltaSpeed.toString()); + } + + public BaseText asText() + { + return Messenger.c( + "m Entity(count="+ this.count +") of", + "l " + Registry.ENTITY_TYPE.getId(entityType), "g {", + "w P: ", "y ", Messenger.dblt("t", entityPos.x, entityPos.y, entityPos.z), + "w dV: ", "gbi " + (deltaSpeed.equals(new Vec3d(0,-0.9923437498509884d, 0)) ? "":""),"y ", Messenger.dblt("d", deltaSpeed.x, deltaSpeed.y, deltaSpeed.z), + "g }" + ); + } + + } +} diff --git a/src/main/java/carpet/mixins/ExplosionMixin.java b/src/main/java/carpet/mixins/ExplosionMixin.java index 8e74cda1..b2358119 100644 --- a/src/main/java/carpet/mixins/ExplosionMixin.java +++ b/src/main/java/carpet/mixins/ExplosionMixin.java @@ -2,9 +2,13 @@ package carpet.mixins; import carpet.helpers.OptimizedExplosion; import carpet.CarpetSettings; +import carpet.logging.LoggerRegistry; +import carpet.logging.logHelpers.ExplosionLogHelper; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; +import net.minecraft.entity.Entity; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; import net.minecraft.world.explosion.Explosion; import org.spongepowered.asm.mixin.Final; @@ -24,13 +28,17 @@ public abstract class ExplosionMixin @Final private List affectedBlocks; + @Shadow @Final private World world; + + private ExplosionLogHelper eLogger; + @Inject(method = "collectBlocksAndDamageEntities", at = @At("HEAD"), cancellable = true) private void onExplosionA(CallbackInfo ci) { if (CarpetSettings.optimizedTNT) { - OptimizedExplosion.doExplosionA((Explosion) (Object) this); + OptimizedExplosion.doExplosionA((Explosion) (Object) this, eLogger); ci.cancel(); } } @@ -39,6 +47,11 @@ public abstract class ExplosionMixin cancellable = true) private void onExplosionB(boolean spawnParticles, CallbackInfo ci) { + if (eLogger != null) + { + eLogger.setAffectBlocks( ! affectedBlocks.isEmpty()); + eLogger.onExplosionDone(this.world.getTime()); + } if (CarpetSettings.explosionNoBlockDamage) { affectedBlocks.clear(); @@ -58,4 +71,24 @@ public abstract class ExplosionMixin if (CarpetSettings.explosionNoBlockDamage) return Blocks.BEDROCK.getDefaultState(); return world.getBlockState(pos); } + + @Inject(method = "(Lnet/minecraft/world/World;Lnet/minecraft/entity/Entity;DDDFZLnet/minecraft/world/explosion/Explosion$DestructionType;)V", + at = @At(value = "RETURN")) + private void onExplosionCreated(World world, Entity entity, double x, double y, double z, float power, boolean createFire, Explosion.DestructionType blockDestructionType, CallbackInfo ci) + { + if (LoggerRegistry.__explosions && ! world.isClient) + { + eLogger = new ExplosionLogHelper(entity, x, y, z, power, createFire, blockDestructionType); + } + } + + @Redirect(method = "collectBlocksAndDamageEntities", + at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;setVelocity(Lnet/minecraft/util/math/Vec3d;)V")) + private void setVelocityAndUpdateLogging(Entity entity, Vec3d velocity) + { + if (eLogger != null) { + eLogger.onEntityImpacted(entity, velocity.subtract(entity.getVelocity())); + } + entity.setVelocity(velocity); + } } From b3484fd0125da9fb070cc5f62359434f2944902f Mon Sep 17 00:00:00 2001 From: gnembon Date: Sat, 6 Jun 2020 20:39:25 -0300 Subject: [PATCH 180/198] fixed missing client side server references. fixes #311 --- src/main/java/carpet/CarpetServer.java | 2 +- src/main/java/carpet/CarpetSettings.java | 5 ++-- .../java/carpet/commands/SpawnCommand.java | 3 ++- .../java/carpet/commands/TickCommand.java | 3 ++- src/main/java/carpet/helpers/TickSpeed.java | 9 ++++---- .../PlayerEntity_antiCheatDisabled.java | 2 +- .../java/carpet/script/CarpetEventServer.java | 5 +++- .../java/carpet/script/CarpetScriptHost.java | 8 +++---- .../carpet/script/CarpetScriptServer.java | 23 +++++++++++-------- .../java/carpet/settings/SettingsManager.java | 3 +-- 10 files changed, 36 insertions(+), 27 deletions(-) diff --git a/src/main/java/carpet/CarpetServer.java b/src/main/java/carpet/CarpetServer.java index 7cc7f021..85b6d31e 100644 --- a/src/main/java/carpet/CarpetServer.java +++ b/src/main/java/carpet/CarpetServer.java @@ -57,7 +57,7 @@ public class CarpetServer // static for now - easier to handle all around the co if (sm != null) sm.attachServer(server); e.onServerLoaded(server); }); - scriptServer = new CarpetScriptServer(); + scriptServer = new CarpetScriptServer(server); scriptServer.loadAllWorldScripts(); MobAI.resetTrackers(); LoggerRegistry.initLoggers(); diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index d36d621b..ee3d0e83 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -501,8 +501,8 @@ public class CarpetSettings if (server.isDedicated()) { int vd = (newValue >= 2)?newValue:((DedicatedServer) server).getProperties().viewDistance; - if (vd != CarpetServer.minecraft_server.getPlayerManager().getViewDistance()) - CarpetServer.minecraft_server.getPlayerManager().setViewDistance(vd); + if (vd != server.getPlayerManager().getViewDistance()) + server.getPlayerManager().setViewDistance(vd); return newValue; } else @@ -549,6 +549,7 @@ public class CarpetSettings //must been some startup thing return newValue; } + if (CarpetServer.minecraft_server == null) return newValue; ServerWorld currentOverworld = CarpetServer.minecraft_server.getWorld(DimensionType.OVERWORLD); if (currentOverworld != null) { diff --git a/src/main/java/carpet/commands/SpawnCommand.java b/src/main/java/carpet/commands/SpawnCommand.java index f50e858b..e5189f11 100644 --- a/src/main/java/carpet/commands/SpawnCommand.java +++ b/src/main/java/carpet/commands/SpawnCommand.java @@ -16,6 +16,7 @@ import net.minecraft.command.arguments.DimensionArgumentType; import net.minecraft.entity.EntityCategory; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.DyeColor; import net.minecraft.util.math.BlockPos; import net.minecraft.world.dimension.DimensionType; @@ -195,7 +196,7 @@ public class SpawnCommand TickSpeed.tickrate_advance(null, 0, null, null); // tick warp given player ServerCommandSource csource = null; - PlayerEntity player = null; + ServerPlayerEntity player = null; try { player = source.getPlayer(); diff --git a/src/main/java/carpet/commands/TickCommand.java b/src/main/java/carpet/commands/TickCommand.java index 0b559f38..e705c8b9 100644 --- a/src/main/java/carpet/commands/TickCommand.java +++ b/src/main/java/carpet/commands/TickCommand.java @@ -9,6 +9,7 @@ import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.BaseText; import net.minecraft.server.command.ServerCommandSource; @@ -80,7 +81,7 @@ public class TickCommand private static int setWarp(ServerCommandSource source, int advance, String tail_command) { - PlayerEntity player = null; + ServerPlayerEntity player = null; try { player = source.getPlayer(); diff --git a/src/main/java/carpet/helpers/TickSpeed.java b/src/main/java/carpet/helpers/TickSpeed.java index dd642112..575867eb 100644 --- a/src/main/java/carpet/helpers/TickSpeed.java +++ b/src/main/java/carpet/helpers/TickSpeed.java @@ -7,10 +7,10 @@ import java.util.function.BiConsumer; import carpet.CarpetServer; import carpet.network.ServerNetworkHandler; import carpet.utils.Messenger; -import net.minecraft.entity.player.PlayerEntity; import net.minecraft.server.MinecraftServer; import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.BaseText; public class TickSpeed @@ -21,7 +21,7 @@ public class TickSpeed public static long time_bias = 0; public static long time_warp_start_time = 0; public static long time_warp_scheduled_ticks = 0; - public static PlayerEntity time_advancerer = null; + public static ServerPlayerEntity time_advancerer = null; public static String tick_warp_callback = null; public static ServerCommandSource tick_warp_sender = null; public static int player_active_timeout = 0; @@ -68,13 +68,14 @@ public class TickSpeed player_active_timeout = PLAYER_GRACE+ticks; } - public static BaseText tickrate_advance(PlayerEntity player, int advance, String callback, ServerCommandSource source) + public static BaseText tickrate_advance(ServerPlayerEntity player, int advance, String callback, ServerCommandSource source) { if (0 == advance) { tick_warp_callback = null; - tick_warp_sender = null; + if (source != tick_warp_sender) tick_warp_sender = null; finish_time_warp(); + tick_warp_sender = null; return Messenger.c("gi Warp interrupted"); } if (time_bias > 0) diff --git a/src/main/java/carpet/mixins/PlayerEntity_antiCheatDisabled.java b/src/main/java/carpet/mixins/PlayerEntity_antiCheatDisabled.java index 2f211d34..e8440bb4 100644 --- a/src/main/java/carpet/mixins/PlayerEntity_antiCheatDisabled.java +++ b/src/main/java/carpet/mixins/PlayerEntity_antiCheatDisabled.java @@ -23,7 +23,7 @@ public abstract class PlayerEntity_antiCheatDisabled @Inject(method = "method_23668", at = @At("HEAD"), cancellable = true) private void allowDeploys(CallbackInfoReturnable cir) { - if (CarpetSettings.antiCheatDisabled && CarpetServer.minecraft_server.isDedicated()) + if (CarpetSettings.antiCheatDisabled && CarpetServer.minecraft_server != null && CarpetServer.minecraft_server.isDedicated()) { ItemStack itemStack_1 = getEquippedStack(EquipmentSlot.CHEST); if (itemStack_1.getItem() == Items.ELYTRA && ElytraItem.isUsable(itemStack_1)) { diff --git a/src/main/java/carpet/script/CarpetEventServer.java b/src/main/java/carpet/script/CarpetEventServer.java index 4d3eb8d2..2eafcd6d 100644 --- a/src/main/java/carpet/script/CarpetEventServer.java +++ b/src/main/java/carpet/script/CarpetEventServer.java @@ -13,6 +13,7 @@ import carpet.script.value.Value; import carpet.utils.Messenger; import net.minecraft.block.BlockState; import net.minecraft.entity.damage.DamageSource; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.entity.Entity; import net.minecraft.server.network.ServerPlayerEntity; @@ -51,6 +52,7 @@ import java.util.stream.Collectors; public class CarpetEventServer { public final List scheduledCalls = new LinkedList<>(); + public final MinecraftServer server; public static class Callback { @@ -652,8 +654,9 @@ public class CarpetEventServer } - public CarpetEventServer() + public CarpetEventServer(MinecraftServer server) { + this.server = server; for (Event e: Event.values()) e.handler.callList.clear(); } diff --git a/src/main/java/carpet/script/CarpetScriptHost.java b/src/main/java/carpet/script/CarpetScriptHost.java index 94f3b2fc..8803d86f 100644 --- a/src/main/java/carpet/script/CarpetScriptHost.java +++ b/src/main/java/carpet/script/CarpetScriptHost.java @@ -323,7 +323,7 @@ public class CarpetScriptHost extends ScriptHost { try { - callUDF(BlockPos.ORIGIN, CarpetServer.minecraft_server.getCommandSource(), closing, Collections.emptyList()); + callUDF(BlockPos.ORIGIN, scriptServer.server.getCommandSource(), closing, Collections.emptyList()); } catch (InvalidCallbackException ignored) { @@ -334,8 +334,8 @@ public class CarpetScriptHost extends ScriptHost FunctionValue userClosing = value.getFunction("__on_close"); if (userClosing != null) { - ServerPlayerEntity player = CarpetServer.minecraft_server.getPlayerManager().getPlayer(key); - ServerCommandSource source = (player != null)?player.getCommandSource():CarpetServer.minecraft_server.getCommandSource(); + ServerPlayerEntity player = scriptServer.server.getPlayerManager().getPlayer(key); + ServerCommandSource source = (player != null)?player.getCommandSource():scriptServer.server.getCommandSource(); try { ((CarpetScriptHost) value).callUDF(BlockPos.ORIGIN, source, userClosing, Collections.emptyList()); @@ -347,7 +347,7 @@ public class CarpetScriptHost extends ScriptHost }); String markerName = CarpetExpression.MARKER_STRING+"_"+((getName()==null)?"":getName()); - for (ServerWorld world : CarpetServer.minecraft_server.getWorlds()) + for (ServerWorld world : scriptServer.server.getWorlds()) { for (Entity e : world.getEntities(EntityType.ARMOR_STAND, (as) -> as.getScoreboardTags().contains(markerName))) { diff --git a/src/main/java/carpet/script/CarpetScriptServer.java b/src/main/java/carpet/script/CarpetScriptServer.java index aa5b0983..a65a7655 100644 --- a/src/main/java/carpet/script/CarpetScriptServer.java +++ b/src/main/java/carpet/script/CarpetScriptServer.java @@ -15,6 +15,7 @@ import carpet.utils.Messenger; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.tree.CommandNode; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.util.math.BlockPos; @@ -34,6 +35,7 @@ import static net.minecraft.server.command.CommandManager.literal; public class CarpetScriptServer { //make static for now, but will change that later: + public final MinecraftServer server; public final CarpetScriptHost globalHost; public final Map modules; public long tickStart; @@ -49,14 +51,15 @@ public class CarpetScriptServer add(new BundledModule("math", true)); }}; - public CarpetScriptServer() + public CarpetScriptServer(MinecraftServer server) { + this.server = server; ScriptHost.systemGlobals.clear(); - events = new CarpetEventServer(); + events = new CarpetEventServer(server); modules = new HashMap<>(); tickStart = 0L; stopAll = false; - holyMoly = CarpetServer.minecraft_server.getCommandManager().getDispatcher().getRoot().getChildren().stream().map(CommandNode::getName).collect(Collectors.toSet()); + holyMoly = server.getCommandManager().getDispatcher().getRoot().getChildren().stream().map(CommandNode::getName).collect(Collectors.toSet()); globalHost = CarpetScriptHost.create(this, null, false, null); } @@ -64,10 +67,10 @@ public class CarpetScriptServer { if (CarpetSettings.scriptsAutoload) { - Messenger.m(CarpetServer.minecraft_server.getCommandSource(), "Auto-loading world scarpet apps"); + Messenger.m(server.getCommandSource(), "Auto-loading world scarpet apps"); for (String moduleName: listAvailableModules(false)) { - addScriptHost(CarpetServer.minecraft_server.getCommandSource(), moduleName, true, true); + addScriptHost(server.getCommandSource(), moduleName, true, true); } } @@ -75,8 +78,8 @@ public class CarpetScriptServer public Module getModule(String name, boolean allowLibraries) { - File folder = CarpetServer.minecraft_server.getLevelStorage().resolveFile( - CarpetServer.minecraft_server.getLevelName(), "scripts"); + File folder = server.getLevelStorage().resolveFile( + server.getLevelName(), "scripts"); File[] listOfFiles = folder.listFiles(); if (listOfFiles != null) for (File script : listOfFiles) @@ -110,8 +113,8 @@ public class CarpetScriptServer if (!mi.isLibrary()) moduleNames.add(mi.getName()); } } - File folder = CarpetServer.minecraft_server.getLevelStorage().resolveFile( - CarpetServer.minecraft_server.getLevelName(), "scripts"); + File folder = server.getLevelStorage().resolveFile( + server.getLevelName(), "scripts"); File[] listOfFiles = folder.listFiles(); if (listOfFiles == null) return moduleNames; @@ -223,7 +226,7 @@ public class CarpetScriptServer }))); } Messenger.m(source, "gi "+hostName+" app loaded with /"+hostName+" command"); - CarpetServer.minecraft_server.getCommandManager().getDispatcher().register(command); + server.getCommandManager().getDispatcher().register(command); CarpetServer.settingsManager.notifyPlayersCommandsChanged(); } diff --git a/src/main/java/carpet/settings/SettingsManager.java b/src/main/java/carpet/settings/SettingsManager.java index 5765f422..b792de08 100644 --- a/src/main/java/carpet/settings/SettingsManager.java +++ b/src/main/java/carpet/settings/SettingsManager.java @@ -362,8 +362,7 @@ public class SettingsManager { if (dispatcher.getRoot().getChildren().stream().anyMatch(node -> node.getName().equalsIgnoreCase(identifier))) { - Messenger.print_server_message(CarpetServer.minecraft_server, - Messenger.c("rb Failed to add settings command for " + identifier + ". It is masking previous command.")); + CarpetSettings.LOG.error("Failed to add settings command for " + identifier + ". It is masking previous command."); return; } From fb3a5cfa6472abc9b7c981965053dfa14efd0ece Mon Sep 17 00:00:00 2001 From: gnembon Date: Sun, 7 Jun 2020 01:52:38 -0300 Subject: [PATCH 181/198] read_file, delete_file, and write_file Deprecated some uses of load_app_data and store_app_data --- docs/scarpet/Full.md | 83 ++++++++++-- docs/scarpet/api/Auxiliary.md | 68 +++++++++- .../java/carpet/script/CarpetExpression.java | 128 ++++++++++++++---- .../java/carpet/script/CarpetScriptHost.java | 23 +++- src/main/java/carpet/script/Tokenizer.java | 6 +- .../carpet/script/bundled/FileModule.java | 49 ++++++- .../java/carpet/script/bundled/Module.java | 49 +++++-- 7 files changed, 351 insertions(+), 55 deletions(-) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index 717784c7..0e1a614e 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -3154,25 +3154,23 @@ Optional shared shape attributes: in the form of `0xRRGGBBAA`, with the default of `-1`, so white opaque, or `0xFFFFFFFF`. * `player` - name or player entity to send the shape to. If specified, the shapes will appear only for the specified player, otherwise it will be send to all players in the dimension. + * `width` - line thickness, defaults to 2.0pt + * `fill` - color for the faces, defaults to no fill. Use `color` attribute format + * `follow` - entity, or player name. Shape will follow an entity instead of being static. + Follow attribute requires all positional arguments to be relative to the entity and disallow + of using entity or block as position markers. You must specify positions as a triple. Available shapes: * `'line'` - draws a straight line between two points * Required attributes: * `from` - triple coordinates, entity, or block value indicating one end of the line * `to` - other end of the line, same format as `from` - * Optional attributes: - * `width` - line thickness, defaults to 2.0pt - * `follow` - entity, or player name. Shape will follow an entity instead of being static. - Follow attribute requires all positional arguments to be relative to the entity and disallow - of using entity or block as position markers. You must specify positions as a triple. * `'box'` - draws a box with corners in specified points * Required attributes: * `from` - triple coordinates, entity, or block value indicating one corner of the box * `to` - other corner, same format as `from` - * Optional attributes: - * `width` - mesh line thickness, defaults to 2.0pt - * `fill` - color for the box faces, defaults to no fill, use shared color attribute format + * `'sphere'` - draws a sphere * Required attributes: * `center` - center of the sphere @@ -3180,7 +3178,6 @@ Available shapes: * Optional attributes: * `level` - level of details, or grid size. The more the denser your sphere. Default level of 0, means that the level of detail will be selected automatically based on radius. - * `width` - line thickness ### `create_marker(text, pos, rotation?, block?)` @@ -3269,6 +3266,63 @@ Example usages: Prints the message to system logs, and not to chat. +### read_file(resource, type) +### delete_file(resource, type) +### write_file(resource, type, data, ...) + +With the specified `resource` in the scripts folder, of a specific `type`, writes/appends `data` to it, reads its + content, or deletes the resource. + +Resource is identified by a path to the file. +A path can contain letters, numbers and folder separator: `'/'`. Any other characters are stripped +from the name. Empty descriptors are invalid. Do not add file extensions to the descriptor - extensions are inferred +based on the `type` of the file. + +Resources can be located in the app specific space, or a shared space for all the apps. Accessing of app-specific +resources is guaranteed to be isolated from other apps. Shared resources are... well, shared across all apes, meaning +they can eat of each others file, however all access to files is synchronized, and files are never left open, so +this should not lead to any access problems. + +If the app's name is `'foo'`, the script location would +be `world/scripts/foo.sc`, app +specific data directory is under `world/scripts/foo.data/...`, and shared data space is under +`world/scripts/shared/...`. + +The default no-name app, via `/script run` command can only save/load/read files from the shared space. + +Functions return `null` if an error is encounter or no file is present (for read and delete operations). Returns `true` +for success writes and deletes, and requested data, based on the file type, for read operations. + +NBT files can be written once as they an store one tag at a time. Consecutive writes will overwrite previous data. + +Write operations to text files always result in appending to the existing file, so consecutive writes will increase +the size of the file and add data to it. Since files are closed after each write, sending multiple lines of data to +write is beneficial for writing speed. To send multiple packs of data, either provide them flat or as a list in the +third argument. + * `write_file('temp', 'text', 'foo', 'bar', 'baz')` or + * write_file('temp', 'text', l('foo', 'bar', 'baz')) + +To log a single line of string + +Supported values for resource `type` is: + * `nbt` - NBT tag + * `text` - text resource with automatic newlines added + * `raw` - text resource without implied newlines + * `shared_nbt`, `shared_text`, `shared_raw` - shared versions of the above + +NBT files have extension `.nbt`, store one NBT tag, and return a NBT type value. Text files have `.txt` extension, +stores multiple lines of text and returns lists of all lines from the file. With `write_file`, multiple lines can be +sent to the file at once. The only difference between `raw` and `text` types are automatic newlines added after each +record to the file. + +
+write_file('foo', 'shared_text, l('one', 'two'));
+write_file('foo', 'shared_text', 'three\n', 'four\n');
+write_file('foo', 'shared_raw', 'five\n', 'six\n');
+
+read_file('foo', 'shared_text')     => ['one', 'two', 'three', '', 'four', '', 'five', 'six']
+
+ ### `run(expr)` Runs a vanilla command from the string result of the `expr` and returns its success count @@ -3283,7 +3337,10 @@ run('give @s stone 4') -> 1 // this operation was successful once Performs autosave, saves all chunks, player data, etc. Useful for programs where autosave is disabled due to performance reasons and saves the world only on demand. -### `load_app_data(), load_app_data(file), load_app_data(file, shared?)` +### `load_app_data()` + +NOTE: usages with arguments, so `load_app_data(file)` and `load_app_data(file, shared?)` are deprecated. +Use `read_file` instead. Loads the app data associated with the app from the world /scripts folder. Without argument returns the memory managed and buffered / throttled NBT tag. With a file name, reads explicitly a file with that name from the @@ -3291,7 +3348,7 @@ scripts folder that belongs exclusively to the app. if `shared` is true, the fil to the app anymore, but located in a shared app space. File descriptor can contain letters, numbers and folder separator: `'/'`. Any other characters are stripped -from the name before saving/loading. Empty descriptors are invalid. +from the name before saving/loading. Empty descriptors are invalid. Do not add file extensions to the descriptor Function returns nbt value with the file content, or `null` if the file is missing or there were problems with retrieving the data. @@ -3305,7 +3362,9 @@ specific data directory is under `world/scripts/foo.data/bar/../baz.nbt`, and sh You can use app data to save non-vanilla information separately from the world and other scripts. -### `store_app_data(tag), store_app_data(tag, file), store_app_data(tag, file, shared?)` +### `store_app_data(tag)` + +Note: `store_app_data(tag, file)` and `store_app_data(tag, file, shared?)` usages deprecated. Use `write_file` instead. Stores the app data associated with the app from the world `/scripts` folder. With the `file` parameter saves immediately and with every call to a specific file defined by the `file`, either in app space, or in the scripts diff --git a/docs/scarpet/api/Auxiliary.md b/docs/scarpet/api/Auxiliary.md index b55c9f5a..d4de9940 100644 --- a/docs/scarpet/api/Auxiliary.md +++ b/docs/scarpet/api/Auxiliary.md @@ -172,6 +172,63 @@ Example usages: Prints the message to system logs, and not to chat. +### read_file(resource, type) +### delete_file(resource, type) +### write_file(resource, type, data, ...) + +With the specified `resource` in the scripts folder, of a specific `type`, writes/appends `data` to it, reads its + content, or deletes the resource. + +Resource is identified by a path to the file. +A path can contain letters, numbers and folder separator: `'/'`. Any other characters are stripped +from the name. Empty descriptors are invalid. Do not add file extensions to the descriptor - extensions are inferred +based on the `type` of the file. + +Resources can be located in the app specific space, or a shared space for all the apps. Accessing of app-specific +resources is guaranteed to be isolated from other apps. Shared resources are... well, shared across all apes, meaning +they can eat of each others file, however all access to files is synchronized, and files are never left open, so +this should not lead to any access problems. + +If the app's name is `'foo'`, the script location would +be `world/scripts/foo.sc`, app +specific data directory is under `world/scripts/foo.data/...`, and shared data space is under +`world/scripts/shared/...`. + +The default no-name app, via `/script run` command can only save/load/read files from the shared space. + +Functions return `null` if an error is encounter or no file is present (for read and delete operations). Returns `true` +for success writes and deletes, and requested data, based on the file type, for read operations. + +NBT files can be written once as they an store one tag at a time. Consecutive writes will overwrite previous data. + +Write operations to text files always result in appending to the existing file, so consecutive writes will increase +the size of the file and add data to it. Since files are closed after each write, sending multiple lines of data to +write is beneficial for writing speed. To send multiple packs of data, either provide them flat or as a list in the +third argument. + * `write_file('temp', 'text', 'foo', 'bar', 'baz')` or + * write_file('temp', 'text', l('foo', 'bar', 'baz')) + +To log a single line of string + +Supported values for resource `type` is: + * `nbt` - NBT tag + * `text` - text resource with automatic newlines added + * `raw` - text resource without implied newlines + * `shared_nbt`, `shared_text`, `shared_raw` - shared versions of the above + +NBT files have extension `.nbt`, store one NBT tag, and return a NBT type value. Text files have `.txt` extension, +stores multiple lines of text and returns lists of all lines from the file. With `write_file`, multiple lines can be +sent to the file at once. The only difference between `raw` and `text` types are automatic newlines added after each +record to the file. + +
+write_file('foo', 'shared_text, l('one', 'two'));
+write_file('foo', 'shared_text', 'three\n', 'four\n');
+write_file('foo', 'shared_raw', 'five\n', 'six\n');
+
+read_file('foo', 'shared_text')     => ['one', 'two', 'three', '', 'four', '', 'five', 'six']
+
+ ### `run(expr)` Runs a vanilla command from the string result of the `expr` and returns its success count @@ -186,7 +243,10 @@ run('give @s stone 4') -> 1 // this operation was successful once Performs autosave, saves all chunks, player data, etc. Useful for programs where autosave is disabled due to performance reasons and saves the world only on demand. -### `load_app_data(), load_app_data(file), load_app_data(file, shared?)` +### `load_app_data()` + +NOTE: usages with arguments, so `load_app_data(file)` and `load_app_data(file, shared?)` are deprecated. +Use `read_file` instead. Loads the app data associated with the app from the world /scripts folder. Without argument returns the memory managed and buffered / throttled NBT tag. With a file name, reads explicitly a file with that name from the @@ -194,7 +254,7 @@ scripts folder that belongs exclusively to the app. if `shared` is true, the fil to the app anymore, but located in a shared app space. File descriptor can contain letters, numbers and folder separator: `'/'`. Any other characters are stripped -from the name before saving/loading. Empty descriptors are invalid. +from the name before saving/loading. Empty descriptors are invalid. Do not add file extensions to the descriptor Function returns nbt value with the file content, or `null` if the file is missing or there were problems with retrieving the data. @@ -208,7 +268,9 @@ specific data directory is under `world/scripts/foo.data/bar/../baz.nbt`, and sh You can use app data to save non-vanilla information separately from the world and other scripts. -### `store_app_data(tag), store_app_data(tag, file), store_app_data(tag, file, shared?)` +### `store_app_data(tag)` + +Note: `store_app_data(tag, file)` and `store_app_data(tag, file, shared?)` usages deprecated. Use `write_file` instead. Stores the app data associated with the app from the world `/scripts` folder. With the `file` parameter saves immediately and with every call to a specific file defined by the `file`, either in app space, or in the scripts diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 6b9e45e8..06d324b3 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -2476,6 +2476,18 @@ public class CarpetExpression } + public static String recognizeResource(Value value) + { + String origfile = value.getString(); + String file = origfile.toLowerCase(Locale.ROOT).replaceAll("[^A-Za-z0-9/]", ""); + file = Arrays.stream(file.split("/+")).filter(s -> !s.isEmpty()).collect(Collectors.joining("/")); + if (file.isEmpty()) + { + throw new InternalExpressionException("Cannot use "+origfile+" as resource name - must have some letters and numbers"); + } + return file; + } + private void API_AuxiliaryAspects() { this.expr.addLazyFunction("sound", -1, (c, t, lv) -> { @@ -2864,13 +2876,6 @@ public class CarpetExpression // implmenetation should dock the task on the main thread. }); - this.expr.addLazyFunction("logger", 1, (c, t, lv) -> - { - Value res = lv.get(0).evalValue(c); - CarpetSettings.LOG.error(res.getString()); - return (_c, _t) -> res; // pass through for variables - }); - this.expr.addLazyFunction("run", 1, (c, t, lv) -> { BlockPos target = ((CarpetContext)c).origin; Vec3d posf = new Vec3d((double)target.getX()+0.5D,(double)target.getY(),(double)target.getZ()+0.5D); @@ -3057,25 +3062,108 @@ public class CarpetExpression return (c_, t_) -> Value.TRUE; }); + this.expr.addLazyFunction("logger", 1, (c, t, lv) -> + { + Value res = lv.get(0).evalValue(c); + CarpetSettings.LOG.error(res.getString()); + return (_c, _t) -> res; // pass through for variables + }); + + this.expr.addLazyFunction("read_file", 2, (c, t, lv) -> { + String resource = recognizeResource(lv.get(0).evalValue(c)); + String origtype = lv.get(1).evalValue(c).getString().toLowerCase(Locale.ROOT); + boolean shared = origtype.startsWith("shared_"); + String type = shared ? origtype.substring(7) : origtype; //len(shared_) + if (!type.equals("raw") && !type.equals("text") && !type.equals("nbt")) + throw new InternalExpressionException("Unsupported file type: "+origtype); + Value retVal; + if (type.equals("nbt")) + { + Tag state = ((CarpetScriptHost)((CarpetContext)c).host).readFileTag(resource, shared); + if (state == null) return LazyValue.NULL; + retVal = new NBTSerializableValue(state); + } + else + { + List content = ((CarpetScriptHost) ((CarpetContext) c).host).readTextResource(resource, shared); + if (content == null) return LazyValue.NULL; + retVal = ListValue.wrap(content.stream().map(StringValue::new).collect(Collectors.toList())); + } + return (cc, tt) -> retVal; + }); + + this.expr.addLazyFunction("delete_file", 2, (c, t, lv) -> { + String resource = recognizeResource(lv.get(0).evalValue(c)); + String origtype = lv.get(1).evalValue(c).getString().toLowerCase(Locale.ROOT); + boolean shared = origtype.startsWith("shared_"); + String type = shared ? origtype.substring(7) : origtype; //len(shared_) + if (!type.equals("raw") && !type.equals("text") && !type.equals("nbt")) + throw new InternalExpressionException("Unsupported file type: "+origtype); + boolean success = ((CarpetScriptHost)((CarpetContext)c).host).removeResourceFile(resource, shared, type); + return success?LazyValue.TRUE:LazyValue.FALSE; + }); + + this.expr.addLazyFunction("write_file", -1, (c, t, lv) -> { + if (lv.size() < 3) throw new InternalExpressionException("'write_file' requires three or more arguments"); + String resource = recognizeResource(lv.get(0).evalValue(c)); + String origtype = lv.get(1).evalValue(c).getString().toLowerCase(Locale.ROOT); + boolean shared = origtype.startsWith("shared_"); + String type = shared ? origtype.substring(7) : origtype; //len(shared_) + if (!type.equals("raw") && !type.equals("text") && !type.equals("nbt")) + throw new InternalExpressionException("Unsupported file type: "+origtype); + boolean success; + if (type.equals("nbt")) + { + Value val = lv.get(2).evalValue(c); + NBTSerializableValue tagValue = (val instanceof NBTSerializableValue) + ? (NBTSerializableValue) val + : new NBTSerializableValue(val.getString()); + Tag tag = tagValue.getTag(); + success = ((CarpetScriptHost)((CarpetContext)c).host).writeTagFile(tag, resource, shared); + } + else + { + List data = new ArrayList<>(); + if (lv.size()==3) + { + Value val = lv.get(2).evalValue(c); + if (val instanceof ListValue) + { + List lval = ((ListValue) val).getItems(); + lval.forEach(v -> data.add(v.getString())); + } + else + { + data.add(val.getString()); + } + } + else + { + for(int i = 2; i < lv.size(); i++) + { + data.add(lv.get(i).evalValue(c).getString()); + } + } + success = ((CarpetScriptHost) ((CarpetContext) c).host).appendLogFile(resource, shared, type, data); + } + return success?LazyValue.TRUE:LazyValue.FALSE; + }); + + //write_file + this.expr.addLazyFunction("load_app_data", -1, (c, t, lv) -> { String file = null; boolean shared = false; if (lv.size()>0) { - String origfile = lv.get(0).evalValue(c).getString(); - file = origfile.toLowerCase(Locale.ROOT).replaceAll("[^A-Za-z0-9/]", ""); - file = Arrays.stream(file.split("/+")).filter(s -> !s.isEmpty()).collect(Collectors.joining("/")); - if (file.isEmpty()) - { - throw new InternalExpressionException("Cannot use "+origfile+" as resource name - must have at least some letters and numbers"); - } + file = recognizeResource(lv.get(0).evalValue(c)); if (lv.size() > 1) { shared = lv.get(1).evalValue(c).getBoolean(); } } - Tag state = ((CarpetScriptHost)((CarpetContext)c).host).getGlobalState(file, shared); + Tag state = ((CarpetScriptHost)((CarpetContext)c).host).readFileTag(file, shared); if (state == null) return (cc, tt) -> Value.NULL; Value retVal = new NBTSerializableValue(state); @@ -3091,13 +3179,7 @@ public class CarpetExpression boolean shared = false; if (lv.size()>1) { - String origfile = lv.get(1).evalValue(c).getString(); - file = origfile.toLowerCase(Locale.ROOT).replaceAll("[^A-Za-z0-9/]", ""); - file = Arrays.stream(file.split("/+")).filter(s -> !s.isEmpty()).collect(Collectors.joining("/")); - if (file.isEmpty()) - { - throw new InternalExpressionException("Cannot use "+origfile+" as resource name - must have some letters and numbers"); - } + file = recognizeResource(lv.get(1).evalValue(c)); if (lv.size() > 2) { shared = lv.get(2).evalValue(c).getBoolean(); @@ -3107,7 +3189,7 @@ public class CarpetExpression ? (NBTSerializableValue) val : new NBTSerializableValue(val.getString()); Tag tag = tagValue.getTag(); - boolean success = ((CarpetScriptHost)((CarpetContext)c).host).setGlobalState(tag, file, shared); + boolean success = ((CarpetScriptHost)((CarpetContext)c).host).writeTagFile(tag, file, shared); return success?LazyValue.TRUE:LazyValue.FALSE; }); diff --git a/src/main/java/carpet/script/CarpetScriptHost.java b/src/main/java/carpet/script/CarpetScriptHost.java index 8803d86f..25892565 100644 --- a/src/main/java/carpet/script/CarpetScriptHost.java +++ b/src/main/java/carpet/script/CarpetScriptHost.java @@ -369,7 +369,7 @@ public class CarpetScriptHost extends ScriptHost return Module.getData(main, null, false); } - public Tag getGlobalState(String file, boolean isShared) + public Tag readFileTag(String file, boolean isShared) { if (getName() == null && !isShared) return null; if (file != null) @@ -379,7 +379,7 @@ public class CarpetScriptHost extends ScriptHost return ((CarpetScriptHost)parent).globalState; } - public boolean setGlobalState(Tag tag, String file, boolean isShared) + public boolean writeTagFile(Tag tag, String file, boolean isShared) { if (getName() == null && !isShared) return false; // if belongs to an app, cannot be default host. @@ -398,6 +398,25 @@ public class CarpetScriptHost extends ScriptHost return true; } + public boolean removeResourceFile(String resource, boolean isShared, String type) + { + if (getName() == null && !isShared) return false; // + return Module.dropExistingFile(main, resource, type.equals("nbt")?"nbt":"txt", isShared); + } + + public boolean appendLogFile(String resource, boolean isShared, String type, List data) + { + if (getName() == null && !isShared) return false; // if belongs to an app, cannot be default host. + return Module.appendToTextFile(main, resource, type, isShared, data); + } + + public List readTextResource(String resource, boolean isShared) + { + if (getName() == null && !isShared) return null; // + return Module.listFile(main, resource, "txt", isShared); + } + + public void tick() { if (this.saveTimeout > 0) diff --git a/src/main/java/carpet/script/Tokenizer.java b/src/main/java/carpet/script/Tokenizer.java index f0c1d4eb..ef4c0d5e 100644 --- a/src/main/java/carpet/script/Tokenizer.java +++ b/src/main/java/carpet/script/Tokenizer.java @@ -173,9 +173,9 @@ public class Tokenizer implements Iterator } else if (nextChar == 't') { - throw new ExpressionException(context, this.expression, token, - "Tab character is not supported"); - //token.append('\t'); + //throw new ExpressionException(context, this.expression, token, + // "Tab character is not supported"); + token.append('\t'); } else if (nextChar == 'r') { diff --git a/src/main/java/carpet/script/bundled/FileModule.java b/src/main/java/carpet/script/bundled/FileModule.java index ef44a292..4c116eec 100644 --- a/src/main/java/carpet/script/bundled/FileModule.java +++ b/src/main/java/carpet/script/bundled/FileModule.java @@ -1,17 +1,24 @@ package carpet.script.bundled; -import carpet.CarpetServer; import net.minecraft.nbt.PositionTracker; import net.minecraft.nbt.Tag; import net.minecraft.nbt.TagReaders; +import java.io.BufferedReader; +import java.io.BufferedWriter; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import java.nio.file.StandardOpenOption; +import java.util.ArrayList; +import java.util.List; import java.util.Locale; public class FileModule extends Module @@ -96,4 +103,44 @@ public class FileModule extends Module if (!file.exists()) file_2.renameTo(file); return true; } + + public static boolean appendText(File filePath, boolean addNewLines, List data) + { + try + { + OutputStream out = Files.newOutputStream(filePath.toPath(), StandardOpenOption.APPEND, StandardOpenOption.CREATE); + try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8))) + { + for (String line: data) + { + writer.append(line); + if (addNewLines) writer.newLine(); + } + } + } + catch (IOException e) + { + return false; + } + return true; + } + + + public static List listFileContent(File filePath) + { + try (BufferedReader reader = Files.newBufferedReader(filePath.toPath(), StandardCharsets.UTF_8)) { + List result = new ArrayList<>(); + for (;;) { + String line = reader.readLine(); + if (line == null) + break; + result.add(line.replaceAll("[\n\r]+","")); + } + return result; + } + catch (IOException e) + { + return null; + } + } } diff --git a/src/main/java/carpet/script/bundled/Module.java b/src/main/java/carpet/script/bundled/Module.java index c15cebd4..deca890e 100644 --- a/src/main/java/carpet/script/bundled/Module.java +++ b/src/main/java/carpet/script/bundled/Module.java @@ -5,15 +5,14 @@ import net.minecraft.nbt.Tag; import java.io.File; import java.nio.file.Files; - -import static carpet.script.bundled.FileModule.read; -import static carpet.script.bundled.FileModule.write; +import java.util.List; public abstract class Module { public abstract String getName(); public abstract String getCode(); public abstract boolean isLibrary(); + public final static Object writeIOSync = new Object(); private static String getDescriptor(Module module, String file, boolean isShared) { @@ -33,20 +32,48 @@ public abstract class Module public static Tag getData(Module module, String file, boolean isShared) { - if (!isShared && (module == null || module.getName() == null)) return null; - File dataFile = CarpetServer.minecraft_server.getLevelStorage().resolveFile( - CarpetServer.minecraft_server.getLevelName(), "scripts/"+getDescriptor(module, file, isShared)+".nbt"); + File dataFile = resolveResource(module, file, "nbt", isShared); + if (dataFile == null) return null; if (!Files.exists(dataFile.toPath()) || !(dataFile.isFile())) return null; - return read(dataFile); + synchronized (writeIOSync) { return FileModule.read(dataFile); } } public static boolean saveData(Module module, String file, Tag globalState, boolean isShared) { - if (!isShared && (module == null || module.getName() == null)) return false; - File dataFile =CarpetServer.minecraft_server.getLevelStorage().resolveFile( - CarpetServer.minecraft_server.getLevelName(), "scripts/"+getDescriptor(module, file, isShared)+".nbt"); + File dataFile = resolveResource(module, file, "nbt", isShared); + if (dataFile == null) return false; if (!Files.exists(dataFile.toPath().getParent()) && !dataFile.getParentFile().mkdirs()) return false; - return write(globalState, dataFile); + synchronized (writeIOSync) { return FileModule.write(globalState, dataFile); } + } + + public static boolean appendToTextFile(Module module, String resourceName, String type, boolean isShared, List message) + { + File dataFile = resolveResource(module, resourceName, "txt", isShared); + if (dataFile == null) return false; + if (!Files.exists(dataFile.toPath().getParent()) && !dataFile.getParentFile().mkdirs()) return false; + synchronized (writeIOSync) { return FileModule.appendText(dataFile, type.equals("text"), message); } + } + + public static boolean dropExistingFile(Module module, String resourceName, String ext, boolean isShared) + { + File dataFile = resolveResource(module, resourceName, ext, isShared); + if (dataFile == null) return false; + synchronized (writeIOSync) { return dataFile.delete(); } + } + + public static List listFile(Module module, String resourceName, String ext, boolean isShared) + { + File dataFile = resolveResource(module, resourceName, ext, isShared); + if (dataFile == null) return null; + if (!dataFile.exists()) return null; + synchronized (writeIOSync) { return FileModule.listFileContent(dataFile); } + } + + private static File resolveResource(Module module, String resourceName, String ext, boolean isShared) + { + if (!isShared && (module == null || module.getName() == null)) return null; + return CarpetServer.minecraft_server.getLevelStorage().resolveFile( + CarpetServer.minecraft_server.getLevelName(), "scripts/"+getDescriptor(module, resourceName, isShared)+"."+ext); } @Override From d9ed35676ff77e95fb60f9178ff7dac285b27d43 Mon Sep 17 00:00:00 2001 From: Ghoulboy Date: Sun, 7 Jun 2020 22:57:04 +0200 Subject: [PATCH 182/198] Added hunger, saturation and exhaustion modification and querying (#286) * Added hunger querying and modification * Cleaning up old code * forgot semicolon * Added saturation querying and modification and exhaustion modification working on exhaustion querying * added if statements to avoid crash * more if statements * o ye boi! Co-authored-by: Ghoulboy78 <53367549+Ghoulboy-78@users.noreply.github.com> --- .../carpet/fakes/HungerManagerInterface.java | 5 +++ ...HungerManagerMixin_scarpetEventsMixin.java | 20 +++++++++ .../java/carpet/script/value/EntityValue.java | 43 ++++++++++++++----- src/main/resources/carpet.mixins.json | 2 +- 4 files changed, 59 insertions(+), 11 deletions(-) create mode 100644 src/main/java/carpet/fakes/HungerManagerInterface.java create mode 100644 src/main/java/carpet/mixins/HungerManagerMixin_scarpetEventsMixin.java diff --git a/src/main/java/carpet/fakes/HungerManagerInterface.java b/src/main/java/carpet/fakes/HungerManagerInterface.java new file mode 100644 index 00000000..028c0bf3 --- /dev/null +++ b/src/main/java/carpet/fakes/HungerManagerInterface.java @@ -0,0 +1,5 @@ +package carpet.fakes; + +public interface HungerManagerInterface { + float getExhaustion(); +} diff --git a/src/main/java/carpet/mixins/HungerManagerMixin_scarpetEventsMixin.java b/src/main/java/carpet/mixins/HungerManagerMixin_scarpetEventsMixin.java new file mode 100644 index 00000000..c9f341e3 --- /dev/null +++ b/src/main/java/carpet/mixins/HungerManagerMixin_scarpetEventsMixin.java @@ -0,0 +1,20 @@ +package carpet.mixins; + +import carpet.fakes.EntityInterface; +import carpet.fakes.HungerManagerInterface; +import carpet.script.EntityEventsGroup; +import net.minecraft.entity.damage.DamageSource; +import net.minecraft.entity.player.HungerManager; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(HungerManager.class) +public class HungerManagerMixin_scarpetEventsMixin implements HungerManagerInterface { + @Shadow private float exhaustion; + public float getExhaustion(){ + return exhaustion; + } +} \ No newline at end of file diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index 68c3f14d..faec676c 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -1,17 +1,21 @@ package carpet.script.value; +import carpet.CarpetSettings; import carpet.fakes.EntityInterface; import carpet.fakes.ItemEntityInterface; import carpet.fakes.LivingEntityInterface; import carpet.fakes.MobEntityInterface; +import carpet.fakes.HungerManagerInterface; import carpet.helpers.Tracer; import carpet.patches.EntityPlayerMPFake; import carpet.script.CarpetContext; import carpet.script.EntityEventsGroup; import carpet.script.argument.Vector3Argument; import carpet.script.exception.InternalExpressionException; +import carpet.utils.Messenger; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.entity.player.HungerManager; import net.minecraft.network.packet.s2c.play.EntityPassengersSetS2CPacket; import net.minecraft.network.packet.s2c.play.EntityPositionS2CPacket; import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket; @@ -285,6 +289,21 @@ public class EntityValue extends Value put("sneaking", (e, a) -> e.isSneaking()?Value.TRUE:Value.FALSE); put("sprinting", (e, a) -> e.isSprinting()?Value.TRUE:Value.FALSE); put("swimming", (e, a) -> e.isSwimming()?Value.TRUE:Value.FALSE); + put("hunger", (e, a) -> { + if(e instanceof PlayerEntity) return new NumericValue(((PlayerEntity) e).getHungerManager().getFoodLevel()); + return Value.NULL; + }); + put("saturation", (e, a) -> { + if(e instanceof PlayerEntity) return new NumericValue(((PlayerEntity) e).getHungerManager().getSaturationLevel()); + return Value.NULL; + }); + + put("exhaustion",(e, a)->{ + if(e instanceof PlayerEntity) + return new NumericValue(((HungerManagerInterface)((PlayerEntity) e).getHungerManager()).getExhaustion()); + return Value.NULL; + }); + put("jumping", (e, a) -> { if (e instanceof LivingEntity) { @@ -934,20 +953,24 @@ public class EntityValue extends Value } }); - put("silent",(e,v)->{ - e.setSilent(v.getBoolean()); + put("silent",(e,v)-> e.setSilent(v.getBoolean())); + + put("gravity",(e,v)-> e.setNoGravity(!v.getBoolean())); + + put("invulnerable",(e,v)-> e.setInvulnerable(v.getBoolean())); + + put("fire",(e,v)-> e.setFireTicks((int)NumericValue.asNumber(v).getLong())); + + put("hunger", (e, v)-> { + if(e instanceof PlayerEntity) ((PlayerEntity) e).getHungerManager().setFoodLevel((int) NumericValue.asNumber(v).getLong()); }); - put("gravity",(e,v)->{ - e.setNoGravity(!v.getBoolean()); + put("exhaustion", (e, v)-> { + if(e instanceof PlayerEntity) ((PlayerEntity) e).getHungerManager().addExhaustion((int) NumericValue.asNumber(v).getLong()); }); - put("invulnerable",(e,v)->{ - e.setInvulnerable(v.getBoolean()); - }); - - put("fire",(e,v)->{ - e.setFireTicks((int)NumericValue.asNumber(v).getLong()); + put("saturation", (e, v)-> { + if(e instanceof PlayerEntity) ((PlayerEntity) e).getHungerManager().setSaturationLevelClient((float)NumericValue.asNumber(v).getLong()); }); // gamemode [check] diff --git a/src/main/resources/carpet.mixins.json b/src/main/resources/carpet.mixins.json index 4b63eb8e..65ec4c40 100644 --- a/src/main/resources/carpet.mixins.json +++ b/src/main/resources/carpet.mixins.json @@ -155,7 +155,7 @@ "StatType_scarpetMixin", "PointOfInterest_scarpetMixin", "ServerWorld_scarpetEventMixin", - + "HungerManagerMixin_scarpetEventsMixin", "PistonBlock_movableTEMixin", "PistonBlockEntity_movableTEMixin", From 73cb9d696821928ad9f73764b4dad6148e5c84e8 Mon Sep 17 00:00:00 2001 From: gnembon Date: Sun, 7 Jun 2020 18:53:17 -0300 Subject: [PATCH 183/198] added hunger, saturation, and exhaustion entity API calls. --- docs/scarpet/api/Entities.md | 18 ++++++++++++++++++ .../carpet/fakes/HungerManagerInterface.java | 3 ++- .../HungerManagerMixin_scarpetEventsMixin.java | 16 ++++++++-------- .../java/carpet/script/value/EntityValue.java | 7 +++++-- 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/docs/scarpet/api/Entities.md b/docs/scarpet/api/Entities.md index 36365a78..f2d7bb97 100644 --- a/docs/scarpet/api/Entities.md +++ b/docs/scarpet/api/Entities.md @@ -314,6 +314,13 @@ query(p,'effect','resistance') => null Number indicating remaining entity health, or `null` if not applicable. +### `query(e, 'hunger')` +### `query(e, 'saturation')` +### `query(e, 'exhaustion')` + +Retrieves player hunger related information. For non-players, returns `null`. + + ### `query(e, 'holds', slot?)` Returns triple of short name, stack count, and NBT of item held in `slot`, or `null` if nothing or not applicable. Available options for `slot` are: @@ -513,6 +520,17 @@ Toggles gravity for the entity. Will set entity on fire for `ticks` ticks. Set to 0 to extinguish. +### `modify(e, 'hunger', value)` +### `modify(e, 'saturation', value)` +### `modify(e, 'exhaustion', value)` + +Modifies directly player raw hunger components. Has no effect on non-players + +### `modify(e, 'add_exhaustion', value)` + +adds exhaustion value to the current player exhaustion level - that's the method you probably want to use +to manipulate how much 'food' some action cost. + ## Entity Events There is a number of events that happen to entities that you can attach your own code to in the form of event handlers. diff --git a/src/main/java/carpet/fakes/HungerManagerInterface.java b/src/main/java/carpet/fakes/HungerManagerInterface.java index 028c0bf3..b4df2334 100644 --- a/src/main/java/carpet/fakes/HungerManagerInterface.java +++ b/src/main/java/carpet/fakes/HungerManagerInterface.java @@ -1,5 +1,6 @@ package carpet.fakes; public interface HungerManagerInterface { - float getExhaustion(); + float getExhaustionCM(); + void setExhaustionCM(float exhaust); } diff --git a/src/main/java/carpet/mixins/HungerManagerMixin_scarpetEventsMixin.java b/src/main/java/carpet/mixins/HungerManagerMixin_scarpetEventsMixin.java index c9f341e3..3e6fcdc2 100644 --- a/src/main/java/carpet/mixins/HungerManagerMixin_scarpetEventsMixin.java +++ b/src/main/java/carpet/mixins/HungerManagerMixin_scarpetEventsMixin.java @@ -1,20 +1,20 @@ package carpet.mixins; -import carpet.fakes.EntityInterface; import carpet.fakes.HungerManagerInterface; -import carpet.script.EntityEventsGroup; -import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.player.HungerManager; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(HungerManager.class) public class HungerManagerMixin_scarpetEventsMixin implements HungerManagerInterface { @Shadow private float exhaustion; - public float getExhaustion(){ + public float getExhaustionCM(){ return exhaustion; } -} \ No newline at end of file + + @Override + public void setExhaustionCM(float exhaust) + { + exhaustion = exhaust; + } +} diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index faec676c..0b053f2c 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -299,8 +299,7 @@ public class EntityValue extends Value }); put("exhaustion",(e, a)->{ - if(e instanceof PlayerEntity) - return new NumericValue(((HungerManagerInterface)((PlayerEntity) e).getHungerManager()).getExhaustion()); + if(e instanceof PlayerEntity) return new NumericValue(((HungerManagerInterface)((PlayerEntity) e).getHungerManager()).getExhaustionCM()); return Value.NULL; }); @@ -966,6 +965,10 @@ public class EntityValue extends Value }); put("exhaustion", (e, v)-> { + if(e instanceof PlayerEntity) ((HungerManagerInterface) ((PlayerEntity) e).getHungerManager()).setExhaustionCM(NumericValue.asNumber(v).getFloat()); + }); + + put("add_exhaustion", (e, v)-> { if(e instanceof PlayerEntity) ((PlayerEntity) e).getHungerManager().addExhaustion((int) NumericValue.asNumber(v).getLong()); }); From 2f08ee8c0149518b79f67c672838779ed62776a0 Mon Sep 17 00:00:00 2001 From: gnembon Date: Sun, 7 Jun 2020 19:32:08 -0300 Subject: [PATCH 184/198] player inventories can be specified as strings player enderchest inventories can also be specified as a single string. --- docs/scarpet/api/Inventories.md | 7 ++++- .../script/value/NBTSerializableValue.java | 30 ++++++++++++++----- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/docs/scarpet/api/Inventories.md b/docs/scarpet/api/Inventories.md index 972cf5b5..5ef96c7a 100644 --- a/docs/scarpet/api/Inventories.md +++ b/docs/scarpet/api/Inventories.md @@ -4,7 +4,12 @@ Most functions in this category require inventory as the first argument. Inventory could be specified by an entity, or a block, or position (three coordinates) of a potential block with inventory. Player enderchest inventory require -two arguments, keyword `'enderchest'`, followed by the player entity argument. If the entity or a block doesn't have +two arguments, keyword `'enderchest'`, followed by the player entity argument, or a single argument as a string of a +form: `'enderchest_steve'`. If your player name starts with enderchest, it can be always accessed by passing a player +entity value. If all else fails, it will try to identify first three arguments as coordinates of a block position of +a block inventory. Player inventories can also be called by their name. + + If the entity or a block doesn't have an inventory, they typically do nothing and return null. Most items returned are in the form of a triple of item name, count, and nbt or the extra data associated with an item. diff --git a/src/main/java/carpet/script/value/NBTSerializableValue.java b/src/main/java/carpet/script/value/NBTSerializableValue.java index 07256909..b4ce70b5 100644 --- a/src/main/java/carpet/script/value/NBTSerializableValue.java +++ b/src/main/java/carpet/script/value/NBTSerializableValue.java @@ -27,6 +27,7 @@ import net.minecraft.nbt.StringNbtReader; import net.minecraft.nbt.StringTag; import net.minecraft.nbt.Tag; import net.minecraft.predicate.entity.EntityPredicates; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; @@ -35,6 +36,7 @@ import net.minecraft.util.math.Box; import java.util.Collection; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.function.Supplier; import java.util.regex.Matcher; @@ -201,16 +203,30 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa return null; return new InventoryLocator(pos, pos, inv, offset + 1); } - else if (v1.getString().equalsIgnoreCase("enderchest")) + else if (v1 instanceof StringValue) { - Value v2 = params.get(1 + offset).evalValue(c); - if (!(v2 instanceof EntityValue) || !(((EntityValue) v2).getEntity() instanceof PlayerEntity)) + String strVal = v1.getString().toLowerCase(Locale.ROOT); + if (strVal.equals("enderchest")) { - throw new InternalExpressionException("enderchest inventory requires player argument"); + Value v2 = params.get(1 + offset).evalValue(c); + ServerPlayerEntity player = EntityValue.getPlayerByValue(c.s.getMinecraftServer(), v2); + if (player == null) throw new InternalExpressionException("enderchest inventory requires player argument"); + return new InventoryLocator(player, player.getBlockPos(), player.getEnderChestInventory(), offset + 2, true); + } + else + { + boolean isEnder = strVal.startsWith("enderchest_"); + if (isEnder) strVal = strVal.substring(11); // len("enderchest_") + ServerPlayerEntity player = c.s.getMinecraftServer().getPlayerManager().getPlayer(strVal); + if (player == null) throw new InternalExpressionException("String description of an inventory should either denote a player or player's enderchest"); + return new InventoryLocator( + player, + player.getBlockPos(), + isEnder ? player.getEnderChestInventory() : player.inventory, + offset + 1, + isEnder + ); } - PlayerEntity e = (PlayerEntity)((EntityValue) v2).getEntity(); - inv = e.getEnderChestInventory(); - return new InventoryLocator(e, e.getBlockPos(), inv, offset + 2, true); } BlockPos pos = new BlockPos( NumericValue.asNumber(v1).getDouble(), From 2739ef9d444577eb55de6873172ade3d7aebef27 Mon Sep 17 00:00:00 2001 From: gnembon Date: Sun, 7 Jun 2020 22:44:52 -0300 Subject: [PATCH 185/198] added sync-preferred option to camera path --- .../resources/assets/carpet/scripts/camera.sc | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/main/resources/assets/carpet/scripts/camera.sc b/src/main/resources/assets/carpet/scripts/camera.sc index 57bf59f2..993825db 100644 --- a/src/main/resources/assets/carpet/scripts/camera.sc +++ b/src/main/resources/assets/carpet/scripts/camera.sc @@ -49,6 +49,11 @@ __command() -> print(' "/camera show": Show current path particles'); print(' color of particles used is different for different players'); print(' "/camera hide": Hide path display'); + print(' "/camera prefer_smooth_play": '); + print(' Eat CPU spikes and continue as usual'); + print(' "/camera prefer_synced_play": '); + print(' After CPU spikes jump to where you should be'); + print(''); '' ); @@ -483,6 +488,11 @@ hide() -> ); // runs the player on the path +global_prefer_sync = false; + +prefer_smooth_play() -> (global_prefer_sync = false; 'Smooth path play'); +prefer_synced_play() -> (global_prefer_sync = true; 'Synchronized path play'); + play() -> ( if (err = __is_not_valid_for_motion(), exit(err)); @@ -501,6 +511,7 @@ play() -> global_playing_path = true; mspt = 1000 / 60; start_time = time(); + very_start = start_time; point = 0; p = __get_player(); try ( @@ -514,9 +525,14 @@ play() -> modify(p, 'location', v); point += 1; end_time = time(); - took = end_time - start_time; - if (took < mspt, sleep(mspt-took)); - start_time = time() + if (global_prefer_sync, + should_be = very_start + mspt*point; + if (end_time < should_be, sleep(should_be-end_time) ) + , + took = end_time - start_time; + if (took < mspt, sleep(mspt-took)); + start_time = time() + ) ) ); ); From 2f102a77857df961ddbb5978c615114dae0ce475 Mon Sep 17 00:00:00 2001 From: gnembon Date: Mon, 8 Jun 2020 21:24:56 -0300 Subject: [PATCH 186/198] Switched to 64FNV-1a as shapes keying algorithm as collision resistant Allow shapes to be sent in bulk as one / few packets Optimized rendering of shapes that not render all faces Moving shapes render now smoothly with higher framerates --- .../DebugRenderer_scarpetRenderMixin.java | 23 +- .../WorldRenderer_scarpetRenderMixin.java | 32 +++ .../carpet/network/ClientNetworkHandler.java | 7 +- .../java/carpet/script/CarpetExpression.java | 45 +--- .../carpet/script/utils/ShapeDispatcher.java | 249 ++++++++++++++---- .../carpet/script/utils/ShapesRenderer.java | 232 ++++++++++------ .../assets/carpet/scripts/chunk_display.sc | 181 +++++++++++++ .../assets/carpet/scripts/overlay.sc | 16 +- src/main/resources/carpet.mixins.json | 3 +- 9 files changed, 595 insertions(+), 193 deletions(-) create mode 100644 src/main/java/carpet/mixins/WorldRenderer_scarpetRenderMixin.java create mode 100644 src/main/resources/assets/carpet/scripts/chunk_display.sc diff --git a/src/main/java/carpet/mixins/DebugRenderer_scarpetRenderMixin.java b/src/main/java/carpet/mixins/DebugRenderer_scarpetRenderMixin.java index a57a3b26..0ed9e836 100644 --- a/src/main/java/carpet/mixins/DebugRenderer_scarpetRenderMixin.java +++ b/src/main/java/carpet/mixins/DebugRenderer_scarpetRenderMixin.java @@ -1,11 +1,7 @@ package carpet.mixins; import carpet.network.CarpetClient; -import carpet.script.utils.ShapesRenderer; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.debug.DebugRenderer; -import net.minecraft.client.util.math.MatrixStack; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -14,25 +10,10 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(DebugRenderer.class) public class DebugRenderer_scarpetRenderMixin { - private ShapesRenderer shapes; - - @Inject(method = "", at = @At("RETURN")) - private void addRenderers(MinecraftClient client, CallbackInfo ci) - { - shapes = new ShapesRenderer(client); - CarpetClient.shapes = shapes; - } - @Inject(method = "reset", at = @At("HEAD")) private void resetScarpetRenderes(CallbackInfo ci) { - shapes.reset(); + if (CarpetClient.shapes != null) + CarpetClient.shapes.reset(); } - - @Inject(method = "render", at = @At("HEAD")) - private void renderScarpetThings(MatrixStack matrices, VertexConsumerProvider.Immediate vertexConsumers, double cameraX, double cameraY, double cameraZ, CallbackInfo ci) - { - shapes.render(matrices, vertexConsumers, cameraX, cameraY, cameraZ); - } - } diff --git a/src/main/java/carpet/mixins/WorldRenderer_scarpetRenderMixin.java b/src/main/java/carpet/mixins/WorldRenderer_scarpetRenderMixin.java new file mode 100644 index 00000000..df777e69 --- /dev/null +++ b/src/main/java/carpet/mixins/WorldRenderer_scarpetRenderMixin.java @@ -0,0 +1,32 @@ +package carpet.mixins; + +import carpet.network.CarpetClient; +import carpet.script.utils.ShapesRenderer; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.BufferBuilderStorage; +import net.minecraft.client.render.Camera; +import net.minecraft.client.render.GameRenderer; +import net.minecraft.client.render.LightmapTextureManager; +import net.minecraft.client.render.WorldRenderer; +import net.minecraft.client.util.math.Matrix4f; +import net.minecraft.client.util.math.MatrixStack; +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.CallbackInfo; + +@Mixin(WorldRenderer.class) +public class WorldRenderer_scarpetRenderMixin +{ + @Inject(method = "", at = @At("RETURN")) + private void addRenderers(MinecraftClient client, BufferBuilderStorage bufferBuilders, CallbackInfo ci) + { + CarpetClient.shapes = new ShapesRenderer(client); + } + + @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/debug/DebugRenderer;render(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider$Immediate;DDD)V")) + private void renderScarpetThings(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, CallbackInfo ci) + { + if (CarpetClient.shapes != null) CarpetClient.shapes.render(camera, tickDelta); + } +} diff --git a/src/main/java/carpet/network/ClientNetworkHandler.java b/src/main/java/carpet/network/ClientNetworkHandler.java index 07ec99df..c65e2ac6 100644 --- a/src/main/java/carpet/network/ClientNetworkHandler.java +++ b/src/main/java/carpet/network/ClientNetworkHandler.java @@ -8,6 +8,7 @@ import io.netty.buffer.Unpooled; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.nbt.AbstractNumberTag; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.network.packet.c2s.play.CustomPayloadC2SPacket; import net.minecraft.util.PacketByteBuf; @@ -35,10 +36,14 @@ public class ClientNetworkHandler } }); put("TickRate", (p, t) -> TickSpeed.tickrate(((AbstractNumberTag)t).getFloat(), false)); - put("scShape", (p, t) -> { + put("scShape", (p, t) -> { // deprecated if (CarpetClient.shapes != null) CarpetClient.shapes.addShape((CompoundTag)t); }); + put("scShapes", (p, t) -> { + if (CarpetClient.shapes != null) + CarpetClient.shapes.addShapes((ListTag) t); + }); }}; diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 06d324b3..711d07d6 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -2662,47 +2662,28 @@ public class CarpetExpression this.expr.addLazyFunction("draw_shape", -1, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; - if (lv.size() < 3) throw new InternalExpressionException("'draw_shape' takes at least three parameters, shape name, duration, and its params"); - String shapeType = lv.get(0).evalValue(c).getString(); - Value duration = NumericValue.asNumber(lv.get(1).evalValue(c)); - Map params; - if (lv.size() == 3) + ServerPlayerEntity player[] = {null}; + List>> shapes = new ArrayList<>(); + if (lv.size() == 1) // bulk { - Value paramValue = lv.get(2).evalValue(c); - if (paramValue instanceof MapValue) + Value specLoad = lv.get(0).evalValue(c); + if (!(specLoad instanceof ListValue)) throw new InternalExpressionException("In bulk mode - shapes need to be provided as a list of shape specs"); + for (Value list : ((ListValue) specLoad).getItems()) { - params = new HashMap<>(); - ((MapValue) paramValue).getMap().entrySet().forEach(e -> params.put(e.getKey().getString(),e.getValue())); + if (!(list instanceof ListValue)) throw new InternalExpressionException("In bulk mode - shapes need to be provided as a list of shape specs"); + shapes.add( ShapeDispatcher.fromFunctionArgs(cc, ((ListValue) list).getItems(), player)); } - else if (paramValue instanceof ListValue) - { - params = ShapeDispatcher.parseParams(((ListValue) paramValue).getItems()); - } - else throw new InternalExpressionException("Parameters for 'draw_shape' need to be defined either in a list or a map"); } else { - List paramList = new ArrayList<>(); - for (int i=2; i < lv.size(); i++) paramList.add(lv.get(i).evalValue(c)); - params = ShapeDispatcher.parseParams(paramList); + List params = new ArrayList<>(); + for (LazyValue v : lv) params.add(v.evalValue(c)); + shapes.add(ShapeDispatcher.fromFunctionArgs(cc, params, player)); } - params.putIfAbsent("dim", new StringValue(cc.s.getWorld().getDimension().getType().toString())); - params.putIfAbsent("duration", duration); - ServerPlayerEntity player = null; - if (params.containsKey("player")) - { - player = EntityValue.getPlayerByValue(cc.s.getMinecraftServer(), params.get("player")); - if (player == null) - throw new InternalExpressionException("'player' parameter needs to represent an existing player"); - params.remove("player"); - } - - ShapeDispatcher.ExpiringShape shape = ShapeDispatcher.create(cc, shapeType, params); ShapeDispatcher.sendShape( - (player==null)?cc.s.getWorld().getPlayers():Collections.singletonList(player), - shape, - params + (player[0]==null)?cc.s.getWorld().getPlayers():Collections.singletonList(player[0]), + shapes ); return LazyValue.TRUE; }); diff --git a/src/main/java/carpet/script/utils/ShapeDispatcher.java b/src/main/java/carpet/script/utils/ShapeDispatcher.java index 5a66f723..770d7639 100644 --- a/src/main/java/carpet/script/utils/ShapeDispatcher.java +++ b/src/main/java/carpet/script/utils/ShapeDispatcher.java @@ -8,6 +8,7 @@ import carpet.script.exception.InternalExpressionException; import carpet.script.value.BlockValue; import carpet.script.value.EntityValue; import carpet.script.value.ListValue; +import carpet.script.value.MapValue; import carpet.script.value.NumericValue; import carpet.script.value.StringValue; import carpet.script.value.Value; @@ -19,8 +20,10 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.command.arguments.ParticleArgumentType; import net.minecraft.entity.Entity; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.DoubleTag; import net.minecraft.nbt.FloatTag; import net.minecraft.nbt.IntTag; +import net.minecraft.nbt.ListTag; import net.minecraft.nbt.StringTag; import net.minecraft.nbt.Tag; import net.minecraft.particle.ParticleEffect; @@ -32,7 +35,9 @@ import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.util.registry.Registry; import net.minecraft.world.dimension.DimensionType; +import org.apache.commons.lang3.tuple.Pair; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -49,23 +54,90 @@ public class ShapeDispatcher { private static final Map particleCache = new HashMap<>(); - public static void sendShape(List players, ExpiringShape shape, Map params) + public static Pair> fromFunctionArgs( + CarpetContext cc, + List lv, + ServerPlayerEntity[] playerRef + ) { - Consumer alternative = null; - CompoundTag tag = null; + if (lv.size() < 3) throw new InternalExpressionException("'draw_shape' takes at least three parameters, shape name, duration, and its params"); + String shapeType = lv.get(0).getString(); + Value duration = NumericValue.asNumber(lv.get(1)); + Map params; + if (lv.size() == 3) + { + Value paramValue = lv.get(2); + if (paramValue instanceof MapValue) + { + params = new HashMap<>(); + ((MapValue) paramValue).getMap().entrySet().forEach(e -> params.put(e.getKey().getString(),e.getValue())); + } + else if (paramValue instanceof ListValue) + { + params = parseParams(((ListValue) paramValue).getItems()); + } + else throw new InternalExpressionException("Parameters for 'draw_shape' need to be defined either in a list or a map"); + } + else + { + List paramList = new ArrayList<>(); + for (int i=2; i < lv.size(); i++) paramList.add(lv.get(i)); + params = ShapeDispatcher.parseParams(paramList); + } + params.putIfAbsent("dim", new StringValue(cc.s.getWorld().getDimension().getType().toString())); + params.putIfAbsent("duration", duration); + + if (params.containsKey("player")) + { + ServerPlayerEntity player = EntityValue.getPlayerByValue(cc.s.getMinecraftServer(), params.get("player")); + if (player == null) + throw new InternalExpressionException("'player' parameter needs to represent an existing player"); + params.remove("player"); + playerRef[0] = player; + } + return Pair.of(ShapeDispatcher.create(cc, shapeType, params), params); + } + + public static void sendShape(List players, List>> shapes) + { + List clientPlayers = new ArrayList<>(); + List alternativePlayers = new ArrayList<>(); for (ServerPlayerEntity player : players) { if (ServerNetworkHandler.validCarpetPlayers.contains(player)) { - if (tag == null) tag = ExpiringShape.toTag(params); - ServerNetworkHandler.sendCustomCommand(player,"scShape", tag); + clientPlayers.add(player); } else { - if (alternative == null) alternative = shape.alternative(); - alternative.accept(player); + alternativePlayers.add(player); } } + if (!clientPlayers.isEmpty()) + { + + ListTag tag = new ListTag(); + int tagcount = 0; + for (Pair> s : shapes) + { + tag.add(ExpiringShape.toTag(s.getRight())); // 4000 shapes limit boxes + if (tagcount++>1000) + { + tagcount = 0; + Tag finalTag = tag; + clientPlayers.forEach( p -> ServerNetworkHandler.sendCustomCommand(p, "scShapes", finalTag)); + tag = new ListTag(); + } + } + Tag finalTag = tag; + if (tag.size() > 0) clientPlayers.forEach( p -> ServerNetworkHandler.sendCustomCommand(p, "scShapes", finalTag)); + } + if (!alternativePlayers.isEmpty()) + { + List> alternatives = new ArrayList<>(); + shapes.forEach(s -> alternatives.add(s.getLeft().alternative())); + alternativePlayers.forEach(p -> alternatives.forEach( a -> a.accept(p))); + } } public static ParticleEffect getParticleData(String name) @@ -174,7 +246,7 @@ public class ShapeDispatcher protected float fr, fg, fb, fa; protected int fillColor; protected int duration = 0; - private int key; + private long key; protected int followEntity; protected DimensionType entityDimension; @@ -214,7 +286,7 @@ public class ShapeDispatcher duration = NumericValue.asNumber(options.get("duration")).getInt(); - lineWidth = NumericValue.asNumber(options.getOrDefault("width", optional.get("width"))).getFloat(); + lineWidth = NumericValue.asNumber(options.getOrDefault("line", optional.get("line"))).getFloat(); fillColor = NumericValue.asNumber(options.getOrDefault("fill", optional.get("fill"))).getInt(); this.fr = (float)(fillColor >> 24 & 0xFF) / 255.0F; @@ -254,19 +326,19 @@ public class ShapeDispatcher } public abstract Consumer alternative(); - public int key() + public long key() { if (key!=0) return key; key = calcKey(); return key; } - protected int calcKey() - { - int hash = 17; - hash = 31*hash + color; - hash = 31*hash + followEntity; - hash = 31*hash + Float.hashCode(lineWidth); - if (fa != 0.0) hash = 31*hash + fillColor; + protected long calcKey() + { // using FNV-1a algorithm + long hash = -3750763034362895579L; + hash ^= color; hash *= 1099511628211L; + hash ^= followEntity; hash *= 1099511628211L; + hash ^= Float.hashCode(lineWidth); hash *= 1099511628211L; + if (fa != 0.0) { hash = 31*hash + fillColor; hash *= 1099511628211L; } return hash; } // list of params that need to be there @@ -274,7 +346,7 @@ public class ShapeDispatcher private final Map optional = ImmutableMap.of( "color", new NumericValue(-1), "follow", new NumericValue(-1), - "width", new NumericValue(2.0), + "line", new NumericValue(2.0), "fill", new NumericValue(0xffffff00) ); protected Set requiredParams() {return required;} @@ -306,6 +378,7 @@ public class ShapeDispatcher super.init(options); from = vecFromValue(options.get("from")); to = vecFromValue(options.get("to")); + if (from.equals(to)) throw new InternalExpressionException("Box dimensions are invalid - cannot draw a zero-size boxes"); } @Override @@ -330,12 +403,12 @@ public class ShapeDispatcher } @Override - public int calcKey() + public long calcKey() { - int hash = super.calcKey(); - hash = 31*hash + 1; - hash = 31*hash + from.hashCode(); - hash = 31*hash + to.hashCode(); + long hash = super.calcKey(); + hash ^= 1; hash *= 1099511628211L; + hash ^= from.hashCode(); hash *= 1099511628211L; + hash ^= to.hashCode(); hash *= 1099511628211L; return hash; } @@ -389,6 +462,7 @@ public class ShapeDispatcher super.init(options); from = vecFromValue(options.get("from")); to = vecFromValue(options.get("to")); + if (from.equals(to)) throw new InternalExpressionException("Line dimensions are invalid - cannot draw a zero-length lines"); } @Override @@ -414,12 +488,12 @@ public class ShapeDispatcher } @Override - public int calcKey() + public long calcKey() { - int hash = super.calcKey(); - hash = 31*hash + 2; - hash = 31*hash + from.hashCode(); - hash = 31*hash + to.hashCode(); + long hash = super.calcKey(); + hash ^= 2; hash *= 1099511628211L; + hash ^= from.hashCode(); hash *= 1099511628211L; + hash ^= to.hashCode(); hash *= 1099511628211L; return hash; } } @@ -494,13 +568,13 @@ public class ShapeDispatcher };} @Override - public int calcKey() + public long calcKey() { - int hash = super.calcKey(); - hash = 31*hash + 3; - hash = 31*hash + center.hashCode(); - hash = 31*hash + Double.hashCode(radius); - hash = 31*hash + level; + long hash = super.calcKey(); + hash ^= 3; hash *= 1099511628211L; + hash ^= center.hashCode(); hash *= 1099511628211L; + hash ^= Double.hashCode(radius); hash *= 1099511628211L; + hash ^= level; hash *= 1099511628211L; return hash; } } @@ -514,7 +588,7 @@ public class ShapeDispatcher put("duration", new PositiveIntParam("duration")); put("color", new ColorParam("color")); put("follow", new EntityParam("follow")); - put("width", new PositiveFloatParam("width")); + put("line", new PositiveFloatParam("line")); put("fill", new ColorParam("fill")); put("from", new Vec3Param("from", false)); @@ -522,6 +596,9 @@ public class ShapeDispatcher put("center", new Vec3Param("center", false)); put("radius", new PositiveFloatParam("radius")); put("level", new PositiveIntParam("level")); + put("height", new PositiveFloatParam("height")); + put("axis", new StringChoiceParam("axis", "x", "y", "z")); + put("points", new PointsParam("points")); }}; protected String id; protected Param(String id) @@ -543,6 +620,24 @@ public class ShapeDispatcher public Value decode(Tag tag) { return new StringValue(tag.asString()); } } + public static class StringChoiceParam extends StringParam + { + private Set options; + public StringChoiceParam(String id, String ... options) + { + super(id); + this.options = Sets.newHashSet(options); + } + + + @Override + public Value validate(Map options, CarpetContext cc, Value value) + { + if (this.options.contains(value.getString())) return value; + return null; + } + } + public static class DimensionParam extends StringParam { protected DimensionParam() { super("dim"); } @@ -620,13 +715,17 @@ public class ShapeDispatcher } @Override public Value validate(Map options, CarpetContext cc, Value value) + { + return validate(this, options, cc, value, roundsUpForBlocks); + } + public static Value validate(Param p, Map options, CarpetContext cc, Value value, boolean roundsUp) { if (value instanceof BlockValue) { if (options.containsKey("follow")) - throw new InternalExpressionException(id+" parameter cannot use blocks as positions for relative positioning due to 'follow' attribute being present"); + throw new InternalExpressionException(p.id+" parameter cannot use blocks as positions for relative positioning due to 'follow' attribute being present"); BlockPos pos = ((BlockValue) value).getPos(); - int offset = roundsUpForBlocks?1:0; + int offset = roundsUp?1:0; return ListValue.of( new NumericValue(pos.getX()+offset), new NumericValue(pos.getY()+offset), @@ -636,18 +735,18 @@ public class ShapeDispatcher if (value instanceof ListValue) { List values = ((ListValue) value).getItems(); - if (values.size()!=3) throw new InternalExpressionException("'"+id+"' requires 3 numerical values"); + if (values.size()!=3) throw new InternalExpressionException("'"+p.id+"' requires 3 numerical values"); for (Value component : values) { if (!(component instanceof NumericValue)) - throw new InternalExpressionException("'"+id+"' requires 3 numerical values"); + throw new InternalExpressionException("'"+p.id+"' requires 3 numerical values"); } return value; } if (value instanceof EntityValue) { if (options.containsKey("follow")) - throw new InternalExpressionException(id+" parameter cannot use entity as positions for relative positioning due to 'follow' attribute being present"); + throw new InternalExpressionException(p.id+" parameter cannot use entity as positions for relative positioning due to 'follow' attribute being present"); Entity e = ((EntityValue) value).getEntity(); return ListValue.of( new NumericValue(e.getX()), @@ -656,29 +755,81 @@ public class ShapeDispatcher ); } CarpetSettings.LOG.error("Value: "+value.getString()); - throw new InternalExpressionException("'"+id+"' requires a triple, block or entity to indicate position"); + throw new InternalExpressionException("'"+p.id+"' requires a triple, block or entity to indicate position"); } public Value decode(Tag tag) { - CompoundTag ctag = (CompoundTag)tag; + ListTag ctag = (ListTag)tag; return ListValue.of( - new NumericValue(ctag.getDouble("x")), - new NumericValue(ctag.getDouble("y")), - new NumericValue(ctag.getDouble("z")) + new NumericValue(ctag.getDouble(0)), + new NumericValue(ctag.getDouble(1)), + new NumericValue(ctag.getDouble(2)) ); } @Override public Tag toTag(Value value) { List lv = ((ListValue)value).getItems(); - CompoundTag tag = new CompoundTag(); - tag.putDouble("x", NumericValue.asNumber(lv.get(0)).getDouble()); - tag.putDouble("y", NumericValue.asNumber(lv.get(1)).getDouble()); - tag.putDouble("z", NumericValue.asNumber(lv.get(2)).getDouble()); + ListTag tag = new ListTag(); + tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(0)).getDouble())); + tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(1)).getDouble())); + tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(2)).getDouble())); return tag; } } + + public static class PointsParam extends Param + { + public PointsParam(String id) + { + super(id); + } + @Override + public Value validate(Map options, CarpetContext cc, Value value) + { + if (!(value instanceof ListValue)) + throw new InternalExpressionException(id+ " parameter should be a list"); + List points = new ArrayList<>(); + for (Value point: ((ListValue) value).getItems()) + points.add(Vec3Param.validate(this, options, cc, point, false)); + return ListValue.wrap(points); + } + + public Value decode(Tag tag) + { + ListTag ltag = (ListTag)tag; + List points = new ArrayList<>(); + for (int i=0, ll = ltag.size(); i lv = ((ListValue)pointsValue).getItems(); + ListTag ltag = new ListTag(); + for (Value value : lv) + { + List coords = ((ListValue)value).getItems(); + ListTag tag = new ListTag(); + tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(0)).getDouble())); + tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(1)).getDouble())); + tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(2)).getDouble())); + ltag.add(tag); + } + return ltag; + } + } + + public static class ColorParam extends NumericParam { protected ColorParam(String id) diff --git a/src/main/java/carpet/script/utils/ShapesRenderer.java b/src/main/java/carpet/script/utils/ShapesRenderer.java index e259a219..1819885b 100644 --- a/src/main/java/carpet/script/utils/ShapesRenderer.java +++ b/src/main/java/carpet/script/utils/ShapesRenderer.java @@ -2,15 +2,15 @@ package carpet.script.utils; import carpet.CarpetSettings; import com.mojang.blaze3d.systems.RenderSystem; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.BufferBuilder; +import net.minecraft.client.render.Camera; import net.minecraft.client.render.Tessellator; -import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexFormats; -import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.Entity; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; import net.minecraft.util.Identifier; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; @@ -25,7 +25,7 @@ import java.util.function.BiFunction; public class ShapesRenderer { - private final Map>> shapes; + private final Map>> shapes; private MinecraftClient client; private Map>> renderedShapes @@ -40,12 +40,12 @@ public class ShapesRenderer { this.client = minecraftClient; shapes = new HashMap<>(); - shapes.put(DimensionType.OVERWORLD, new Int2ObjectOpenHashMap<>()); - shapes.put(DimensionType.THE_NETHER, new Int2ObjectOpenHashMap<>()); - shapes.put(DimensionType.THE_END, new Int2ObjectOpenHashMap<>()); + shapes.put(DimensionType.OVERWORLD, new Long2ObjectOpenHashMap<>()); + shapes.put(DimensionType.THE_NETHER, new Long2ObjectOpenHashMap<>()); + shapes.put(DimensionType.THE_END, new Long2ObjectOpenHashMap<>()); } - public void render(MatrixStack matrices, VertexConsumerProvider vertexConsumers, double cameraX, double cameraY, double cameraZ) + public void render(Camera camera, float partialTick) { IWorld iWorld = this.client.world; DimensionType dimensionType = iWorld.getDimension().getType(); @@ -68,20 +68,25 @@ public class ShapesRenderer //RenderSystem.polygonOffset(-3f, -3f); //RenderSystem.enablePolygonOffset(); //Entity entity = this.client.gameRenderer.getCamera().getFocusedEntity(); + Tessellator tessellator = Tessellator.getInstance(); BufferBuilder bufferBuilder = tessellator.getBuffer(); // render + double cameraX = camera.getPos().x; + double cameraY = camera.getPos().y; + double cameraZ = camera.getPos().z; + synchronized (shapes) { - shapes.get(dimensionType).int2ObjectEntrySet().removeIf( + shapes.get(dimensionType).long2ObjectEntrySet().removeIf( entry -> entry.getValue().isExpired(currentTime) ); shapes.get(dimensionType).values().forEach( s -> { if ( s.shouldRender(dimensionType)) - s.renderFaces(tessellator, bufferBuilder, cameraX, cameraY, cameraZ); + s.renderFaces(tessellator, bufferBuilder, cameraX, cameraY, cameraZ, partialTick); } ); //lines @@ -89,7 +94,7 @@ public class ShapesRenderer s -> { if ( s.shouldRender(dimensionType)) - s.renderLines(tessellator, bufferBuilder, cameraX, cameraY, cameraZ); + s.renderLines(tessellator, bufferBuilder, cameraX, cameraY, cameraZ, partialTick); } ); } @@ -102,6 +107,14 @@ public class ShapesRenderer RenderSystem.shadeModel(7424); } + public void addShapes(ListTag tag) + { + for (int i=0, count = tag.size(); i < count; i++) + { + addShape(tag.getCompound(i)); + } + } + public void addShape(CompoundTag tag) { ShapeDispatcher.ExpiringShape shape = ShapeDispatcher.fromTag(tag); @@ -116,7 +129,7 @@ public class ShapesRenderer { RenderedShape rshape = shapeFactory.apply(client, shape); DimensionType dim = Registry.DIMENSION_TYPE.get(new Identifier(tag.getString("dim"))); - int key = rshape.key(); + long key = rshape.key(); synchronized (shapes) { RenderedShape existing = shapes.get(dim).get(key); @@ -135,7 +148,7 @@ public class ShapesRenderer { synchronized (shapes) { - shapes.values().forEach(Int2ObjectOpenHashMap::clear); + shapes.values().forEach(Long2ObjectOpenHashMap::clear); } } @@ -146,13 +159,13 @@ public class ShapesRenderer protected MinecraftClient client; long expiryTick; double renderEpsilon = 0; - public abstract void renderLines(Tessellator tessellator, BufferBuilder builder, double cx, double cy, double cz ); - public void renderFaces(Tessellator tessellator, BufferBuilder builder, double cx, double cy, double cz ) {} + public abstract void renderLines(Tessellator tessellator, BufferBuilder builder, double cx, double cy, double cz, float partialTick ); + public void renderFaces(Tessellator tessellator, BufferBuilder builder, double cx, double cy, double cz, float partialTick ) {} protected RenderedShape(MinecraftClient client, T shape) { this.shape = shape; expiryTick = client.world.getTime()+shape.getExpiry(); - renderEpsilon = (2+((double)shape.key())/Integer.MAX_VALUE)/1000; + renderEpsilon = (3+((double)shape.key())/Long.MAX_VALUE)/1000; this.client = client; } @@ -160,7 +173,7 @@ public class ShapesRenderer { return expiryTick < currentTick; } - public int key() + public long key() { return shape.key(); }; @@ -172,11 +185,15 @@ public class ShapesRenderer if (client.world.getEntityById(shape.followEntity) == null) return false; return true; } - protected Vec3d relativiseRender(Vec3d vec) + protected Vec3d relativiseRender(Vec3d vec, float partialTick) { if (shape.followEntity <= 0) return vec; Entity e = client.world.getEntityById(shape.followEntity); - return shape.toAbsolute(e, vec); + return vec.add( + MathHelper.lerp(partialTick, e.prevX, e.getX()), + MathHelper.lerp(partialTick, e.prevY, e.getY()), + MathHelper.lerp(partialTick, e.prevZ, e.getZ()) + ); } } @@ -189,28 +206,30 @@ public class ShapesRenderer } @Override - public void renderLines(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz) + public void renderLines(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick) { if (shape.a == 0.0) return; - Vec3d v1 = relativiseRender(shape.from); - Vec3d v2 = relativiseRender(shape.to); + Vec3d v1 = relativiseRender(shape.from, partialTick); + Vec3d v2 = relativiseRender(shape.to, partialTick); RenderSystem.lineWidth(shape.lineWidth); drawBoxWireGLLines(tessellator, bufferBuilder, (float)(v1.x-cx-renderEpsilon), (float)(v1.y-cy-renderEpsilon), (float)(v1.z-cz-renderEpsilon), (float)(v2.x-cx+renderEpsilon), (float)(v2.y-cy+renderEpsilon), (float)(v2.z-cz+renderEpsilon), + v1.x!=v2.x, v1.y!=v2.y, v1.z!=v2.z, shape.r, shape.g, shape.b, shape.a, shape.r, shape.g, shape.b ); } @Override - public void renderFaces(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz) + public void renderFaces(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick) { if (shape.fa == 0.0) return; - Vec3d v1 = relativiseRender(shape.from); - Vec3d v2 = relativiseRender(shape.to); + Vec3d v1 = relativiseRender(shape.from, partialTick); + Vec3d v2 = relativiseRender(shape.to, partialTick); RenderSystem.lineWidth(1.0F); drawBoxFaces(tessellator, bufferBuilder, (float)(v1.x-cx-renderEpsilon), (float)(v1.y-cy-renderEpsilon), (float)(v1.z-cz-renderEpsilon), (float)(v2.x-cx+renderEpsilon), (float)(v2.y-cy+renderEpsilon), (float)(v2.z-cz+renderEpsilon), + v1.x!=v2.x, v1.y!=v2.y, v1.z!=v2.z, shape.fr, shape.fg, shape.fb, shape.fa ); } @@ -224,10 +243,10 @@ public class ShapesRenderer super(client, (ShapeDispatcher.Line)shape); } @Override - public void renderLines(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz) + public void renderLines(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick) { - Vec3d v1 = relativiseRender(shape.from); - Vec3d v2 = relativiseRender(shape.to); + Vec3d v1 = relativiseRender(shape.from, partialTick); + Vec3d v2 = relativiseRender(shape.to, partialTick); RenderSystem.lineWidth(shape.lineWidth); drawLine(tessellator, bufferBuilder, (float)(v1.x-cx-renderEpsilon), (float)(v1.y-cy-renderEpsilon), (float)(v1.z-cz-renderEpsilon), @@ -244,10 +263,10 @@ public class ShapesRenderer super(client, (ShapeDispatcher.Sphere)shape); } @Override - public void renderLines(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz) + public void renderLines(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick) { if (shape.a == 0.0) return; - Vec3d vc = relativiseRender(shape.center); + Vec3d vc = relativiseRender(shape.center, partialTick); RenderSystem.lineWidth(shape.lineWidth); drawSphereWireframe(tessellator, bufferBuilder, (float)(vc.x-cx-renderEpsilon), (float)(vc.y-cy-renderEpsilon), (float)(vc.z-cz-renderEpsilon), @@ -255,10 +274,10 @@ public class ShapesRenderer shape.r, shape.g, shape.b, shape.a); } @Override - public void renderFaces(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz) + public void renderFaces(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick) { if (shape.fa == 0.0) return; - Vec3d vc = relativiseRender(shape.center); + Vec3d vc = relativiseRender(shape.center, partialTick); RenderSystem.lineWidth(1.0f); drawSphereFaces(tessellator, bufferBuilder, (float)(vc.x-cx-renderEpsilon), (float)(vc.y-cy-renderEpsilon), (float)(vc.z-cz-renderEpsilon), @@ -276,68 +295,117 @@ public class ShapesRenderer tessellator.draw(); } - public static void drawBoxWireGLLines(Tessellator tessellator, BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha, float red2, float grn2, float blu2) + public static void drawBoxWireGLLines( + Tessellator tessellator, BufferBuilder builder, + float x1, float y1, float z1, + float x2, float y2, float z2, + boolean xthick, boolean ythick, boolean zthick, + float red1, float grn1, float blu1, float alpha, float red2, float grn2, float blu2) { builder.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR); // 3 - builder.vertex(x1, y1, z1).color(red1, grn2, blu2, alpha).next(); - builder.vertex(x2, y1, z1).color(red1, grn2, blu2, alpha).next(); - builder.vertex(x1, y1, z1).color(red2, grn1, blu2, alpha).next(); - builder.vertex(x1, y2, z1).color(red2, grn1, blu2, alpha).next(); - builder.vertex(x1, y1, z1).color(red2, grn2, blu1, alpha).next(); - builder.vertex(x1, y1, z2).color(red2, grn2, blu1, alpha).next(); - builder.vertex(x2, y1, z1).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x1, y2, z1).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x1, y2, z1).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x1, y2, z2).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x1, y2, z2).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x1, y1, z2).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x1, y1, z2).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x2, y1, z2).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x2, y1, z2).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x2, y1, z1).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x1, y2, z2).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x2, y1, z2).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); + if (xthick) + { + builder.vertex(x1, y1, z1).color(red1, grn2, blu2, alpha).next(); + builder.vertex(x2, y1, z1).color(red1, grn2, blu2, alpha).next(); + + builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x1, y2, z1).color(red1, grn1, blu1, alpha).next(); + + builder.vertex(x1, y1, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y1, z2).color(red1, grn1, blu1, alpha).next(); + + builder.vertex(x1, y2, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); + } + if (ythick) + { + builder.vertex(x1, y1, z1).color(red2, grn1, blu2, alpha).next(); + builder.vertex(x1, y2, z1).color(red2, grn1, blu2, alpha).next(); + + builder.vertex(x2, y1, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); + + builder.vertex(x1, y2, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x1, y1, z2).color(red1, grn1, blu1, alpha).next(); + + builder.vertex(x2, y1, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); + } + if (zthick) + { + builder.vertex(x1, y1, z1).color(red2, grn2, blu1, alpha).next(); + builder.vertex(x1, y1, z2).color(red2, grn2, blu1, alpha).next(); + + builder.vertex(x1, y2, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x1, y2, z2).color(red1, grn1, blu1, alpha).next(); + + builder.vertex(x2, y1, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y1, z1).color(red1, grn1, blu1, alpha).next(); + + builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); + } tessellator.draw(); } - public static void drawBoxFaces(Tessellator tessellator, BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha) + public static void drawBoxFaces( + Tessellator tessellator, BufferBuilder builder, + float x1, float y1, float z1, + float x2, float y2, float z2, + boolean xthick, boolean ythick, boolean zthick, + float red1, float grn1, float blu1, float alpha) { builder.begin(GL11.GL_QUADS, VertexFormats.POSITION_COLOR); - builder.vertex(x1, y1, z1).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x2, y1, z1).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x1, y2, z1).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x1, y1, z2).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x1, y2, z2).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x2, y1, z2).color(red1, grn1, blu1, alpha).next(); + if (xthick && ythick) + { + builder.vertex(x1, y1, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y1, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x1, y2, z1).color(red1, grn1, blu1, alpha).next(); + if (zthick) + { + builder.vertex(x1, y1, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x1, y2, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y1, z2).color(red1, grn1, blu1, alpha).next(); + } + } - builder.vertex(x1, y1, z1).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x1, y2, z1).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x1, y2, z2).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x1, y1, z2).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x2, y1, z1).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x2, y1, z2).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); + if (zthick && ythick) + { + builder.vertex(x1, y1, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x1, y2, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x1, y2, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x1, y1, z2).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x1, y1, z1).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x1, y1, z2).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x2, y1, z2).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x2, y1, z1).color(red1, grn1, blu1, alpha).next(); + if (xthick) + { + builder.vertex(x2, y1, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y1, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); + } + } - builder.vertex(x1, y2, z1).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); - builder.vertex(x1, y2, z2).color(red1, grn1, blu1, alpha).next(); + // now at least drawing one + if (zthick && xthick) + { + builder.vertex(x1, y1, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y1, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y1, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x1, y1, z2).color(red1, grn1, blu1, alpha).next(); + + + if (ythick) + { + builder.vertex(x1, y2, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); + builder.vertex(x1, y2, z2).color(red1, grn1, blu1, alpha).next(); + } + } tessellator.draw(); } diff --git a/src/main/resources/assets/carpet/scripts/chunk_display.sc b/src/main/resources/assets/carpet/scripts/chunk_display.sc new file mode 100644 index 00000000..1a9edf21 --- /dev/null +++ b/src/main/resources/assets/carpet/scripts/chunk_display.sc @@ -0,0 +1,181 @@ +global_chunk_colors = m( + // loaded ticking + l(3, l(0xBBFF0000, 0x88bb0000)), // lime, green + l(2, l(0xFF000000, 0x88000000)), // red + l(1, l(0xFFFF0000, 0xbbbb0000)), // yellow + // 'unloaded' (in memory, so rather 'inaccessible') + l(0, l(0xcccccc00, 0x11111100)), // gray / hi constast + // stable full generation (for '0's, all 1,2,3 are always 'full') + l('full', l(0xbbbbbb00, 0x88888800)), // gray + // unstable final bits + l('heightmaps', l(0xFFFFFF00, 0x00000000)), // check + l('spawn', l(0xFFFFFF00, 0x00000000)), // check + l('light_gen', l(0xFFFFFF00, 0x00000000)), // check + // stable features + l('features', l(0x88bb2200, 0x66882200)), // green muddled + //stable terrain + l('liquid_carvers', l(0x65432100, 0x54321000)), // browns + //unstable terrain - not generated yet + l('carvers', l(0xFFFFFF00, 0x00000000)), // check + l('surface', l(0xFFFFFF00, 0x00000000)), // check + l('noise', l(0xFFFFFF00, 0x00000000)), // check + l('biomes', l(0xFFFFFF00, 0x00000000)), // check + l('structure_references', l(0xFFFFFF00, 0x00000000)), // check + // stable + l('structure_starts', l(0x66666600, 0x22222200)), // darkgrey + // not stated yet + l('empty', l(0xFF88888800, 0xDD444400)), // pink + // proper not in memory + l(null , l(0xFFFFFF00, 0xFFFFFF00)), // hwite + + // ticket types + l('player', l(0x0000DD00, 0x00008800)), // blue + l('portal', l(0xAA00AA00, 0xAA00AA00)), // purple + l('dragon', l(0xAA008800, 0xAA008800)), // purple + l('forced', l(0xAABBFF00, 0x8899AA00)), // blue + l('light', l(0xFFFF0000, 0xBBBB0000)), // yellow + l('post_teleport', l(0xAA00AA00, 0xAA00AA00)), // purple + l('start', l(0xDDFF0000, 0xDDFF0000)), // lime, green + // recent chunk requests + l('unknown', l(0xFFFFFF00, 0x00000000)) // check +); + +// map representing current displayed chunkloading setup +global_current_setup = null; + +// which blocks in the inventory represent which dimension +global_block_markers = m( + l('netherrack', 'the_nether'), + l('grass_block', 'overworld'), + l('end_stone', 'the_end') +); + +__on_player_uses_item(player, item_tuple, hand) -> +( + if (hand != 'mainhand', return()); + if (!has(global_block_markers, item_tuple:0), return()); + if (item_tuple:1%16 != 0, return()); + new_setup = true; + if (global_current_setup, + new_setup = __remove_previous_setup(player) + ); + if (!new_setup, return()); + tag = nbt('{}'); + put(tag:'Enchantments','[]'); + put(tag:'Enchantments', '{lvl:1s,id:"minecraft:protection"}', 0); + inventory_set(player, player~'selected_slot', item_tuple:1, item_tuple:0, tag); + __setup_tracker(player, item_tuple); +); + +//__on_tick() -> null; + +__remove_previous_setup(new_player) -> +( + if (!global_current_setup, return()); + global_running = false; + p = player(); + if (p && + global_block_markers:((item = inventory_get(p, global_current_setup:'inventory_slot')):0)==global_current_setup:'source_dimension' && + item:1 == global_current_setup:'radius' && + item:2, + inventory_set(p, global_current_setup:'inventory_slot', item:1, item:0, null); // disenchant + if( new_player == p && new_player~'selected_slot' == global_current_setup:'inventory_slot', + disabled = true + ); + ); + global_current_setup = null; + !disabled +); + +__setup_tracker(player, item) -> +( + setup = m(); + setup:'player_name' = str(player); + setup:'inventory_slot' = player ~ 'selected_slot'; + setup:'plot_dimension' = player ~ 'dimension'; + setup:'plot_center' = map(pos(player), floor(_))-l(0,1,0); + setup:'radius' = item:1; + setup:'source_dimension' = global_block_markers:(item:0); + multiplier = 1; + if (setup:'source_dimension' != setup:'plot_dimension', + multiplier = if ( + setup:'source_dimension' == 'the_nether', 1/8, + setup:'source_dimension' == 'the_end', 0, + 8); + ); + setup:'source_center' = setup:'plot_center' * multiplier; + print(setup:'source_dimension'+' around '+setup:'source_center'+' with '+setup:'radius'+' radius ('+ (2*setup:'radius'+1)^2 +' chunks)'); + + l(sx, sy, sz) = setup:'source_center'; + global_status_cache = m(); + loop( 2*setup:'radius'+1, dx = _ - setup:'radius'; + loop( 2*setup:'radius'+1, dz = _ - setup:'radius'; + source_pos = l(sx+16*dx,sy,sz+16*dz); + global_status_cache:source_pos = null + ) + ); + global_current_setup = setup; + global_running = true; + schedule(0, '__chunk_visualizer_tick', player); +); + +global_status_cache = m(); + +__chunk_visualizer_tick(p) -> +( + setup = global_current_setup; + if(!setup, return()); + if (!global_running, return()); + show_activity = (p~'holds':0 == 'redstone_torch'); + in_dimension( setup:'plot_dimension', + l(sx, sy, sz) = setup:'source_center'; + l(px, py, pz) = setup:'plot_center'; + source_center = setup:'source_center'; + radius = setup:'radius'; + source_dimension = setup:'source_dimension'; + + shapes = l(); + + loop( 2*radius+1, dx = _ - radius; + loop( 2*radius+1, dz = _ - radius; + changed = false; + source_pos = l(sx+16*dx,sy,sz+16*dz); + status = in_dimension( source_dimension, + loaded_status = loaded_status(source_pos); + if (loaded_status > 0, loaded_status, generation_status(source_pos)) + ); + // will mix with light ticket + if (status=='light', status = 'light_gen'); + + if ( status != global_status_cache:source_pos, + global_status_cache:source_pos = status; + changed = true; + ); + if (loaded_status > 0, + tickets = in_dimension( source_dimension, chunk_tickets(source_pos)); + for(tickets, + l(type, level) = _; + if (show_activity || type != 'unknown', + global_status_cache:source_pos = type; + changed = true; + ); + ); + ); + //if (changed, + //to = global_status_cache:source_pos; + //if(!has(global_chunk_colors:to), print('problem with '+to)); + //set(px+dx,py,pz+dz, global_chunk_colors:to:((dx+dz)%2)); + //set(px+dx,py,pz+dz, global_chunk_colors:(global_status_cache:source_pos):((dx+dz)%2)); + //bpos = l(px+dx/2, py, pz+dz/2); + bpos = l(dx/2, -10, dz/2); + bcol = global_chunk_colors:(global_status_cache:source_pos):((dx+dz)%2); + shapes += l('box', 10, 'from', bpos, 'to', bpos + l(0.5,0,0.5), 'color', bcol, 'fill', bcol+128, + 'follow', p) + ; + //); + ); + ); + draw_shape(shapes); + ); + schedule(5, '__chunk_visualizer_tick', p) +) \ No newline at end of file diff --git a/src/main/resources/assets/carpet/scripts/overlay.sc b/src/main/resources/assets/carpet/scripts/overlay.sc index 81b42749..8038b9d3 100644 --- a/src/main/resources/assets/carpet/scripts/overlay.sc +++ b/src/main/resources/assets/carpet/scripts/overlay.sc @@ -94,7 +94,7 @@ __structure_renderer(player_name) -> l(from, to) = structure_data; total_size = _euclidean(from, to); density = max(10, total_size/10); - draw_shape('box', 15, 'from', from, 'to', to+1, 'color', 0x00FFFFFF, 'width', 3, 'fill', 0x00FFFF22); + draw_shape('box', 15, 'from', from, 'to', to+1, 'color', 0x00FFFFFF, 'line', 3, 'fill', 0x00FFFF22); structure_pieces = slice(sort_key(structure_pieces, _euclidean_sq((_:2+_:3)/2,ppos)), 0, config:'max_pieces'); for (structure_pieces, l(piece, direction, from, to) = _; r = 255 - floor(128 * _i/config:'max_pieces'); @@ -133,12 +133,14 @@ __chunk_renderer(player_name) -> b = 30; a = max(0, 255-player_distance); color = a+256*(b+256*(g+256*r)); - draw_shape('line', 15, 'from', top_00, 'to', top_10, 'color', color, 'width', 3); - draw_shape('line', 15, 'from', top_10, 'to', top_11, 'color', color, 'width', 3); - draw_shape('line', 15, 'from', top_11, 'to', top_01, 'color', color, 'width', 3); - draw_shape('line', 15, 'from', top_01, 'to', top_00, 'color', color, 'width', 3); - draw_shape('line', 15, 'from', top_00, 'to', top_11, 'color', color, 'width', 3); - draw_shape('line', 15, 'from', top_01, 'to', top_10, 'color', color, 'width', 3); + draw_shape(l( + l('line', 15, 'from', top_00, 'to', top_10, 'color', color, 'line', 3), + l('line', 15, 'from', top_10, 'to', top_11, 'color', color, 'line', 3), + l('line', 15, 'from', top_11, 'to', top_01, 'color', color, 'line', 3), + l('line', 15, 'from', top_01, 'to', top_00, 'color', color, 'line', 3), + l('line', 15, 'from', top_00, 'to', top_11, 'color', color, 'line', 3), + l('line', 15, 'from', top_01, 'to', top_10, 'color', color, 'line', 3) + )); ) ) ) diff --git a/src/main/resources/carpet.mixins.json b/src/main/resources/carpet.mixins.json index 65ec4c40..db91b5fe 100644 --- a/src/main/resources/carpet.mixins.json +++ b/src/main/resources/carpet.mixins.json @@ -182,7 +182,8 @@ "WorldRenderer_fogOffMixin", "WorldRenderer_creativeNoClipMixin", "ClientPlayNetworkHandlerMixin", - "DebugRenderer_scarpetRenderMixin" + "DebugRenderer_scarpetRenderMixin", + "WorldRenderer_scarpetRenderMixin" ], "server": [ "MinecraftDedicatedServerMixin" From d7e4b49d56f0e04e9b9ae21c8389882f9891c2be Mon Sep 17 00:00:00 2001 From: gnembon Date: Tue, 9 Jun 2020 02:58:44 -0300 Subject: [PATCH 187/198] chunk display fixes --- .../assets/carpet/scripts/chunk_display.sc | 63 ++++++++++--------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/src/main/resources/assets/carpet/scripts/chunk_display.sc b/src/main/resources/assets/carpet/scripts/chunk_display.sc index 1a9edf21..7f770b0a 100644 --- a/src/main/resources/assets/carpet/scripts/chunk_display.sc +++ b/src/main/resources/assets/carpet/scripts/chunk_display.sc @@ -1,30 +1,30 @@ global_chunk_colors = m( // loaded ticking - l(3, l(0xBBFF0000, 0x88bb0000)), // lime, green + l(3, l(0xAAdd0000, 0x66990000)), // lime, green l(2, l(0xFF000000, 0x88000000)), // red - l(1, l(0xFFFF0000, 0xbbbb0000)), // yellow + l(1, l(0xFFcc0000, 0xbbaa0000)), // yellowish // 'unloaded' (in memory, so rather 'inaccessible') l(0, l(0xcccccc00, 0x11111100)), // gray / hi constast // stable full generation (for '0's, all 1,2,3 are always 'full') l('full', l(0xbbbbbb00, 0x88888800)), // gray // unstable final bits - l('heightmaps', l(0xFFFFFF00, 0x00000000)), // check - l('spawn', l(0xFFFFFF00, 0x00000000)), // check - l('light_gen', l(0xFFFFFF00, 0x00000000)), // check + l('heightmaps', l(0xFFFFFF00, 0x00000000)), // checker + l('spawn', l(0xFFFFFF00, 0x00000000)), // checker + l('light_gen', l(0xFFFFFF00, 0x00000000)), // checker // stable features l('features', l(0x88bb2200, 0x66882200)), // green muddled //stable terrain l('liquid_carvers', l(0x65432100, 0x54321000)), // browns //unstable terrain - not generated yet - l('carvers', l(0xFFFFFF00, 0x00000000)), // check - l('surface', l(0xFFFFFF00, 0x00000000)), // check - l('noise', l(0xFFFFFF00, 0x00000000)), // check - l('biomes', l(0xFFFFFF00, 0x00000000)), // check - l('structure_references', l(0xFFFFFF00, 0x00000000)), // check + l('carvers', l(0xFFFFFF00, 0x00000000)), // checker + l('surface', l(0xFFFFFF00, 0x00000000)), // checker + l('noise', l(0xFFFFFF00, 0x00000000)), // checker + l('biomes', l(0xFFFFFF00, 0x00000000)), // checker + l('structure_references', l(0xFFFFFF00, 0x00000000)), // checker // stable l('structure_starts', l(0x66666600, 0x22222200)), // darkgrey // not stated yet - l('empty', l(0xFF88888800, 0xDD444400)), // pink + l('empty', l(0xFF888800, 0xDD444400)), // pink // proper not in memory l(null , l(0xFFFFFF00, 0xFFFFFF00)), // hwite @@ -111,7 +111,7 @@ __setup_tracker(player, item) -> loop( 2*setup:'radius'+1, dx = _ - setup:'radius'; loop( 2*setup:'radius'+1, dz = _ - setup:'radius'; source_pos = l(sx+16*dx,sy,sz+16*dz); - global_status_cache:source_pos = null + global_status_cache:source_pos = l(null, 0); ) ); global_current_setup = setup; @@ -135,6 +135,7 @@ __chunk_visualizer_tick(p) -> source_dimension = setup:'source_dimension'; shapes = l(); + now = tick_time(); loop( 2*radius+1, dx = _ - radius; loop( 2*radius+1, dz = _ - radius; @@ -147,35 +148,35 @@ __chunk_visualizer_tick(p) -> // will mix with light ticket if (status=='light', status = 'light_gen'); - if ( status != global_status_cache:source_pos, - global_status_cache:source_pos = status; - changed = true; - ); + if (loaded_status > 0, tickets = in_dimension( source_dimension, chunk_tickets(source_pos)); for(tickets, l(type, level) = _; if (show_activity || type != 'unknown', - global_status_cache:source_pos = type; - changed = true; + //global_status_cache:source_pos = type; + //changed = true; + status = type; ); ); ); - //if (changed, - //to = global_status_cache:source_pos; - //if(!has(global_chunk_colors:to), print('problem with '+to)); - //set(px+dx,py,pz+dz, global_chunk_colors:to:((dx+dz)%2)); - //set(px+dx,py,pz+dz, global_chunk_colors:(global_status_cache:source_pos):((dx+dz)%2)); - //bpos = l(px+dx/2, py, pz+dz/2); - bpos = l(dx/2, -10, dz/2); - bcol = global_chunk_colors:(global_status_cache:source_pos):((dx+dz)%2); - shapes += l('box', 10, 'from', bpos, 'to', bpos + l(0.5,0,0.5), 'color', bcol, 'fill', bcol+128, - 'follow', p) - ; - //); + l(cached_status, expiry) = global_status_cache:source_pos; + changed = (status != cached_status); + if ( changed || (expiry < now), + global_status_cache:source_pos = l(status, now+100+floor(rand(20))); + bpos = l(dx/2, 10, dz/2); + bcol = global_chunk_colors:status:((dx+dz)%2); + shapes += l('box', 150, 'from', bpos, 'to', bpos + l(0.5,0,0.5), + 'color', 0xffffff00, 'fill', bcol+128, 'follow', p); + if (changed, + pbcol = global_chunk_colors:cached_status:((dx+dz)%2); + shapes += l('box', 0, 'from', bpos, 'to', bpos + l(0.5,0,0.5), + 'color', 0xffffff00, 'fill', pbcol+128, 'follow', p); + ); + ); ); ); draw_shape(shapes); ); - schedule(5, '__chunk_visualizer_tick', p) + schedule(1, '__chunk_visualizer_tick', p) ) \ No newline at end of file From f5868b24e29bc773e1f8b2f7e564505bddc7d349 Mon Sep 17 00:00:00 2001 From: gnembon Date: Tue, 9 Jun 2020 02:59:53 -0300 Subject: [PATCH 188/198] Duration can be sent as 0 --- .../carpet/script/utils/ShapeDispatcher.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/carpet/script/utils/ShapeDispatcher.java b/src/main/java/carpet/script/utils/ShapeDispatcher.java index 770d7639..6215fe99 100644 --- a/src/main/java/carpet/script/utils/ShapeDispatcher.java +++ b/src/main/java/carpet/script/utils/ShapeDispatcher.java @@ -585,7 +585,7 @@ public class ShapeDispatcher public static Map of = new HashMap(){{ put("shape", new ShapeParam()); put("dim", new DimensionParam()); - put("duration", new PositiveIntParam("duration")); + put("duration", new NonNegativeIntParam("duration")); put("color", new ColorParam("color")); put("follow", new EntityParam("follow")); put("line", new PositiveFloatParam("line")); @@ -704,6 +704,20 @@ public class ShapeDispatcher public Tag toTag(Value value) { return IntTag.of(NumericValue.asNumber(value).getInt()); } } + public static class NonNegativeIntParam extends NumericParam + { + protected NonNegativeIntParam(String id) { super(id); } + @Override + public Value decode(Tag tag) { return new NumericValue(((IntTag)tag).getInt()); } + @Override + public Tag toTag(Value value) { return IntTag.of(NumericValue.asNumber(value).getInt()); } + @Override public Value validate(Map options, CarpetContext cc, Value value) + { + Value ret = super.validate(options, cc, value); + if (((NumericValue)ret).getDouble()<0) throw new InternalExpressionException("'"+id+"' should be non-negative"); + return ret; + } + } public static class Vec3Param extends Param { From eb2e6921c13d9f95e36f031d2035fff8bc4e1b33 Mon Sep 17 00:00:00 2001 From: gnembon Date: Tue, 9 Jun 2020 12:27:41 -0300 Subject: [PATCH 189/198] docs --- docs/scarpet/api/Entities.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/scarpet/api/Entities.md b/docs/scarpet/api/Entities.md index 36365a78..7d8f831f 100644 --- a/docs/scarpet/api/Entities.md +++ b/docs/scarpet/api/Entities.md @@ -473,7 +473,8 @@ players, since they are controlled client side. ### `modify(e, 'effect', name, duration?, amplifier?, show_particles?, show_icon?)` Applies status effect to the living entity. Takes several optional parameters, which default to `0`, `true` -and `true`. If no duration is specified, or if it's null or 0, the effect is removed. +and `true`. If no duration is specified, or if it's null or 0, the effect is removed. If the effect name is specified +as `null` that clears all effects. ### `modify(e, 'home', null), modify(e, 'home', block, distance?), modify(e, 'home', x, y, z, distance?)` From 0ea463bbedf323eab87dd5e192c5973a056f5962 Mon Sep 17 00:00:00 2001 From: gnembon Date: Tue, 9 Jun 2020 12:34:03 -0300 Subject: [PATCH 190/198] docs --- docs/scarpet/api/Entities.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/scarpet/api/Entities.md b/docs/scarpet/api/Entities.md index fc80dcb6..a0524460 100644 --- a/docs/scarpet/api/Entities.md +++ b/docs/scarpet/api/Entities.md @@ -477,11 +477,11 @@ If called with `false` value, it will disable AI in the mob. `true` will enable Sets if the entity obeys any collisions, including collisions with the terrain and basic physics. Not affecting players, since they are controlled client side. -### `modify(e, 'effect', name, duration?, amplifier?, show_particles?, show_icon?)` +### `modify(e, 'effect', name?, duration?, amplifier?, show_particles?, show_icon?)` Applies status effect to the living entity. Takes several optional parameters, which default to `0`, `true` -and `true`. If no duration is specified, or if it's null or 0, the effect is removed. If the effect name is specified -as `null` that clears all effects. +and `true`. If no duration is specified, or if it's null or 0, the effect is removed. If name is not specified, +it clears all effects. ### `modify(e, 'home', null), modify(e, 'home', block, distance?), modify(e, 'home', x, y, z, distance?)` From 58862fca11a8bb415b6166bdfb94faf0befca9ae Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 10 Jun 2020 01:25:51 -0300 Subject: [PATCH 191/198] added snap to shape added bulk shape rendering --- docs/scarpet/api/Auxiliary.md | 13 +- .../carpet/script/CarpetScriptServer.java | 1 + .../carpet/script/utils/ShapeDispatcher.java | 232 ++++++++++++++---- .../carpet/script/utils/ShapesRenderer.java | 148 +++++++++-- .../carpet/script/value/NumericValue.java | 7 + .../assets/carpet/scripts/chunk_display.sc | 31 ++- 6 files changed, 341 insertions(+), 91 deletions(-) diff --git a/docs/scarpet/api/Auxiliary.md b/docs/scarpet/api/Auxiliary.md index d4de9940..8cb0c117 100644 --- a/docs/scarpet/api/Auxiliary.md +++ b/docs/scarpet/api/Auxiliary.md @@ -36,7 +36,10 @@ supplied, only that player will receive particles. ## Markers -### `draw_shape(shape, duration, key?, value?, ... )`, `draw_shape(shape, duration, l(key?, value?, ... ))`, `draw_shape(shape, duration, attribute_map)` +### `draw_shape(shape, duration, key?, value?, ... )`, +### `draw_shape(shape, duration, l(key?, value?, ... ))`, +### `draw_shape(shape, duration, attribute_map)` +### `draw_shape(shape_list)` Draws a shape in the world that will expire in `duration` ticks. Other attributes of the shape should be provided as consecutive key - value argument pairs, either as next arguments, or packed in a list, or supplied as a proper key-value @@ -47,6 +50,10 @@ are not required to follow all attributes precisely, but will allow vanilla clie apps. One of the attributes that will definitely not be honored is the duration - particles will be send once per shape and last whatever they typically last in the game. +Shapes can be send one by one, using either of the first three invocations, or batched as a list of shape descriptors. +Batching has this benefit that they will be send possibly as one packet, limiting network overhead of +sending many small packets to draw several shapes at once. + Shapes will fail to draw and raise a runtime error if not all its required parameters are specified and all available shapes have some parameters that are required, so make sure to have them in place: @@ -65,6 +72,10 @@ Optional shared shape attributes: * `follow` - entity, or player name. Shape will follow an entity instead of being static. Follow attribute requires all positional arguments to be relative to the entity and disallow of using entity or block as position markers. You must specify positions as a triple. + * `snap` - if `follow` is present, indicated on which axis the snapping to entity coordinates occurs, and which axis + will be treated statically, i.e. the coordinate passed in a coord triple is the actual value in the world. Default + value is `'xyz'`, meaning the shape will be drawn relatively to the entity in all three directions. Using `xz` for + instance makes so that the shape follows the entity, but stays at the same, absolute Y coordinate. Available shapes: * `'line'` - draws a straight line between two points diff --git a/src/main/java/carpet/script/CarpetScriptServer.java b/src/main/java/carpet/script/CarpetScriptServer.java index a65a7655..2f0e627d 100644 --- a/src/main/java/carpet/script/CarpetScriptServer.java +++ b/src/main/java/carpet/script/CarpetScriptServer.java @@ -49,6 +49,7 @@ public class CarpetScriptServer add(new BundledModule("event_test", false)); add(new BundledModule("stats_test", false)); add(new BundledModule("math", true)); + add(new BundledModule("chunk_display", false)); }}; public CarpetScriptServer(MinecraftServer server) diff --git a/src/main/java/carpet/script/utils/ShapeDispatcher.java b/src/main/java/carpet/script/utils/ShapeDispatcher.java index 6215fe99..9007d675 100644 --- a/src/main/java/carpet/script/utils/ShapeDispatcher.java +++ b/src/main/java/carpet/script/utils/ShapeDispatcher.java @@ -31,9 +31,11 @@ import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.util.registry.Registry; +import net.minecraft.world.World; import net.minecraft.world.dimension.DimensionType; import org.apache.commons.lang3.tuple.Pair; @@ -62,7 +64,7 @@ public class ShapeDispatcher { if (lv.size() < 3) throw new InternalExpressionException("'draw_shape' takes at least three parameters, shape name, duration, and its params"); String shapeType = lv.get(0).getString(); - Value duration = NumericValue.asNumber(lv.get(1)); + Value duration = NumericValue.asNumber(lv.get(1), "duration"); Map params; if (lv.size() == 3) { @@ -230,6 +232,7 @@ public class ShapeDispatcher put("line", creator(Line::new)); put("box", creator(Box::new)); put("sphere", creator(Sphere::new)); + put("cylinder", creator(Cylinder::new)); }}; private static Function,ExpiringShape> creator(Supplier shapeFactory) { @@ -248,7 +251,9 @@ public class ShapeDispatcher protected int duration = 0; private long key; protected int followEntity; - protected DimensionType entityDimension; + protected String snapTo; + protected boolean snapX, snapY, snapZ; + public DimensionType shapeDimension; protected ExpiringShape() { } @@ -302,18 +307,33 @@ public class ShapeDispatcher key = 0; followEntity = -1; - entityDimension = null; + shapeDimension = Registry.DIMENSION_TYPE.get(new Identifier(options.get("dim").getString())); if (options.containsKey("follow")) { followEntity = NumericValue.asNumber(options.getOrDefault("follow", optional.get("follow"))).getInt(); - entityDimension = Registry.DIMENSION_TYPE.get(new Identifier(options.get("dim").getString())); + snapTo = options.getOrDefault("snap", optional.get("snap")).getString().toLowerCase(Locale.ROOT); + snapX = snapTo.contains("x"); + snapY = snapTo.contains("y"); + snapZ = snapTo.contains("z"); } } public int getExpiry() { return duration; } - public Vec3d toAbsolute(Entity e, Vec3d vec) + public Vec3d toAbsolute(Entity e, Vec3d vec, float partialTick) { - return e.getPos().add(vec); + return vec.add( + snapX?MathHelper.lerp(partialTick, e.prevX, e.getX()):0.0, + snapY?MathHelper.lerp(partialTick, e.prevY, e.getY()):0.0, + snapZ?MathHelper.lerp(partialTick, e.prevZ, e.getZ()):0.0 + ); } + public Vec3d relativiseRender(World world, Vec3d vec, float partialTick) + { + if (followEntity <= 0) return vec; + Entity e = world.getEntityById(followEntity); + if (e == null) return vec; + return toAbsolute(e, vec, partialTick); + } + public Vec3d vecFromValue(Value value) { if (!(value instanceof ListValue)) throw new InternalExpressionException("decoded value of "+value.getPrettyString()+" is not a triple"); @@ -335,6 +355,7 @@ public class ShapeDispatcher protected long calcKey() { // using FNV-1a algorithm long hash = -3750763034362895579L; + hash ^= shapeDimension.hashCode(); hash *= 1099511628211L; hash ^= color; hash *= 1099511628211L; hash ^= followEntity; hash *= 1099511628211L; hash ^= Float.hashCode(lineWidth); hash *= 1099511628211L; @@ -347,7 +368,8 @@ public class ShapeDispatcher "color", new NumericValue(-1), "follow", new NumericValue(-1), "line", new NumericValue(2.0), - "fill", new NumericValue(0xffffff00) + "fill", new NumericValue(0xffffff00), + "snap", new StringValue("xyz") ); protected Set requiredParams() {return required;} // list of params that can be there, with defaults @@ -389,16 +411,16 @@ public class ShapeDispatcher double density = Math.max(2.0, from.distanceTo(to) /50) / (a+0.1); return p -> { - if (followEntity == -1) + if (p.dimension == shapeDimension) { - particleMesh(Collections.singletonList(p), particle, density, from, to); - return; + particleMesh( + Collections.singletonList(p), + particle, + density, + relativiseRender(p.getServerWorld(), from, 0), + relativiseRender(p.getServerWorld(), to, 0) + ); } - Entity e = p.getServer().getWorld(entityDimension).getEntityById(followEntity); - if (e == null) return; - Vec3d rel1 = toAbsolute(e, from); - Vec3d rel2 = toAbsolute(e, to); - particleMesh(Collections.singletonList(p), particle, density, rel1, rel2); }; } @@ -471,19 +493,16 @@ public class ShapeDispatcher String particleName = String.format(Locale.ROOT , "dust %.1f %.1f %.1f 1.0", r, g, b); ParticleEffect particle = getParticleData(particleName); double density = Math.max(2.0, from.distanceTo(to) /50) / (a+0.1); + return p -> { - if (followEntity == -1) - { - drawParticleLine(Collections.singletonList(p), particle, from, to, density); - return; - } - - Entity e = p.getServer().getWorld(entityDimension).getEntityById(followEntity); - if (e == null) return; - Vec3d rel1 = toAbsolute(e, from); - Vec3d rel2 = toAbsolute(e, to); - drawParticleLine(Collections.singletonList(p), particle, rel1, rel2, density); + if (p.dimension == shapeDimension) drawParticleLine( + Collections.singletonList(p), + particle, + relativiseRender(p.getServerWorld(), from, 0), + relativiseRender(p.getServerWorld(), to, 0), + density + ); }; } @@ -534,24 +553,18 @@ public class ShapeDispatcher @Override public Consumer alternative() { return p -> { + if (p.dimension != shapeDimension) return; String particleName = String.format(Locale.ROOT , "dust %.1f %.1f %.1f 1.0", r, g, b); ParticleEffect particle = getParticleData(particleName); int partno = Math.min(1000,20*subdivisions); Random rand = p.world.getRandom(); ServerWorld world = p.getServerWorld(); - double ccx, ccy, ccz; - if (followEntity == -1) - { - ccx = center.x; ccy = center.y; ccz = center.z; - } - else - { - Entity e = p.getServer().getWorld(entityDimension).getEntityById(followEntity); - if (e == null) return; - Vec3d rel1 = toAbsolute(e, center); - ccx = (float)rel1.x; ccy = (float)rel1.y; ccz = (float)rel1.z; - } + Vec3d ccenter = relativiseRender(world, center, 0 ); + + double ccx = ccenter.x; + double ccy = ccenter.y; + double ccz = ccenter.z; for (int i=0; i required = ImmutableSet.of("center", "radius"); + private final Map optional = ImmutableMap.of( + "level", Value.ZERO, + "height", Value.ZERO, + "axis", new StringValue("y") + ); + @Override + protected Set requiredParams() { return Sets.union(super.requiredParams(), required); } + @Override + protected Set optionalParams() { return Sets.union(super.optionalParams(), optional.keySet()); } + + Vec3d center; + float height; + float radius; + int level; + int subdivisions; + Direction.Axis axis; + + private Cylinder() { super(); } + + @Override + protected void init(Map options) + { + super.init(options); + center = vecFromValue(options.get("center")); + radius = NumericValue.asNumber(options.get("radius")).getFloat(); + level = NumericValue.asNumber(options.getOrDefault("level", optional.get("level"))).getInt(); + subdivisions = level; + if (subdivisions <= 0) + { + subdivisions = Math.max(10, (int)(10*Math.sqrt(radius))); + } + height = NumericValue.asNumber(options.getOrDefault("height", optional.get("height"))).getFloat(); + axis = Direction.Axis.fromName(options.getOrDefault("axis", optional.get("axis")).getString()); + } + + + @Override + public Consumer alternative() { return p -> + { + String particleName = String.format(Locale.ROOT , "dust %.1f %.1f %.1f 1.0", r, g, b); + ParticleEffect particle = getParticleData(particleName); + int partno = (int)Math.min(1000,Math.sqrt(20*subdivisions*(1+height))); + Random rand = p.world.getRandom(); + ServerWorld world = p.getServerWorld(); + + Vec3d ccenter = relativiseRender(world, center, 0 ); + + double ccx = ccenter.x; + double ccy = ccenter.y; + double ccz = ccenter.z; + + if (axis == Direction.Axis.Y) + { + for (int i=0; i options, CarpetContext cc, Value value) + { + Value ret = super.validate(options, cc, value); + if (((NumericValue)ret).getDouble()<0) throw new InternalExpressionException("'"+id+"' should be non-negative"); + return ret; + } + } + public static class NonNegativeFloatParam extends NumericParam + { + protected NonNegativeFloatParam(String id) { super(id); } + @Override + public Value decode(Tag tag) { return new NumericValue(((FloatTag)tag).getFloat()); } + @Override + public Tag toTag(Value value) { return FloatTag.of(NumericValue.asNumber(value, id).getFloat()); } @Override public Value validate(Map options, CarpetContext cc, Value value) { Value ret = super.validate(options, cc, value); @@ -786,9 +918,9 @@ public class ShapeDispatcher { List lv = ((ListValue)value).getItems(); ListTag tag = new ListTag(); - tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(0)).getDouble())); - tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(1)).getDouble())); - tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(2)).getDouble())); + tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(0), "x").getDouble())); + tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(1), "y").getDouble())); + tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(2), "z").getDouble())); return tag; } } @@ -834,9 +966,9 @@ public class ShapeDispatcher { List coords = ((ListValue)value).getItems(); ListTag tag = new ListTag(); - tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(0)).getDouble())); - tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(1)).getDouble())); - tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(2)).getDouble())); + tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(0), "x").getDouble())); + tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(1), "y").getDouble())); + tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(2), "z").getDouble())); ltag.add(tag); } return ltag; @@ -853,7 +985,7 @@ public class ShapeDispatcher public Value decode(Tag tag) { return new NumericValue(((IntTag)tag).getInt()); } @Override - public Tag toTag(Value value) { return IntTag.of(NumericValue.asNumber(value).getInt()); } + public Tag toTag(Value value) { return IntTag.of(NumericValue.asNumber(value, id).getInt()); } } public static class EntityParam extends Param @@ -864,7 +996,7 @@ public class ShapeDispatcher @Override public Tag toTag(Value value) { - return IntTag.of(NumericValue.asNumber(value).getInt()); + return IntTag.of(NumericValue.asNumber(value, id).getInt()); } @Override diff --git a/src/main/java/carpet/script/utils/ShapesRenderer.java b/src/main/java/carpet/script/utils/ShapesRenderer.java index 1819885b..d4bb1e9f 100644 --- a/src/main/java/carpet/script/utils/ShapesRenderer.java +++ b/src/main/java/carpet/script/utils/ShapesRenderer.java @@ -8,13 +8,11 @@ import net.minecraft.client.render.BufferBuilder; import net.minecraft.client.render.Camera; import net.minecraft.client.render.Tessellator; import net.minecraft.client.render.VertexFormats; -import net.minecraft.entity.Entity; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; -import net.minecraft.util.Identifier; +import net.minecraft.util.math.Direction; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; -import net.minecraft.util.registry.Registry; import net.minecraft.world.IWorld; import net.minecraft.world.dimension.DimensionType; import org.lwjgl.opengl.GL11; @@ -34,6 +32,7 @@ public class ShapesRenderer put("line", RenderedLine::new); put("box", RenderedBox::new); put("sphere", RenderedSphere::new); + put("cylinder", RenderedCylinder::new); }}; public ShapesRenderer(MinecraftClient minecraftClient) @@ -128,7 +127,7 @@ public class ShapesRenderer else { RenderedShape rshape = shapeFactory.apply(client, shape); - DimensionType dim = Registry.DIMENSION_TYPE.get(new Identifier(tag.getString("dim"))); + DimensionType dim = shape.shapeDimension; long key = rshape.key(); synchronized (shapes) { @@ -181,20 +180,9 @@ public class ShapesRenderer { if (shape.followEntity <=0 ) return true; if (client.world == null) return false; - if (client.world.dimension.getType() != dim) return false; if (client.world.getEntityById(shape.followEntity) == null) return false; return true; } - protected Vec3d relativiseRender(Vec3d vec, float partialTick) - { - if (shape.followEntity <= 0) return vec; - Entity e = client.world.getEntityById(shape.followEntity); - return vec.add( - MathHelper.lerp(partialTick, e.prevX, e.getX()), - MathHelper.lerp(partialTick, e.prevY, e.getY()), - MathHelper.lerp(partialTick, e.prevZ, e.getZ()) - ); - } } public static class RenderedBox extends RenderedShape @@ -209,8 +197,8 @@ public class ShapesRenderer public void renderLines(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick) { if (shape.a == 0.0) return; - Vec3d v1 = relativiseRender(shape.from, partialTick); - Vec3d v2 = relativiseRender(shape.to, partialTick); + Vec3d v1 = shape.relativiseRender(client.world, shape.from, partialTick); + Vec3d v2 = shape.relativiseRender(client.world, shape.to, partialTick); RenderSystem.lineWidth(shape.lineWidth); drawBoxWireGLLines(tessellator, bufferBuilder, (float)(v1.x-cx-renderEpsilon), (float)(v1.y-cy-renderEpsilon), (float)(v1.z-cz-renderEpsilon), @@ -223,8 +211,8 @@ public class ShapesRenderer public void renderFaces(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick) { if (shape.fa == 0.0) return; - Vec3d v1 = relativiseRender(shape.from, partialTick); - Vec3d v2 = relativiseRender(shape.to, partialTick); + Vec3d v1 = shape.relativiseRender(client.world, shape.from, partialTick); + Vec3d v2 = shape.relativiseRender(client.world, shape.to, partialTick); RenderSystem.lineWidth(1.0F); drawBoxFaces(tessellator, bufferBuilder, (float)(v1.x-cx-renderEpsilon), (float)(v1.y-cy-renderEpsilon), (float)(v1.z-cz-renderEpsilon), @@ -245,8 +233,8 @@ public class ShapesRenderer @Override public void renderLines(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick) { - Vec3d v1 = relativiseRender(shape.from, partialTick); - Vec3d v2 = relativiseRender(shape.to, partialTick); + Vec3d v1 = shape.relativiseRender(client.world, shape.from, partialTick); + Vec3d v2 = shape.relativiseRender(client.world, shape.to, partialTick); RenderSystem.lineWidth(shape.lineWidth); drawLine(tessellator, bufferBuilder, (float)(v1.x-cx-renderEpsilon), (float)(v1.y-cy-renderEpsilon), (float)(v1.z-cz-renderEpsilon), @@ -266,7 +254,7 @@ public class ShapesRenderer public void renderLines(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick) { if (shape.a == 0.0) return; - Vec3d vc = relativiseRender(shape.center, partialTick); + Vec3d vc = shape.relativiseRender(client.world, shape.center, partialTick); RenderSystem.lineWidth(shape.lineWidth); drawSphereWireframe(tessellator, bufferBuilder, (float)(vc.x-cx-renderEpsilon), (float)(vc.y-cy-renderEpsilon), (float)(vc.z-cz-renderEpsilon), @@ -277,7 +265,7 @@ public class ShapesRenderer public void renderFaces(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick) { if (shape.fa == 0.0) return; - Vec3d vc = relativiseRender(shape.center, partialTick); + Vec3d vc = shape.relativiseRender(client.world, shape.center, partialTick); RenderSystem.lineWidth(1.0f); drawSphereFaces(tessellator, bufferBuilder, (float)(vc.x-cx-renderEpsilon), (float)(vc.y-cy-renderEpsilon), (float)(vc.z-cz-renderEpsilon), @@ -286,6 +274,36 @@ public class ShapesRenderer } } + public static class RenderedCylinder extends RenderedShape + { + public RenderedCylinder(MinecraftClient client, ShapeDispatcher.ExpiringShape shape) + { + super(client, (ShapeDispatcher.Cylinder)shape); + } + @Override + public void renderLines(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick) + { + if (shape.a == 0.0) return; + Vec3d vc = shape.relativiseRender(client.world, shape.center, partialTick); + RenderSystem.lineWidth(shape.lineWidth); + drawCylinderWireframe(tessellator, bufferBuilder, + (float)(vc.x-cx-renderEpsilon), (float)(vc.y-cy-renderEpsilon), (float)(vc.z-cz-renderEpsilon), + shape.radius, shape.height, shape.axis, shape.subdivisions, + shape.r, shape.g, shape.b, shape.a); + } + @Override + public void renderFaces(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick) + { + if (shape.fa == 0.0) return; + //Vec3d vc = shape.relativiseRender(client.world, shape.center, partialTick); + //RenderSystem.lineWidth(1.0f); + //drawSphereFaces(tessellator, bufferBuilder, + // (float)(vc.x-cx-renderEpsilon), (float)(vc.y-cy-renderEpsilon), (float)(vc.z-cz-renderEpsilon), + // shape.radius, shape.subdivisions, + // shape.fr, shape.fg, shape.fb, shape.fa); + } + } + // some raw shit public static void drawLine(Tessellator tessellator, BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha) { @@ -409,6 +427,90 @@ public class ShapesRenderer tessellator.draw(); } + public static void drawCylinderWireframe(Tessellator tessellator, BufferBuilder builder, + float cx, float cy, float cz, + float r, float h, Direction.Axis axis, int subd, + float red, float grn, float blu, float alpha) + { + float step = (float)Math.PI / (subd/2); + int num_steps180 = (int)(Math.PI / step)+1; + int num_steps360 = (int)(2*Math.PI / step); + int hsteps = (h>0) ? ((int)Math.ceil(h / (step*r))+1) : 1; + float hstep = (h>0) ? (h / (hsteps-1)) : 1; + // draw base + + if (axis == Direction.Axis.Y) + { + for (int dh = 0; dh < hsteps; dh++) + { + float hh = dh*hstep; + builder.begin(GL11.GL_LINE_LOOP, VertexFormats.POSITION_COLOR); + for (int i = 0; i <= num_steps360; i++) + { + float theta = step * i; + float x = r * MathHelper.cos(theta); + float y = hh; + float z = r * MathHelper.sin(theta); + builder.vertex(x + cx, y + cy, z + cz).color(red, grn, blu, alpha).next(); + } + tessellator.draw(); + } + + if (h > 0) + { + for (int i = 0; i <= num_steps180; i++) + { + builder.begin(GL11.GL_LINE_LOOP, VertexFormats.POSITION_COLOR); + float theta = step * i; + float x = r * MathHelper.cos(theta); + + float z = r * MathHelper.sin(theta); + + builder.vertex(cx - x, cy + 0, cz + z).color(red, grn, blu, alpha).next(); + builder.vertex(cx + x, cy + 0, cz - z).color(red, grn, blu, alpha).next(); + builder.vertex(cx + x, cy + h, cz - z).color(red, grn, blu, alpha).next(); + builder.vertex(cx - x, cy + h, cz + z).color(red, grn, blu, alpha).next(); + tessellator.draw(); + } + } + + } + else if (axis == Direction.Axis.X) + { + for (int dh = 0; dh < hsteps; dh++) + { + float hh = dh * hstep; + builder.begin(GL11.GL_LINE_LOOP, VertexFormats.POSITION_COLOR); + for (int i = 0; i <= num_steps360; i++) + { + float theta = step * i; + float z = r * MathHelper.cos(theta); + float x = hh; + float y = r * MathHelper.sin(theta); + builder.vertex(x + cx, y + cy, z + cz).color(red, grn, blu, alpha).next(); + } + tessellator.draw(); + } + } + else if (axis == Direction.Axis.Z) + { + for (int dh = 0; dh < hsteps; dh++) + { + float hh = dh * hstep; + builder.begin(GL11.GL_LINE_LOOP, VertexFormats.POSITION_COLOR); + for (int i = 0; i <= num_steps360; i++) + { + float theta = step * i; + float y = r * MathHelper.cos(theta); + float z = hh; + float x = r * MathHelper.sin(theta); + builder.vertex(x + cx, y + cy, z + cz).color(red, grn, blu, alpha).next(); + } + tessellator.draw(); + } + } + } + public static void drawSphereWireframe(Tessellator tessellator, BufferBuilder builder, float cx, float cy, float cz, float r, int subd, diff --git a/src/main/java/carpet/script/value/NumericValue.java b/src/main/java/carpet/script/value/NumericValue.java index fa6a58c9..2ae575fb 100644 --- a/src/main/java/carpet/script/value/NumericValue.java +++ b/src/main/java/carpet/script/value/NumericValue.java @@ -13,6 +13,13 @@ public class NumericValue extends Value private Double value; final static double epsilon = 1024*Double.MIN_VALUE; + public static NumericValue asNumber(Value v1, String id) + { + if (!(v1 instanceof NumericValue)) + throw new InternalExpressionException("Argument "+id+" has to be of a numeric type"); + return ((NumericValue) v1); + } + public static NumericValue asNumber(Value v1) { if (!(v1 instanceof NumericValue)) diff --git a/src/main/resources/assets/carpet/scripts/chunk_display.sc b/src/main/resources/assets/carpet/scripts/chunk_display.sc index 7f770b0a..1eca80e5 100644 --- a/src/main/resources/assets/carpet/scripts/chunk_display.sc +++ b/src/main/resources/assets/carpet/scripts/chunk_display.sc @@ -8,19 +8,19 @@ global_chunk_colors = m( // stable full generation (for '0's, all 1,2,3 are always 'full') l('full', l(0xbbbbbb00, 0x88888800)), // gray // unstable final bits - l('heightmaps', l(0xFFFFFF00, 0x00000000)), // checker - l('spawn', l(0xFFFFFF00, 0x00000000)), // checker - l('light_gen', l(0xFFFFFF00, 0x00000000)), // checker + l('heightmaps', l(0x33333300, 0x22222200)), // checker + l('spawn', l(0x00333300, 0x00222200)), // checker + l('light_gen', l(0x55550000, 0x44440000)), // checker // stable features l('features', l(0x88bb2200, 0x66882200)), // green muddled //stable terrain l('liquid_carvers', l(0x65432100, 0x54321000)), // browns //unstable terrain - not generated yet - l('carvers', l(0xFFFFFF00, 0x00000000)), // checker - l('surface', l(0xFFFFFF00, 0x00000000)), // checker - l('noise', l(0xFFFFFF00, 0x00000000)), // checker - l('biomes', l(0xFFFFFF00, 0x00000000)), // checker - l('structure_references', l(0xFFFFFF00, 0x00000000)), // checker + l('carvers', l(0x33003300, 0x22002200)), // checker + l('surface', l(0x33330000, 0x22220000)), // checker + l('noise', l(0x33000000, 0x22000000)), // checker + l('biomes', l(0x00330000, 0x00220000)), // checker + l('structure_references', l(0x00003300, 0x00002200)), // checker // stable l('structure_starts', l(0x66666600, 0x22222200)), // darkgrey // not stated yet @@ -37,7 +37,7 @@ global_chunk_colors = m( l('post_teleport', l(0xAA00AA00, 0xAA00AA00)), // purple l('start', l(0xDDFF0000, 0xDDFF0000)), // lime, green // recent chunk requests - l('unknown', l(0xFFFFFF00, 0x00000000)) // check + l('unknown', l(0xFF55FF00, 0xff99ff00)) // pink purple ); // map representing current displayed chunkloading setup @@ -67,8 +67,6 @@ __on_player_uses_item(player, item_tuple, hand) -> __setup_tracker(player, item_tuple); ); -//__on_tick() -> null; - __remove_previous_setup(new_player) -> ( if (!global_current_setup, return()); @@ -127,6 +125,7 @@ __chunk_visualizer_tick(p) -> if(!setup, return()); if (!global_running, return()); show_activity = (p~'holds':0 == 'redstone_torch'); + yval = setup:'plot_center':1+16; in_dimension( setup:'plot_dimension', l(sx, sy, sz) = setup:'source_center'; l(px, py, pz) = setup:'plot_center'; @@ -154,8 +153,6 @@ __chunk_visualizer_tick(p) -> for(tickets, l(type, level) = _; if (show_activity || type != 'unknown', - //global_status_cache:source_pos = type; - //changed = true; status = type; ); ); @@ -163,15 +160,15 @@ __chunk_visualizer_tick(p) -> l(cached_status, expiry) = global_status_cache:source_pos; changed = (status != cached_status); if ( changed || (expiry < now), - global_status_cache:source_pos = l(status, now+100+floor(rand(20))); - bpos = l(dx/2, 10, dz/2); + global_status_cache:source_pos = l(status, now+100+floor(rand(40))); + bpos = l(dx/2, yval, dz/2); bcol = global_chunk_colors:status:((dx+dz)%2); shapes += l('box', 150, 'from', bpos, 'to', bpos + l(0.5,0,0.5), - 'color', 0xffffff00, 'fill', bcol+128, 'follow', p); + 'color', 0xffffff00, 'fill', bcol+128, 'follow', p, 'snap', 'xz'); if (changed, pbcol = global_chunk_colors:cached_status:((dx+dz)%2); shapes += l('box', 0, 'from', bpos, 'to', bpos + l(0.5,0,0.5), - 'color', 0xffffff00, 'fill', pbcol+128, 'follow', p); + 'color', 0xffffff00, 'fill', pbcol+128, 'follow', p, 'snap', 'xz'); ); ); ); From 4c7c5c5a359d10aa8dc23f22f2e8f412fdc90b54 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 10 Jun 2020 01:54:45 -0300 Subject: [PATCH 192/198] updaeted loom --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b7e5897c..2dc45583 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '0.2.6-SNAPSHOT' + id 'fabric-loom' version '0.4-SNAPSHOT' id 'maven-publish' } From 118554dbababbc3843601a4cd282a0e0c4f8b571 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 10 Jun 2020 12:30:33 -0300 Subject: [PATCH 193/198] added 'cylinder' shape --- docs/scarpet/api/Auxiliary.md | 11 +- .../carpet/script/utils/ShapeDispatcher.java | 14 +- .../carpet/script/utils/ShapesRenderer.java | 242 ++++++++++++++++-- 3 files changed, 248 insertions(+), 19 deletions(-) diff --git a/docs/scarpet/api/Auxiliary.md b/docs/scarpet/api/Auxiliary.md index 8cb0c117..98021758 100644 --- a/docs/scarpet/api/Auxiliary.md +++ b/docs/scarpet/api/Auxiliary.md @@ -88,13 +88,22 @@ Available shapes: * `from` - triple coordinates, entity, or block value indicating one corner of the box * `to` - other corner, same format as `from` - * `'sphere'` - draws a sphere + * `'sphere'`: * Required attributes: * `center` - center of the sphere * `radius` - radius of the sphere * Optional attributes: * `level` - level of details, or grid size. The more the denser your sphere. Default level of 0, means that the level of detail will be selected automatically based on radius. + + * `'cylinder'`: + * Required attributes: + * `center` - center of the base + * `radius` - radius of the base circle + * Optional attributes: + * `axis` - cylinder direction, one of `'x'`, `'y'`, `'z'` defaults to `'y'` + * `height` - height of the cyllinder, defaults to `0`, so flat disk. Can be negative. + * `level` - level of details, see `'sphere'`. ### `create_marker(text, pos, rotation?, block?)` diff --git a/src/main/java/carpet/script/utils/ShapeDispatcher.java b/src/main/java/carpet/script/utils/ShapeDispatcher.java index 9007d675..58f30095 100644 --- a/src/main/java/carpet/script/utils/ShapeDispatcher.java +++ b/src/main/java/carpet/script/utils/ShapeDispatcher.java @@ -714,7 +714,7 @@ public class ShapeDispatcher put("center", new Vec3Param("center", false)); put("radius", new PositiveFloatParam("radius")); put("level", new PositiveIntParam("level")); - put("height", new NonNegativeFloatParam("height")); + put("height", new FloatParam("height")); put("axis", new StringChoiceParam("axis", "x", "y", "z")); put("points", new PointsParam("points")); }}; @@ -794,6 +794,15 @@ public class ShapeDispatcher return value; } } + public static class FloatParam extends NumericParam + { + protected FloatParam(String id) { super(id); } + @Override + public Value decode(Tag tag) { return new NumericValue(((FloatTag)tag).getFloat()); } + @Override + public Tag toTag(Value value) { return FloatTag.of(NumericValue.asNumber(value, id).getFloat()); } + } + public static abstract class PositiveParam extends NumericParam { protected PositiveParam(String id) { super(id); } @@ -851,6 +860,9 @@ public class ShapeDispatcher } } + + + public static class Vec3Param extends Param { private boolean roundsUpForBlocks; diff --git a/src/main/java/carpet/script/utils/ShapesRenderer.java b/src/main/java/carpet/script/utils/ShapesRenderer.java index d4bb1e9f..c2a799b9 100644 --- a/src/main/java/carpet/script/utils/ShapesRenderer.java +++ b/src/main/java/carpet/script/utils/ShapesRenderer.java @@ -257,8 +257,8 @@ public class ShapesRenderer Vec3d vc = shape.relativiseRender(client.world, shape.center, partialTick); RenderSystem.lineWidth(shape.lineWidth); drawSphereWireframe(tessellator, bufferBuilder, - (float)(vc.x-cx-renderEpsilon), (float)(vc.y-cy-renderEpsilon), (float)(vc.z-cz-renderEpsilon), - shape.radius, shape.subdivisions, + (float)(vc.x-cx), (float)(vc.y-cy), (float)(vc.z-cz), + (float)(shape.radius+renderEpsilon), shape.subdivisions, shape.r, shape.g, shape.b, shape.a); } @Override @@ -268,8 +268,8 @@ public class ShapesRenderer Vec3d vc = shape.relativiseRender(client.world, shape.center, partialTick); RenderSystem.lineWidth(1.0f); drawSphereFaces(tessellator, bufferBuilder, - (float)(vc.x-cx-renderEpsilon), (float)(vc.y-cy-renderEpsilon), (float)(vc.z-cz-renderEpsilon), - shape.radius, shape.subdivisions, + (float)(vc.x-cx), (float)(vc.y-cy), (float)(vc.z-cz), + (float)(shape.radius+renderEpsilon), shape.subdivisions, shape.fr, shape.fg, shape.fb, shape.fa); } } @@ -286,21 +286,26 @@ public class ShapesRenderer if (shape.a == 0.0) return; Vec3d vc = shape.relativiseRender(client.world, shape.center, partialTick); RenderSystem.lineWidth(shape.lineWidth); + double dir = MathHelper.sign(shape.height); drawCylinderWireframe(tessellator, bufferBuilder, - (float)(vc.x-cx-renderEpsilon), (float)(vc.y-cy-renderEpsilon), (float)(vc.z-cz-renderEpsilon), - shape.radius, shape.height, shape.axis, shape.subdivisions, + (float) (vc.x - cx - dir * renderEpsilon), (float) (vc.y - cy - dir * renderEpsilon), (float) (vc.z - cz - dir * renderEpsilon), + (float) (shape.radius + renderEpsilon), (float) (shape.height + 2*dir*renderEpsilon), shape.axis, + shape.subdivisions, shape.radius == 0, shape.r, shape.g, shape.b, shape.a); + } @Override public void renderFaces(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick) { if (shape.fa == 0.0) return; - //Vec3d vc = shape.relativiseRender(client.world, shape.center, partialTick); - //RenderSystem.lineWidth(1.0f); - //drawSphereFaces(tessellator, bufferBuilder, - // (float)(vc.x-cx-renderEpsilon), (float)(vc.y-cy-renderEpsilon), (float)(vc.z-cz-renderEpsilon), - // shape.radius, shape.subdivisions, - // shape.fr, shape.fg, shape.fb, shape.fa); + Vec3d vc = shape.relativiseRender(client.world, shape.center, partialTick); + RenderSystem.lineWidth(1.0f); + double dir = MathHelper.sign(shape.height); + drawCylinderFaces(tessellator, bufferBuilder, + (float) (vc.x - cx - dir * renderEpsilon), (float) (vc.y - cy - dir * renderEpsilon), (float) (vc.z - cz - dir * renderEpsilon), + (float) (shape.radius + renderEpsilon), (float) (shape.height + 2*dir*renderEpsilon), shape.axis, + shape.subdivisions, shape.radius == 0, + shape.fr, shape.fg, shape.fb, shape.fa); } } @@ -429,15 +434,19 @@ public class ShapesRenderer public static void drawCylinderWireframe(Tessellator tessellator, BufferBuilder builder, float cx, float cy, float cz, - float r, float h, Direction.Axis axis, int subd, + float r, float h, Direction.Axis axis, int subd, boolean isFlat, float red, float grn, float blu, float alpha) { float step = (float)Math.PI / (subd/2); int num_steps180 = (int)(Math.PI / step)+1; int num_steps360 = (int)(2*Math.PI / step); - int hsteps = (h>0) ? ((int)Math.ceil(h / (step*r))+1) : 1; - float hstep = (h>0) ? (h / (hsteps-1)) : 1; - // draw base + int hsteps = 1; + float hstep = 1.0f; + if (!isFlat) + { + hsteps = (int) Math.ceil(MathHelper.abs(h) / (step * r)) + 1; + hstep = h / (hsteps - 1); + }// draw base if (axis == Direction.Axis.Y) { @@ -456,7 +465,7 @@ public class ShapesRenderer tessellator.draw(); } - if (h > 0) + if (!isFlat) { for (int i = 0; i <= num_steps180; i++) { @@ -473,6 +482,19 @@ public class ShapesRenderer tessellator.draw(); } } + else + { + builder.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR); + for (int i = 0; i <= num_steps180; i++) + { + float theta = step * i; + float x = r * MathHelper.cos(theta); + float z = r * MathHelper.sin(theta); + builder.vertex(cx - x, cy, cz + z).color(red, grn, blu, alpha).next(); + builder.vertex(cx + x, cy, cz - z).color(red, grn, blu, alpha).next(); + } + tessellator.draw(); + } } else if (axis == Direction.Axis.X) @@ -491,6 +513,37 @@ public class ShapesRenderer } tessellator.draw(); } + + if (!isFlat) + { + for (int i = 0; i <= num_steps180; i++) + { + builder.begin(GL11.GL_LINE_LOOP, VertexFormats.POSITION_COLOR); + float theta = step * i; + float y = r * MathHelper.cos(theta); + + float z = r * MathHelper.sin(theta); + + builder.vertex(cx + 0, cy - y, cz + z).color(red, grn, blu, alpha).next(); + builder.vertex(cx + 0, cy + y, cz - z).color(red, grn, blu, alpha).next(); + builder.vertex(cx + h, cy + y, cz - z).color(red, grn, blu, alpha).next(); + builder.vertex(cx + h, cy - y, cz + z).color(red, grn, blu, alpha).next(); + tessellator.draw(); + } + } + else + { + builder.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR); + for (int i = 0; i <= num_steps180; i++) + { + float theta = step * i; + float y = r * MathHelper.cos(theta); + float z = r * MathHelper.sin(theta); + builder.vertex(cx, cy - y, cz + z).color(red, grn, blu, alpha).next(); + builder.vertex(cx, cy + y, cz - z).color(red, grn, blu, alpha).next(); + } + tessellator.draw(); + } } else if (axis == Direction.Axis.Z) { @@ -508,6 +561,161 @@ public class ShapesRenderer } tessellator.draw(); } + if (!isFlat) + { + for (int i = 0; i <= num_steps180; i++) + { + builder.begin(GL11.GL_LINE_LOOP, VertexFormats.POSITION_COLOR); + float theta = step * i; + float x = r * MathHelper.cos(theta); + + float y = r * MathHelper.sin(theta); + + builder.vertex(cx + x, cy - y, cz + 0).color(red, grn, blu, alpha).next(); + builder.vertex(cx - x, cy + y, cz + 0).color(red, grn, blu, alpha).next(); + builder.vertex(cx - x, cy + y, cz + h).color(red, grn, blu, alpha).next(); + builder.vertex(cx + x, cy - y, cz + h).color(red, grn, blu, alpha).next(); + tessellator.draw(); + } + } + else + { + builder.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR); + for (int i = 0; i <= num_steps180; i++) + { + float theta = step * i; + float x = r * MathHelper.cos(theta); + float y = r * MathHelper.sin(theta); + builder.vertex(cx + x, cy - y, cz).color(red, grn, blu, alpha).next(); + builder.vertex(cx - x, cy + y, cz).color(red, grn, blu, alpha).next(); + } + tessellator.draw(); + } + + } + } + + public static void drawCylinderFaces(Tessellator tessellator, BufferBuilder builder, + float cx, float cy, float cz, + float r, float h, Direction.Axis axis, int subd, boolean isFlat, + float red, float grn, float blu, float alpha) + { + float step = (float)Math.PI / (subd/2); + int num_steps180 = (int)(Math.PI / step)+1; + int num_steps360 = (int)(2*Math.PI / step)+1; + + if (axis == Direction.Axis.Y) + { + + builder.begin(GL11.GL_TRIANGLE_FAN, VertexFormats.POSITION_COLOR); + builder.vertex(cx, cy, cz).color(red, grn, blu, alpha).next(); + for (int i = 0; i <= num_steps360; i++) + { + float theta = step * i; + float x = r * MathHelper.cos(theta); + float z = r * MathHelper.sin(theta); + builder.vertex(x + cx, cy, z + cz).color(red, grn, blu, alpha).next(); + } + tessellator.draw(); + if (!isFlat) + { + builder.begin(GL11.GL_TRIANGLE_FAN, VertexFormats.POSITION_COLOR); + builder.vertex(cx, cy+h, cz).color(red, grn, blu, alpha).next(); + for (int i = 0; i <= num_steps360; i++) + { + float theta = step * i; + float x = r * MathHelper.cos(theta); + float z = r * MathHelper.sin(theta); + builder.vertex(x + cx, cy+h, z + cz).color(red, grn, blu, alpha).next(); + } + tessellator.draw(); + + builder.begin(GL11.GL_QUAD_STRIP, VertexFormats.POSITION_COLOR); + for (int i = 0; i <= num_steps360; i++) + { + float theta = step * i; + float x = r * MathHelper.cos(theta); + float z = r * MathHelper.sin(theta); + builder.vertex(cx + x, cy + 0, cz + z).color(red, grn, blu, alpha).next(); + builder.vertex(cx + x, cy + h, cz + z).color(red, grn, blu, alpha).next(); + } + tessellator.draw(); + } + + } + else if (axis == Direction.Axis.X) + { + builder.begin(GL11.GL_TRIANGLE_FAN, VertexFormats.POSITION_COLOR); + builder.vertex(cx, cy, cz).color(red, grn, blu, alpha).next(); + for (int i = 0; i <= num_steps360; i++) + { + float theta = step * i; + float y = r * MathHelper.cos(theta); + float z = r * MathHelper.sin(theta); + builder.vertex(cx, cy + y, z + cz).color(red, grn, blu, alpha).next(); + } + tessellator.draw(); + if (!isFlat) + { + builder.begin(GL11.GL_TRIANGLE_FAN, VertexFormats.POSITION_COLOR); + builder.vertex(cx+h, cy, cz).color(red, grn, blu, alpha).next(); + for (int i = 0; i <= num_steps360; i++) + { + float theta = step * i; + float y = r * MathHelper.cos(theta); + float z = r * MathHelper.sin(theta); + builder.vertex(cx+h, cy + y, cz + z).color(red, grn, blu, alpha).next(); + } + tessellator.draw(); + + builder.begin(GL11.GL_QUAD_STRIP, VertexFormats.POSITION_COLOR); + for (int i = 0; i <= num_steps360; i++) + { + float theta = step * i; + float y = r * MathHelper.cos(theta); + float z = r * MathHelper.sin(theta); + builder.vertex(cx + 0, cy + y, cz + z).color(red, grn, blu, alpha).next(); + builder.vertex(cx + h, cy + y, cz + z).color(red, grn, blu, alpha).next(); + } + tessellator.draw(); + } + } + else if (axis == Direction.Axis.Z) + { + builder.begin(GL11.GL_TRIANGLE_FAN, VertexFormats.POSITION_COLOR); + builder.vertex(cx, cy, cz).color(red, grn, blu, alpha).next(); + for (int i = 0; i <= num_steps360; i++) + { + float theta = step * i; + float x = r * MathHelper.cos(theta); + float y = r * MathHelper.sin(theta); + builder.vertex(x + cx, cy+y, cz).color(red, grn, blu, alpha).next(); + } + tessellator.draw(); + if (!isFlat) + { + builder.begin(GL11.GL_TRIANGLE_FAN, VertexFormats.POSITION_COLOR); + builder.vertex(cx, cy, cz+h).color(red, grn, blu, alpha).next(); + for (int i = 0; i <= num_steps360; i++) + { + float theta = step * i; + float x = r * MathHelper.cos(theta); + float y = r * MathHelper.sin(theta); + builder.vertex(x + cx, cy+y, cz+h).color(red, grn, blu, alpha).next(); + } + tessellator.draw(); + + builder.begin(GL11.GL_QUAD_STRIP, VertexFormats.POSITION_COLOR); + for (int i = 0; i <= num_steps360; i++) + { + float theta = step * i; + float x = r * MathHelper.cos(theta); + float y = r * MathHelper.sin(theta); + builder.vertex(cx + x, cy + y, cz + 0).color(red, grn, blu, alpha).next(); + builder.vertex(cx + x, cy + y, cz + h).color(red, grn, blu, alpha).next(); + } + tessellator.draw(); + } } } From afef9f1de040bcad8322b6e2cd9415b059dfcfc7 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 10 Jun 2020 13:30:01 -0300 Subject: [PATCH 194/198] 1.3.28 --- gradle.properties | 2 +- src/main/java/carpet/CarpetSettings.java | 2 +- src/main/resources/fabric.mod.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 06c8de17..fc828653 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ org.gradle.jvmargs=-Xmx1G loader_version=0.8.7+build.201 # Mod Properties - mod_version = 1.3.27+v200605 + mod_version = 1.3.28+v200610 maven_group = carpet archives_base_name = fabric-carpet diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index ee3d0e83..a8bf439c 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -34,7 +34,7 @@ import static carpet.settings.RuleCategory.CLIENT; @SuppressWarnings("CanBeFinal") public class CarpetSettings { - public static final String carpetVersion = "1.3.27+v200605"; + public static final String carpetVersion = "1.3.28+v200610"; public static final Logger LOG = LogManager.getLogger(); public static boolean skipGenerationChecks = false; public static boolean impendingFillSkipUpdates = false; diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index cf4b596d..f0f2cffe 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,7 +1,7 @@ { "schemaVersion": 1, "id": "carpet", - "version": "1.3.27", + "version": "1.3.28", "name": "Carpet Mod in Fabric", "description": "Carpet made out of fabric", From 7eb345ff59d86b049e0e0b54a4523cb4d087b86b Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 10 Jun 2020 15:51:38 -0300 Subject: [PATCH 195/198] docs --- docs/scarpet/Full.md | 54 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index 0e1a614e..22deab0d 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -2639,6 +2639,13 @@ query(p,'effect','resistance') => null Number indicating remaining entity health, or `null` if not applicable. +### `query(e, 'hunger')` +### `query(e, 'saturation')` +### `query(e, 'exhaustion')` + +Retrieves player hunger related information. For non-players, returns `null`. + + ### `query(e, 'holds', slot?)` Returns triple of short name, stack count, and NBT of item held in `slot`, or `null` if nothing or not applicable. Available options for `slot` are: @@ -2795,10 +2802,11 @@ If called with `false` value, it will disable AI in the mob. `true` will enable Sets if the entity obeys any collisions, including collisions with the terrain and basic physics. Not affecting players, since they are controlled client side. -### `modify(e, 'effect', name, duration?, amplifier?, show_particles?, show_icon?)` +### `modify(e, 'effect', name?, duration?, amplifier?, show_particles?, show_icon?)` Applies status effect to the living entity. Takes several optional parameters, which default to `0`, `true` -and `true`. If no duration is specified, or if it's null or 0, the effect is removed. +and `true`. If no duration is specified, or if it's null or 0, the effect is removed. If name is not specified, +it clears all effects. ### `modify(e, 'home', null), modify(e, 'home', block, distance?), modify(e, 'home', x, y, z, distance?)` @@ -2838,6 +2846,17 @@ Toggles gravity for the entity. Will set entity on fire for `ticks` ticks. Set to 0 to extinguish. +### `modify(e, 'hunger', value)` +### `modify(e, 'saturation', value)` +### `modify(e, 'exhaustion', value)` + +Modifies directly player raw hunger components. Has no effect on non-players + +### `modify(e, 'add_exhaustion', value)` + +adds exhaustion value to the current player exhaustion level - that's the method you probably want to use +to manipulate how much 'food' some action cost. + ## Entity Events There is a number of events that happen to entities that you can attach your own code to in the form of event handlers. @@ -2887,7 +2906,12 @@ health back to the villager after being harmed. Most functions in this category require inventory as the first argument. Inventory could be specified by an entity, or a block, or position (three coordinates) of a potential block with inventory. Player enderchest inventory require -two arguments, keyword `'enderchest'`, followed by the player entity argument. If the entity or a block doesn't have +two arguments, keyword `'enderchest'`, followed by the player entity argument, or a single argument as a string of a +form: `'enderchest_steve'`. If your player name starts with enderchest, it can be always accessed by passing a player +entity value. If all else fails, it will try to identify first three arguments as coordinates of a block position of +a block inventory. Player inventories can also be called by their name. + + If the entity or a block doesn't have an inventory, they typically do nothing and return null. Most items returned are in the form of a triple of item name, count, and nbt or the extra data associated with an item. @@ -3130,7 +3154,10 @@ supplied, only that player will receive particles. ## Markers -### `draw_shape(shape, duration, key?, value?, ... )`, `draw_shape(shape, duration, l(key?, value?, ... ))`, `draw_shape(shape, duration, attribute_map)` +### `draw_shape(shape, duration, key?, value?, ... )`, +### `draw_shape(shape, duration, l(key?, value?, ... ))`, +### `draw_shape(shape, duration, attribute_map)` +### `draw_shape(shape_list)` Draws a shape in the world that will expire in `duration` ticks. Other attributes of the shape should be provided as consecutive key - value argument pairs, either as next arguments, or packed in a list, or supplied as a proper key-value @@ -3141,6 +3168,10 @@ are not required to follow all attributes precisely, but will allow vanilla clie apps. One of the attributes that will definitely not be honored is the duration - particles will be send once per shape and last whatever they typically last in the game. +Shapes can be send one by one, using either of the first three invocations, or batched as a list of shape descriptors. +Batching has this benefit that they will be send possibly as one packet, limiting network overhead of +sending many small packets to draw several shapes at once. + Shapes will fail to draw and raise a runtime error if not all its required parameters are specified and all available shapes have some parameters that are required, so make sure to have them in place: @@ -3159,6 +3190,10 @@ Optional shared shape attributes: * `follow` - entity, or player name. Shape will follow an entity instead of being static. Follow attribute requires all positional arguments to be relative to the entity and disallow of using entity or block as position markers. You must specify positions as a triple. + * `snap` - if `follow` is present, indicated on which axis the snapping to entity coordinates occurs, and which axis + will be treated statically, i.e. the coordinate passed in a coord triple is the actual value in the world. Default + value is `'xyz'`, meaning the shape will be drawn relatively to the entity in all three directions. Using `xz` for + instance makes so that the shape follows the entity, but stays at the same, absolute Y coordinate. Available shapes: * `'line'` - draws a straight line between two points @@ -3171,13 +3206,22 @@ Available shapes: * `from` - triple coordinates, entity, or block value indicating one corner of the box * `to` - other corner, same format as `from` - * `'sphere'` - draws a sphere + * `'sphere'`: * Required attributes: * `center` - center of the sphere * `radius` - radius of the sphere * Optional attributes: * `level` - level of details, or grid size. The more the denser your sphere. Default level of 0, means that the level of detail will be selected automatically based on radius. + + * `'cylinder'`: + * Required attributes: + * `center` - center of the base + * `radius` - radius of the base circle + * Optional attributes: + * `axis` - cylinder direction, one of `'x'`, `'y'`, `'z'` defaults to `'y'` + * `height` - height of the cyllinder, defaults to `0`, so flat disk. Can be negative. + * `level` - level of details, see `'sphere'`. ### `create_marker(text, pos, rotation?, block?)` From 39f0b862725bb0df67506081e6797ef243fa1d83 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 10 Jun 2020 23:20:21 -0300 Subject: [PATCH 196/198] fixes --- .../carpet/network/ServerNetworkHandler.java | 16 +++++++++-- .../carpet/script/utils/ShapeDispatcher.java | 28 ++++++++++--------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/main/java/carpet/network/ServerNetworkHandler.java b/src/main/java/carpet/network/ServerNetworkHandler.java index ba6d1db0..6de0b77b 100644 --- a/src/main/java/carpet/network/ServerNetworkHandler.java +++ b/src/main/java/carpet/network/ServerNetworkHandler.java @@ -18,8 +18,8 @@ import java.util.Set; public class ServerNetworkHandler { - public static Map remoteCarpetPlayers = new HashMap<>(); - public static Set validCarpetPlayers = new HashSet<>(); + private static Map remoteCarpetPlayers = new HashMap<>(); + private static Set validCarpetPlayers = new HashSet<>(); public static void handleData(PacketByteBuf data, ServerPlayerEntity player) { @@ -63,6 +63,7 @@ public class ServerNetworkHandler public static void updateRuleWithConnectedClients(ParsedRule rule) { + if (CarpetSettings.superSecretSetting) return; for (ServerPlayerEntity player : remoteCarpetPlayers.keySet()) { player.networkHandler.sendPacket(new CustomPayloadS2CPacket( @@ -74,6 +75,7 @@ public class ServerNetworkHandler public static void updateTickSpeedToConnectedPlayers() { + if (CarpetSettings.superSecretSetting) return; for (ServerPlayerEntity player : remoteCarpetPlayers.keySet()) { player.networkHandler.sendPacket(new CustomPayloadS2CPacket( @@ -85,6 +87,7 @@ public class ServerNetworkHandler public static void broadcastCustomCommand(String command, Tag data) { + if (CarpetSettings.superSecretSetting) return; for (ServerPlayerEntity player : validCarpetPlayers) { player.networkHandler.sendPacket(new CustomPayloadS2CPacket( @@ -96,7 +99,7 @@ public class ServerNetworkHandler public static void sendCustomCommand(ServerPlayerEntity player, String command, Tag data) { - if (validCarpetPlayers.contains(player)) + if (isValidCarpetPlayer(player)) { player.networkHandler.sendPacket(new CustomPayloadS2CPacket( CarpetClient.CARPET_CHANNEL, @@ -119,6 +122,13 @@ public class ServerNetworkHandler validCarpetPlayers.clear(); } + public static boolean isValidCarpetPlayer(ServerPlayerEntity player) + { + if (CarpetSettings.superSecretSetting) return false; + return validCarpetPlayers.contains(player); + + } + private static class DataBuilder { private CompoundTag tag; diff --git a/src/main/java/carpet/script/utils/ShapeDispatcher.java b/src/main/java/carpet/script/utils/ShapeDispatcher.java index 58f30095..cebcb143 100644 --- a/src/main/java/carpet/script/utils/ShapeDispatcher.java +++ b/src/main/java/carpet/script/utils/ShapeDispatcher.java @@ -106,7 +106,7 @@ public class ShapeDispatcher List alternativePlayers = new ArrayList<>(); for (ServerPlayerEntity player : players) { - if (ServerNetworkHandler.validCarpetPlayers.contains(player)) + if (ServerNetworkHandler.isValidCarpetPlayer(player)) { clientPlayers.add(player); } @@ -328,7 +328,7 @@ public class ShapeDispatcher } public Vec3d relativiseRender(World world, Vec3d vec, float partialTick) { - if (followEntity <= 0) return vec; + if (followEntity < 0) return vec; Entity e = world.getEntityById(followEntity); if (e == null) return vec; return toAbsolute(e, vec, partialTick); @@ -344,6 +344,14 @@ public class ShapeDispatcher NumericValue.asNumber( elements.get(2)).getDouble() ); } + protected ParticleEffect replacementParticle() + { + String particleName = fa ==0 ? + String.format(Locale.ROOT , "dust %.1f %.1f %.1f 1.0", r, g, b): + String.format(Locale.ROOT , "dust %.1f %.1f %.1f 1.0", fr, fg, fb); + return getParticleData(particleName); + } + public abstract Consumer alternative(); public long key() @@ -406,8 +414,7 @@ public class ShapeDispatcher @Override public Consumer alternative() { - String particleName = String.format(Locale.ROOT , "dust %.1f %.1f %.1f 1.0", r, g, b); - ParticleEffect particle = getParticleData(particleName); + ParticleEffect particle = replacementParticle(); double density = Math.max(2.0, from.distanceTo(to) /50) / (a+0.1); return p -> { @@ -440,7 +447,7 @@ public class ShapeDispatcher double x1 = from.x; double y1 = from.y; double z1 = from.z; - double x2 = to.z; + double x2 = to.x; double y2 = to.y; double z2 = to.z; return @@ -490,10 +497,8 @@ public class ShapeDispatcher @Override public Consumer alternative() { - String particleName = String.format(Locale.ROOT , "dust %.1f %.1f %.1f 1.0", r, g, b); - ParticleEffect particle = getParticleData(particleName); + ParticleEffect particle = replacementParticle(); double density = Math.max(2.0, from.distanceTo(to) /50) / (a+0.1); - return p -> { if (p.dimension == shapeDimension) drawParticleLine( @@ -553,9 +558,7 @@ public class ShapeDispatcher @Override public Consumer alternative() { return p -> { - if (p.dimension != shapeDimension) return; - String particleName = String.format(Locale.ROOT , "dust %.1f %.1f %.1f 1.0", r, g, b); - ParticleEffect particle = getParticleData(particleName); + ParticleEffect particle = replacementParticle(); int partno = Math.min(1000,20*subdivisions); Random rand = p.world.getRandom(); ServerWorld world = p.getServerWorld(); @@ -633,8 +636,7 @@ public class ShapeDispatcher @Override public Consumer alternative() { return p -> { - String particleName = String.format(Locale.ROOT , "dust %.1f %.1f %.1f 1.0", r, g, b); - ParticleEffect particle = getParticleData(particleName); + ParticleEffect particle = replacementParticle(); int partno = (int)Math.min(1000,Math.sqrt(20*subdivisions*(1+height))); Random rand = p.world.getRandom(); ServerWorld world = p.getServerWorld(); From 6779b3bf599024348a76e3fb2433a66ab2ba83f8 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 10 Jun 2020 23:24:56 -0300 Subject: [PATCH 197/198] explosion logger cleanup --- .../logHelpers/ExplosionLogHelper.java | 281 ++++++++---------- 1 file changed, 125 insertions(+), 156 deletions(-) diff --git a/src/main/java/carpet/logging/logHelpers/ExplosionLogHelper.java b/src/main/java/carpet/logging/logHelpers/ExplosionLogHelper.java index c61b8771..e11479e5 100644 --- a/src/main/java/carpet/logging/logHelpers/ExplosionLogHelper.java +++ b/src/main/java/carpet/logging/logHelpers/ExplosionLogHelper.java @@ -1,156 +1,125 @@ -package carpet.logging.logHelpers; - -import carpet.logging.LoggerRegistry; -import carpet.utils.Messenger; -import com.google.common.collect.Lists; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; -import net.minecraft.text.BaseText; -import net.minecraft.util.math.Vec3d; -import net.minecraft.util.registry.Registry; -import net.minecraft.world.explosion.Explosion; - -import java.util.List; - -public class ExplosionLogHelper -{ - private final boolean createFire; - private final Explosion.DestructionType blockDestructionType; - public final double x; - public final double y; - public final double z; - public final Entity entity; - private final float power; - private boolean affectBlocks = false; - private List entityChangedStatusWithCount = Lists.newArrayList(); - - private static long lastGametime = 0; - private static int explosionCountInCurretGT = 0; - - public ExplosionLogHelper(Entity entity, double x, double y, double z, float power, boolean createFire, Explosion.DestructionType blockDestructionType) { - this.entity = entity; - this.power = power; - this.x = x; - this.y = y; - this.z = z; - this.createFire = createFire; - this.blockDestructionType = blockDestructionType; - } - - public void setAffectBlocks(boolean b) - { - affectBlocks = b; - } - - public void onExplosionDone(long gametime) - { - BaseText timeDisplay; - if (!(lastGametime == gametime)){ - explosionCountInCurretGT = 0; - lastGametime = gametime; - timeDisplay = Messenger.c("wb " + ">>>>>> CURRENT GAME TIME : ", "d " + gametime, "wb >>>>>>\n"); - } - else - { - timeDisplay = Messenger.s(""); - } - explosionCountInCurretGT++; - LoggerRegistry.getLogger("explosions").log( (option) -> { - switch (option) - { - case "brief": - return new BaseText[]{Messenger.c( - timeDisplay, "gb EXPLOSION", "d #" + explosionCountInCurretGT,"gb -> ", - "w P: ", "d ",Messenger.dblt("l",x ,y ,z), - "w affectBlocks: ", "m " + this.affectBlocks - )}; - case "full": - return new BaseText[]{Messenger.c( - timeDisplay, "gb EXPLOSION", "d #" + explosionCountInCurretGT,"gb -> ", - "w P: ", "d ",Messenger.dblt("l",x ,y ,z), - "w createFire: ", "m " + this.createFire, - "w power: ", "c " + this.power, - "w destructionType: ", "c " + this.blockDestructionType.name(), - "w affectBlocks: ", "m " + this.affectBlocks, - "b \n", ListToText() - )}; - } - return null; - }); - } - - public void onEntityImpacted(Entity entity, Vec3d deltaVelocity) - { - for (EntityChangedStatusWithCount e : entityChangedStatusWithCount) - { - if (e.checkIfEquals(entity, deltaVelocity)) - { - e.count++; - return; - } - } - entityChangedStatusWithCount.add(new EntityChangedStatusWithCount(entity.getPos(), entity.getType(), deltaVelocity)); - } - - public BaseText ListToText() - { - BaseText s = Messenger.s("Entities Impacted:\n"); - for (EntityChangedStatusWithCount entityChanges : entityChangedStatusWithCount) - { - s.append(entityChanges.asText()); - s.append("\n"); - } - return s; - } - - - public static class EntityChangedStatusWithCount - { - public final Vec3d entityPos; - public final EntityType entityType; - public final Vec3d deltaSpeed; - public int count; - public EntityChangedStatusWithCount(Vec3d entityPos, EntityType entityType, Vec3d deltaSpeed) - { - this.entityPos = entityPos; - this.entityType = entityType; - this.deltaSpeed = deltaSpeed; - this.count = 1; - } - - public boolean equals(EntityChangedStatusWithCount e) - { - return ( - e.entityType == this.entityType && - e.deltaSpeed.equals(this.deltaSpeed) && - e.entityPos.equals(this.entityPos) - ); - } - - public boolean checkIfEquals(Entity e, Vec3d deltaSpeed) - { - return ( - e.getType() == this.entityType && - deltaSpeed.equals(this.deltaSpeed) && - e.getPos().equals(this.entityPos) - ); - } - - public String toString() - { - return String.format("{EntityType: %s, EntityPos: %s ,DeltaSpeed: %s}", entityType.getName().asString(), entityPos.toString(), deltaSpeed.toString()); - } - - public BaseText asText() - { - return Messenger.c( - "m Entity(count="+ this.count +") of", - "l " + Registry.ENTITY_TYPE.getId(entityType), "g {", - "w P: ", "y ", Messenger.dblt("t", entityPos.x, entityPos.y, entityPos.z), - "w dV: ", "gbi " + (deltaSpeed.equals(new Vec3d(0,-0.9923437498509884d, 0)) ? "":""),"y ", Messenger.dblt("d", deltaSpeed.x, deltaSpeed.y, deltaSpeed.z), - "g }" - ); - } - - } -} +package carpet.logging.logHelpers; + +import carpet.logging.LoggerRegistry; +import carpet.utils.Messenger; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.text.BaseText; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.explosion.Explosion; + +import java.util.ArrayList; +import java.util.List; + +import static carpet.utils.Messenger.c; + +public class ExplosionLogHelper +{ + private final boolean createFire; + private final Explosion.DestructionType blockDestructionType; + public final Vec3d pos; + public final Entity entity; + private final float power; + private boolean affectBlocks = false; + private Object2IntMap impactedEntities = new Object2IntOpenHashMap<>(); + + private static long lastGametime = 0; + private static int explosionCountInCurretGT = 0; + + public ExplosionLogHelper(Entity entity, double x, double y, double z, float power, boolean createFire, Explosion.DestructionType blockDestructionType) { + this.entity = entity; + this.power = power; + this.pos = new Vec3d(x,y,z); + this.createFire = createFire; + this.blockDestructionType = blockDestructionType; + } + + public void setAffectBlocks(boolean b) + { + affectBlocks = b; + } + + public void onExplosionDone(long gametime) + { + List messages = new ArrayList<>(); + if (!(lastGametime == gametime)){ + explosionCountInCurretGT = 0; + lastGametime = gametime; + messages.add(c("wb tick : ", "d " + gametime)); + } + explosionCountInCurretGT++; + LoggerRegistry.getLogger("explosions").log( (option) -> { + if ("brief".equals(option)) + { + messages.add( c("d #" + explosionCountInCurretGT,"gb ->", + Messenger.dblt("l", pos.x, pos.y, pos.z), (affectBlocks)?"m (affects blocks)":"m (doesn't affect blocks)" )); + } + if ("full".equals(option)) + { + messages.add( c("d #" + explosionCountInCurretGT,"gb ->", Messenger.dblt("l", pos.x, pos.y, pos.z) )); + messages.add(c("w affects blocks: ", "m " + this.affectBlocks)); + messages.add(c("w creates fire: ", "m " + this.createFire)); + messages.add(c("w power: ", "c " + this.power)); + messages.add(c( "w destruction: ", "c " + this.blockDestructionType.name())); + if (impactedEntities.isEmpty()) + { + messages.add(c("w affected entities: ", "m None")); + } + else + { + messages.add(c("w affected entities:")); + impactedEntities.forEach((k, v) -> + { + messages.add(c((k.pos.equals(pos))?"r - TNT":"w - ", + Messenger.dblt((k.pos.equals(pos))?"r":"y", k.pos.x, k.pos.y, k.pos.z), "w dV", + Messenger.dblt("d", k.accel.x, k.accel.y, k.accel.z), + "w "+Registry.ENTITY_TYPE.getId(k.type).getPath(), (v>1)?"l ("+v+")":"" + )); + }); + } + } + return messages.toArray(new BaseText[0]); + }); + } + + public void onEntityImpacted(Entity entity, Vec3d accel) + { + EntityChangedStatusWithCount ent = new EntityChangedStatusWithCount(entity, accel); + impactedEntities.put(ent, impactedEntities.getOrDefault(ent, 0)+1); + } + + + public static class EntityChangedStatusWithCount + { + public final Vec3d pos; + public final EntityType type; + public final Vec3d accel; + + public EntityChangedStatusWithCount(Entity e, Vec3d accel) + { + this.pos = e.getPos(); + this.type = e.getType(); + this.accel = accel; + } + + @Override + public boolean equals(Object obj) + { + if (obj instanceof EntityChangedStatusWithCount) + { + EntityChangedStatusWithCount other = (EntityChangedStatusWithCount) obj; + return other.pos.equals(pos) && other.accel.equals(accel) && other.type.equals(type); + } + return super.equals(obj); + } + + @Override + public int hashCode() + { + return pos.hashCode()+ type.hashCode()+accel.hashCode(); + } + } +} From 5f2ee1c627392ccd811b5986b5cf1ccd9b903990 Mon Sep 17 00:00:00 2001 From: gnembon Date: Thu, 11 Jun 2020 18:39:28 -0300 Subject: [PATCH 198/198] 1.3.29 --- gradle.properties | 2 +- src/main/java/carpet/CarpetSettings.java | 2 +- src/main/resources/fabric.mod.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index fc828653..699591e3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ org.gradle.jvmargs=-Xmx1G loader_version=0.8.7+build.201 # Mod Properties - mod_version = 1.3.28+v200610 + mod_version = 1.3.29+v200611 maven_group = carpet archives_base_name = fabric-carpet diff --git a/src/main/java/carpet/CarpetSettings.java b/src/main/java/carpet/CarpetSettings.java index a8bf439c..c93402ce 100644 --- a/src/main/java/carpet/CarpetSettings.java +++ b/src/main/java/carpet/CarpetSettings.java @@ -34,7 +34,7 @@ import static carpet.settings.RuleCategory.CLIENT; @SuppressWarnings("CanBeFinal") public class CarpetSettings { - public static final String carpetVersion = "1.3.28+v200610"; + public static final String carpetVersion = "1.3.29+v200611"; public static final Logger LOG = LogManager.getLogger(); public static boolean skipGenerationChecks = false; public static boolean impendingFillSkipUpdates = false; diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index f0f2cffe..b31f6f4c 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,7 +1,7 @@ { "schemaVersion": 1, "id": "carpet", - "version": "1.3.28", + "version": "1.3.29", "name": "Carpet Mod in Fabric", "description": "Carpet made out of fabric",