From c14c78f6eedabe00ae82e7c8864f064c963a9539 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Sun, 8 Nov 2020 00:24:53 +0800 Subject: [PATCH] More events --- .../event/events/PlayerEvent.java | 26 ++++++++++++++++-- .../mixin/fabric/MixinPlayer.java | 12 +++++++++ .../mixin/fabric/MixinResultSlot.java | 27 +++++++++++++++++++ .../mixin/fabric/MixinServerPlayer.java | 25 +++++++++++++++++ .../main/resources/architectury.mixins.json | 4 +-- .../event/forge/EventHandlerImpl.java | 22 +++++++++++++++ 6 files changed, 112 insertions(+), 4 deletions(-) create mode 100644 fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinResultSlot.java diff --git a/common/src/main/java/me/shedaniel/architectury/event/events/PlayerEvent.java b/common/src/main/java/me/shedaniel/architectury/event/events/PlayerEvent.java index 0929ba5c..717d4661 100644 --- a/common/src/main/java/me/shedaniel/architectury/event/events/PlayerEvent.java +++ b/common/src/main/java/me/shedaniel/architectury/event/events/PlayerEvent.java @@ -23,9 +23,11 @@ import net.fabricmc.api.Environment; import net.minecraft.advancements.Advancement; import net.minecraft.client.player.LocalPlayer; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Container; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.ItemStack; public interface PlayerEvent { @@ -37,9 +39,13 @@ public interface PlayerEvent { @Environment(EnvType.CLIENT) Event CLIENT_PLAYER_RESPAWN = EventFactory.createLoop(ClientPlayerRespawn.class); Event PLAYER_ADVANCEMENT = EventFactory.createLoop(PlayerAdvancement.class); Event PLAYER_CLONE = EventFactory.createLoop(PlayerClone.class); + Event CRAFT_ITEM = EventFactory.createLoop(CraftItem.class); Event SMELT_ITEM = EventFactory.createLoop(SmeltItem.class); Event PICKUP_ITEM_PRE = EventFactory.createInteractionResult(PickupItemPredicate.class); Event PICKUP_ITEM_POST = EventFactory.createLoop(PickupItem.class); + Event DROP_ITEM = EventFactory.createLoop(DropItem.class); + Event OPEN_MENU = EventFactory.createLoop(OpenMenu.class); + Event CLOSE_MENU = EventFactory.createLoop(CloseMenu.class); interface PlayerJoin { void join(ServerPlayer player); @@ -61,16 +67,32 @@ public interface PlayerEvent { void award(ServerPlayer player, Advancement advancement); } + interface CraftItem { + void craft(Player player, ItemStack smelted, Container inventory); + } + interface SmeltItem { void smelt(Player player, ItemStack smelted); } interface PickupItemPredicate { - InteractionResult canPickup(Player player, ItemEntity entity, ItemStack smelted); + InteractionResult canPickup(Player player, ItemEntity entity, ItemStack stack); } interface PickupItem { - void pickup(Player player, ItemEntity entity, ItemStack smelted); + void pickup(Player player, ItemEntity entity, ItemStack stack); + } + + interface DropItem { + InteractionResult drop(Player player, ItemEntity entity); + } + + interface OpenMenu { + void open(Player player, AbstractContainerMenu menu); + } + + interface CloseMenu { + void close(Player player, AbstractContainerMenu menu); } @Environment(EnvType.CLIENT) diff --git a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinPlayer.java b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinPlayer.java index 347bb123..7b9a8013 100644 --- a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinPlayer.java +++ b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinPlayer.java @@ -16,12 +16,17 @@ package me.shedaniel.architectury.mixin.fabric; +import me.shedaniel.architectury.event.events.PlayerEvent; import me.shedaniel.architectury.event.events.TickEvent; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; 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.CallbackInfoReturnable; @Mixin(Player.class) public class MixinPlayer { @@ -34,4 +39,11 @@ public class MixinPlayer { private void postTick(CallbackInfo ci) { TickEvent.PLAYER_POST.invoker().tick((Player) (Object) this); } + + @Inject(method = "drop(Lnet/minecraft/world/item/ItemStack;ZZ)Lnet/minecraft/world/entity/item/ItemEntity;", at = @At("RETURN"), cancellable = true) + private void drop(ItemStack itemStack, boolean bl, boolean bl2, CallbackInfoReturnable cir) { + if (PlayerEvent.DROP_ITEM.invoker().drop((Player) (Object) this, cir.getReturnValue()) == InteractionResult.FAIL) { + cir.setReturnValue(null); + } + } } diff --git a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinResultSlot.java b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinResultSlot.java new file mode 100644 index 00000000..6ff7d606 --- /dev/null +++ b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinResultSlot.java @@ -0,0 +1,27 @@ +package me.shedaniel.architectury.mixin.fabric; + +import me.shedaniel.architectury.event.events.PlayerEvent; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.CraftingContainer; +import net.minecraft.world.inventory.ResultSlot; +import net.minecraft.world.item.ItemStack; +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.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ResultSlot.class) +public class MixinResultSlot { + @Shadow @Final private Player player; + + @Shadow @Final private CraftingContainer craftSlots; + + @Inject(method = "checkTakeAchievements", at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/item/ItemStack;onCraftedBy(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/player/Player;I)V", + shift = At.Shift.AFTER)) + private void craft(ItemStack itemStack, CallbackInfo ci) { + PlayerEvent.CRAFT_ITEM.invoker().craft(player, itemStack, craftSlots); + } +} diff --git a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinServerPlayer.java b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinServerPlayer.java index ade7e4fb..906eaf7e 100644 --- a/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinServerPlayer.java +++ b/fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinServerPlayer.java @@ -18,10 +18,16 @@ package me.shedaniel.architectury.mixin.fabric; import me.shedaniel.architectury.event.events.PlayerEvent; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Container; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.entity.animal.horse.AbstractHorse; 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.CallbackInfoReturnable; + +import java.util.OptionalInt; @Mixin(ServerPlayer.class) public class MixinServerPlayer { @@ -29,4 +35,23 @@ public class MixinServerPlayer { private void restoreFrom(ServerPlayer serverPlayer, boolean bl, CallbackInfo ci) { PlayerEvent.PLAYER_CLONE.invoker().clone((ServerPlayer) (Object) this, serverPlayer, bl); } + + @Inject(method = "openMenu", at = @At("RETURN")) + private void openMenu(MenuProvider menuProvider, CallbackInfoReturnable cir) { + if (cir.getReturnValue().isPresent()) { + PlayerEvent.OPEN_MENU.invoker().open((ServerPlayer) (Object) this, ((ServerPlayer) (Object) this).containerMenu); + } + } + + @Inject(method = "openHorseInventory", at = @At("RETURN")) + private void openHorseInventory(AbstractHorse abstractHorse, Container container, CallbackInfo ci) { + PlayerEvent.OPEN_MENU.invoker().open((ServerPlayer) (Object) this, ((ServerPlayer) (Object) this).containerMenu); + } + + @Inject(method = "doCloseContainer", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/AbstractContainerMenu;removed(Lnet/minecraft/world/entity/player/Player;)V", + shift = At.Shift.AFTER)) + private void doCloseContainer(CallbackInfo ci) { + PlayerEvent.CLOSE_MENU.invoker().close((ServerPlayer) (Object) this, ((ServerPlayer) (Object) this).containerMenu); + } } diff --git a/fabric/src/main/resources/architectury.mixins.json b/fabric/src/main/resources/architectury.mixins.json index cdf91db9..be21d158 100644 --- a/fabric/src/main/resources/architectury.mixins.json +++ b/fabric/src/main/resources/architectury.mixins.json @@ -13,8 +13,8 @@ ], "mixins": [ "ExplosionPreInvoker", "LivingDeathInvoker", "MixinCommands", "MixinExplosion", "MixinFurnaceResultSlot", "MixinItemEntity", "MixinLivingEntity", - "MixinPlayer", "MixinPlayerAdvancements", "MixinPlayerList", "MixinServerGamePacketListenerImpl", "MixinServerLevel", "MixinServerPlayer", - "PlayerAttackInvoker" + "MixinPlayer", "MixinPlayerAdvancements", "MixinPlayerList", "MixinResultSlot", "MixinServerGamePacketListenerImpl", "MixinServerLevel", + "MixinServerPlayer", "PlayerAttackInvoker" ], "injectors": { "defaultRequire": 1 diff --git a/forge/src/main/java/me/shedaniel/architectury/event/forge/EventHandlerImpl.java b/forge/src/main/java/me/shedaniel/architectury/event/forge/EventHandlerImpl.java index eaf39d7a..dd57ce32 100644 --- a/forge/src/main/java/me/shedaniel/architectury/event/forge/EventHandlerImpl.java +++ b/forge/src/main/java/me/shedaniel/architectury/event/forge/EventHandlerImpl.java @@ -35,11 +35,13 @@ import net.minecraftforge.event.RegisterCommandsEvent; import net.minecraftforge.event.ServerChatEvent; import net.minecraftforge.event.TickEvent.*; import net.minecraftforge.event.entity.EntityJoinWorldEvent; +import net.minecraftforge.event.entity.item.ItemTossEvent; import net.minecraftforge.event.entity.living.LivingAttackEvent; import net.minecraftforge.event.entity.living.LivingDeathEvent; import net.minecraftforge.event.entity.player.AdvancementEvent; import net.minecraftforge.event.entity.player.EntityItemPickupEvent; import net.minecraftforge.event.entity.player.ItemTooltipEvent; +import net.minecraftforge.event.entity.player.PlayerContainerEvent; import net.minecraftforge.event.entity.player.PlayerEvent.*; import net.minecraftforge.event.world.ExplosionEvent.Detonate; import net.minecraftforge.event.world.ExplosionEvent.Start; @@ -321,6 +323,11 @@ public class EventHandlerImpl implements EventHandler.Impl { } } + @SubscribeEvent + public static void event(ItemCraftedEvent event) { + PlayerEvent.CRAFT_ITEM.invoker().craft(event.getPlayer(), event.getCrafting(), event.getInventory()); + } + @SubscribeEvent public static void event(ItemSmeltedEvent event) { PlayerEvent.SMELT_ITEM.invoker().smelt(event.getPlayer(), event.getSmelting()); @@ -335,6 +342,21 @@ public class EventHandlerImpl implements EventHandler.Impl { public static void event(ItemPickupEvent event) { PlayerEvent.PICKUP_ITEM_POST.invoker().pickup(event.getPlayer(), event.getOriginalEntity(), event.getStack()); } + + @SubscribeEvent + public static void event(ItemTossEvent event) { + PlayerEvent.DROP_ITEM.invoker().drop(event.getPlayer(), event.getEntityItem()); + } + + @SubscribeEvent + public static void event(PlayerContainerEvent.Open event) { + PlayerEvent.OPEN_MENU.invoker().open(event.getPlayer(), event.getContainer()); + } + + @SubscribeEvent + public static void event(PlayerContainerEvent.Close event) { + PlayerEvent.CLOSE_MENU.invoker().close(event.getPlayer(), event.getContainer()); + } } @OnlyIn(Dist.DEDICATED_SERVER)