From d7ca974f1ab7ba9a007fa4fee916655b5866e10d Mon Sep 17 00:00:00 2001 From: gnembon Date: Fri, 27 Dec 2019 03:25:56 -0400 Subject: [PATCH] statistics, block placed and interacted events, stats event test --- .../java/carpet/fakes/StatTypeInterface.java | 6 +++ .../mixins/BlockItem_scarpetEventMixin.java | 27 +++++++++++++ ...PlayNetworkHandler_scarpetEventsMixin.java | 6 +-- ...InteractionManager_scarpetEventsMixin.java | 17 ++++++++ .../carpet/mixins/StatType_scarpetMixin.java | 22 ++++++++++ .../java/carpet/script/CarpetEventServer.java | 40 ++++++++++++++++++- .../java/carpet/script/CarpetExpression.java | 39 ++++++++++++++++++ .../carpet/script/CarpetScriptServer.java | 6 +++ .../java/carpet/script/value/EntityValue.java | 20 ++++++++++ .../java/carpet/script/value/ThreadValue.java | 5 +++ .../assets/carpet/scripts/event_test.sc | 27 +++++++++++-- src/main/resources/carpet.mixins.json | 2 + 12 files changed, 210 insertions(+), 7 deletions(-) create mode 100644 src/main/java/carpet/fakes/StatTypeInterface.java create mode 100644 src/main/java/carpet/mixins/BlockItem_scarpetEventMixin.java create mode 100644 src/main/java/carpet/mixins/StatType_scarpetMixin.java diff --git a/src/main/java/carpet/fakes/StatTypeInterface.java b/src/main/java/carpet/fakes/StatTypeInterface.java new file mode 100644 index 00000000..e4196879 --- /dev/null +++ b/src/main/java/carpet/fakes/StatTypeInterface.java @@ -0,0 +1,6 @@ +package carpet.fakes; + +public interface StatTypeInterface +{ + boolean hasStatCreated(T key); +} diff --git a/src/main/java/carpet/mixins/BlockItem_scarpetEventMixin.java b/src/main/java/carpet/mixins/BlockItem_scarpetEventMixin.java new file mode 100644 index 00000000..e6f1092b --- /dev/null +++ b/src/main/java/carpet/mixins/BlockItem_scarpetEventMixin.java @@ -0,0 +1,27 @@ +package carpet.mixins; + +import net.minecraft.item.BlockItem; +import net.minecraft.item.ItemPlacementContext; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.ActionResult; +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_PLACES_BLOCK; + +@Mixin(BlockItem.class) +public class BlockItem_scarpetEventMixin +{ + @Inject(method = "place(Lnet/minecraft/item/ItemPlacementContext;)Lnet/minecraft/util/ActionResult;", at = @At( + value = "INVOKE", + target = "Lnet/minecraft/block/Block;onPlaced(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/item/ItemStack;)V", + shift = At.Shift.AFTER + )) + private void afterPlacement(ItemPlacementContext context, CallbackInfoReturnable cir) + { + if (context.getPlayer() instanceof ServerPlayerEntity && PLAYER_PLACES_BLOCK.isNeeded()) + PLAYER_PLACES_BLOCK.onBlockPlaced((ServerPlayerEntity) context.getPlayer(), context.getBlockPos(), context.getHand(), context.getStack()); + } +} diff --git a/src/main/java/carpet/mixins/ServerPlayNetworkHandler_scarpetEventsMixin.java b/src/main/java/carpet/mixins/ServerPlayNetworkHandler_scarpetEventsMixin.java index 6e560e89..48e3ab9e 100644 --- a/src/main/java/carpet/mixins/ServerPlayNetworkHandler_scarpetEventsMixin.java +++ b/src/main/java/carpet/mixins/ServerPlayNetworkHandler_scarpetEventsMixin.java @@ -24,7 +24,7 @@ import static carpet.script.CarpetEventServer.Event.PLAYER_CLICKS_BLOCK; import static carpet.script.CarpetEventServer.Event.PLAYER_DEPLOYS_ELYTRA; import static carpet.script.CarpetEventServer.Event.PLAYER_DROPS_ITEM; import static carpet.script.CarpetEventServer.Event.PLAYER_DROPS_STACK; -import static carpet.script.CarpetEventServer.Event.PLAYER_INERACTSW_WITH_ENTITY; +import static carpet.script.CarpetEventServer.Event.PLAYER_INTERACTS_WITH_ENTITY; import static carpet.script.CarpetEventServer.Event.PLAYER_RELEASED_ITEM; import static carpet.script.CarpetEventServer.Event.PLAYER_RIDES; import static carpet.script.CarpetEventServer.Event.PLAYER_JUMPS; @@ -87,7 +87,7 @@ public class ServerPlayNetworkHandler_scarpetEventsMixin @Inject(method = "onPlayerAction", at = @At( value = "INVOKE", target = "Lnet/minecraft/server/network/ServerPlayerInteractionManager;method_14263(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/server/network/packet/PlayerActionC2SPacket$Action;Lnet/minecraft/util/math/Direction;I)V", - shift = At.Shift.AFTER + shift = At.Shift.BEFORE )) private void onClicked(PlayerActionC2SPacket packet, CallbackInfo ci) { @@ -208,7 +208,7 @@ public class ServerPlayNetworkHandler_scarpetEventsMixin )) private void onEntityInteract(PlayerInteractEntityC2SPacket playerInteractEntityC2SPacket_1, CallbackInfo ci) { - PLAYER_INERACTSW_WITH_ENTITY.onEntityAction(player, playerInteractEntityC2SPacket_1.getEntity(player.getServerWorld()), playerInteractEntityC2SPacket_1.getHand()); + PLAYER_INTERACTS_WITH_ENTITY.onEntityAction(player, playerInteractEntityC2SPacket_1.getEntity(player.getServerWorld()), playerInteractEntityC2SPacket_1.getHand()); } @Inject(method = "onPlayerInteractEntity", at = @At( diff --git a/src/main/java/carpet/mixins/ServerPlayerInteractionManager_scarpetEventsMixin.java b/src/main/java/carpet/mixins/ServerPlayerInteractionManager_scarpetEventsMixin.java index 79e83cec..a9dc05cf 100644 --- a/src/main/java/carpet/mixins/ServerPlayerInteractionManager_scarpetEventsMixin.java +++ b/src/main/java/carpet/mixins/ServerPlayerInteractionManager_scarpetEventsMixin.java @@ -3,9 +3,15 @@ package carpet.mixins; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerInteractionManager; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -14,6 +20,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import static carpet.script.CarpetEventServer.Event.PLAYER_BREAK_BLOCK; +import static carpet.script.CarpetEventServer.Event.PLAYER_INTERACTS_WITH_BLOCK; + @Mixin(ServerPlayerInteractionManager.class) public class ServerPlayerInteractionManager_scarpetEventsMixin @@ -29,4 +37,13 @@ public class ServerPlayerInteractionManager_scarpetEventsMixin { PLAYER_BREAK_BLOCK.onBlockBroken(player, blockPos_1, blockState_1); } + + @Inject(method = "interactBlock", at = @At( + value = "RETURN", + ordinal = 2 + )) + private void onBlockActivated(PlayerEntity playerArg, World world, ItemStack stack, Hand hand, BlockHitResult blockHitResult, CallbackInfoReturnable cir) + { + PLAYER_INTERACTS_WITH_BLOCK.onBlockHit(player, hand, blockHitResult); + } } diff --git a/src/main/java/carpet/mixins/StatType_scarpetMixin.java b/src/main/java/carpet/mixins/StatType_scarpetMixin.java new file mode 100644 index 00000000..97b221ad --- /dev/null +++ b/src/main/java/carpet/mixins/StatType_scarpetMixin.java @@ -0,0 +1,22 @@ +package carpet.mixins; + +import carpet.fakes.StatTypeInterface; +import net.minecraft.stat.Stat; +import net.minecraft.stat.StatType; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Map; + +@Mixin(StatType.class) +public class StatType_scarpetMixin implements StatTypeInterface +{ + @Shadow @Final private Map> stats; + + @Override + public boolean hasStatCreated(T key) + { + return this.stats.containsKey(key); + } +} diff --git a/src/main/java/carpet/script/CarpetEventServer.java b/src/main/java/carpet/script/CarpetEventServer.java index f132c638..dd8cae7b 100644 --- a/src/main/java/carpet/script/CarpetEventServer.java +++ b/src/main/java/carpet/script/CarpetEventServer.java @@ -296,6 +296,43 @@ public class CarpetEventServer }, player::getCommandSource); } }, + PLAYER_INTERACTS_WITH_BLOCK("player_interacts_with_block", new CallbackList(5)) + { + @Override + public void onBlockHit(ServerPlayerEntity player, Hand enumhand, BlockHitResult hitRes) + { + handler.call( () -> + { + BlockPos blockpos = hitRes.getBlockPos(); + Direction enumfacing = hitRes.getSide(); + Vec3d vec3d = hitRes.getPos().subtract(blockpos.getX(), blockpos.getY(), blockpos.getZ()); + return Arrays.asList( + ((c, t) -> new EntityValue(player)), + ((c, t) -> new StringValue(enumhand == Hand.MAIN_HAND ? "mainhand" : "offhand")), + ((c, t) -> new BlockValue(null, player.getServerWorld(), blockpos)), + ((c, t) -> new StringValue(enumfacing.getName())), + ((c, t) -> ListValue.of( + new NumericValue(vec3d.x), + new NumericValue(vec3d.y), + new NumericValue(vec3d.z) + )) + ); + }, player::getCommandSource); + } + }, + PLAYER_PLACES_BLOCK("player_places_block", new CallbackList(4)) + { + @Override + public void onBlockPlaced(ServerPlayerEntity player, BlockPos pos, Hand enumhand, ItemStack itemstack) + { + handler.call( () -> Arrays.asList( + ((c, t) -> new EntityValue(player)), + ((c, t) -> ListValue.fromItemStack(itemstack)), + ((c, t) -> new StringValue(enumhand == Hand.MAIN_HAND ? "mainhand" : "offhand")), + ((c, t) -> new BlockValue(null, player.getServerWorld(), pos)) + ), player::getCommandSource); + } + }, PLAYER_BREAK_BLOCK("player_breaks_block",new CallbackList(2)) { @Override @@ -307,7 +344,7 @@ public class CarpetEventServer ), player::getCommandSource); } }, - PLAYER_INERACTSW_WITH_ENTITY("player_interacts_with_entity",new CallbackList(3)) + PLAYER_INTERACTS_WITH_ENTITY("player_interacts_with_entity",new CallbackList(3)) { @Override public void onEntityAction(ServerPlayerEntity player, Entity entity, Hand enumhand) @@ -465,6 +502,7 @@ public class CarpetEventServer public void onBlockAction(ServerPlayerEntity player, BlockPos blockpos, Direction facing) { } public void onBlockHit(ServerPlayerEntity player, Hand enumhand, BlockHitResult hitRes) { } 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) { } } diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index c8e6b380..49467223 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -2,6 +2,7 @@ package carpet.script; import carpet.CarpetServer; import carpet.fakes.MinecraftServerInterface; +import carpet.fakes.StatTypeInterface; import carpet.helpers.FeatureGenerator; import carpet.mixins.ChunkTicketManager_scarpetMixin; import carpet.mixins.ServerChunkManager_scarpetMixin; @@ -68,11 +69,14 @@ import net.minecraft.server.world.ChunkTicket; import net.minecraft.server.world.ServerWorld; import net.minecraft.sound.BlockSoundGroup; import net.minecraft.sound.SoundCategory; +import net.minecraft.stat.Stat; +import net.minecraft.stat.StatType; import net.minecraft.state.StateFactory; import net.minecraft.state.property.Property; import net.minecraft.text.LiteralText; import net.minecraft.util.Clearable; import net.minecraft.util.Identifier; +import net.minecraft.util.InvalidIdentifierException; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; import net.minecraft.util.math.ChunkPos; @@ -3217,8 +3221,43 @@ public class CarpetExpression ((CarpetScriptHost)((CarpetContext)c).host).setGlobalState(tag, file); return (cc, tt) -> Value.NULL; }); + + this.expr.addLazyFunction("statistic", 3, (c, t, lv) -> + { + Value playerValue = lv.get(0).evalValue(c); + CarpetContext cc = (CarpetContext)c; + ServerPlayerEntity player = EntityValue.getPlayerByValue(cc.s.getMinecraftServer(), playerValue); + if (player == null) return LazyValue.NULL; + Identifier category; + Identifier statName; + try + { + category = new Identifier(lv.get(1).evalValue(c).getString()); + statName = new Identifier(lv.get(2).evalValue(c).getString()); + } + catch (InvalidIdentifierException e) + { + return LazyValue.NULL; + } + StatType type = Registry.STAT_TYPE.get(category); + if (type == null) + return LazyValue.NULL; + Stat stat = getStat(type, statName); + if (stat == null) + return LazyValue.NULL; + return (_c, _t) -> new NumericValue(player.getStatHandler().getStat(stat)); + }); } + private Stat getStat(StatType type, Identifier id) + { + T key = type.getRegistry().get(id); + if (key == null || !((StatTypeInterface)type).hasStatCreated(key)) + return null; + return type.getOrCreateStat(key); + } + + /** *

.

* @param expression expression diff --git a/src/main/java/carpet/script/CarpetScriptServer.java b/src/main/java/carpet/script/CarpetScriptServer.java index 75968456..0f8639a8 100644 --- a/src/main/java/carpet/script/CarpetScriptServer.java +++ b/src/main/java/carpet/script/CarpetScriptServer.java @@ -46,6 +46,7 @@ public class CarpetScriptServer private static List bundledModuleData = new ArrayList(){{ add(new BundledModule("camera")); add(new BundledModule("event_test")); + add(new BundledModule("stats_test")); }}; public CarpetScriptServer() @@ -166,6 +167,11 @@ public class CarpetScriptServer //TODO add per player modules to support player actions better on a server name = name.toLowerCase(Locale.ROOT); ModuleInterface module = getModule(name); + if (module == null) + { + Messenger.m(source, "r Failed to add "+name+" app"); + return false; + } CarpetScriptHost newHost = createMinecraftScriptHost(name, module, perPlayer, source); if (newHost == null) { diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index f1e44d99..0489a28b 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -29,6 +29,7 @@ import net.minecraft.entity.mob.MobEntityWithAi; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.CompoundTag; import net.minecraft.predicate.entity.EntityPredicates; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; @@ -93,6 +94,25 @@ public class EntityValue extends Value return entity; } + public static ServerPlayerEntity getPlayerByValue(MinecraftServer server, Value value) + { + ServerPlayerEntity player = null; + if (value instanceof EntityValue) + { + Entity e = ((EntityValue) value).getEntity(); + if (e instanceof ServerPlayerEntity) + { + player = (ServerPlayerEntity) e; + } + } + else + { + String playerName = value.getString(); + player = server.getPlayerManager().getPlayer(playerName); + } + return player; + } + @Override public String getString() { diff --git a/src/main/java/carpet/script/value/ThreadValue.java b/src/main/java/carpet/script/value/ThreadValue.java index 40500011..42682197 100644 --- a/src/main/java/carpet/script/value/ThreadValue.java +++ b/src/main/java/carpet/script/value/ThreadValue.java @@ -37,6 +37,11 @@ public class ThreadValue extends Value return taskFuture.getNow(Value.NULL).getString(); } + public Value getValue() + { + return taskFuture.getNow(Value.NULL); + } + @Override public boolean getBoolean() { diff --git a/src/main/resources/assets/carpet/scripts/event_test.sc b/src/main/resources/assets/carpet/scripts/event_test.sc index 4ac8d59e..80e2346e 100644 --- a/src/main/resources/assets/carpet/scripts/event_test.sc +++ b/src/main/resources/assets/carpet/scripts/event_test.sc @@ -160,7 +160,28 @@ __on_player_drops_stack(player) -> ( print('Player '+player+' drops current stack.') ); -__on_statistic(player, category, event, value) -> +__on_player_interacts_with_block(player, hand, block, face, hitvec) -> ( - print('__on_statistic(player, category, event, value) -> ['+join(', ',l(player, category, event, value))+']'); -); \ No newline at end of file + print(''); + print('__on_player_interacts_with_block(player, hand, block, face, hitvec) '); + print('block right clicked by player:'); + print(' - player: '+player); + print(' - hand: '+hand); + print(' - block: '+block+' at '+map(pos(block), str('%.2f',_))); + print(' - face: '+face); + print(' - hitvec: '+map(hitvec, str('%.2f',_))) +); +__on_player_places_block(player, item_tuple, hand, block) -> +( + l(item, count, nbt) = item_tuple || l('None', 0, null); + print(''); + print('__on_player_places_block(player, item_tuple, hand, block)'); + print('player places a block:'); + print(' - player: '+player); + print(' - block: '+block+' at '+map(pos(block), str('%.2f',_))); + print(' - hand: '+hand); + print(' - item:'); + print(' > name: '+item); + print(' > count: '+count); + print(' > nbt: '+nbt); +); diff --git a/src/main/resources/carpet.mixins.json b/src/main/resources/carpet.mixins.json index 0ff0fc32..6191c3a2 100644 --- a/src/main/resources/carpet.mixins.json +++ b/src/main/resources/carpet.mixins.json @@ -141,9 +141,11 @@ "DamageTracker_scarpetEventMixin", "ServerPlayerEntity_scarpetEventMixin", "FallingBlockEntity_scarpetEventsMixin", + "BlockItem_scarpetEventMixin", "ChunkTicketManager_scarpetMixin", "ServerChunkManager_scarpetMixin", + "StatType_scarpetMixin", "PistonBlock_movableTEMixin",