shedaniel 4 жил өмнө
parent
commit
c14c78f6ee

+ 24 - 2
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.advancements.Advancement;
 import net.minecraft.client.player.LocalPlayer;
 import net.minecraft.client.player.LocalPlayer;
 import net.minecraft.server.level.ServerPlayer;
 import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.world.Container;
 import net.minecraft.world.InteractionResult;
 import net.minecraft.world.InteractionResult;
 import net.minecraft.world.entity.item.ItemEntity;
 import net.minecraft.world.entity.item.ItemEntity;
 import net.minecraft.world.entity.player.Player;
 import net.minecraft.world.entity.player.Player;
+import net.minecraft.world.inventory.AbstractContainerMenu;
 import net.minecraft.world.item.ItemStack;
 import net.minecraft.world.item.ItemStack;
 
 
 public interface PlayerEvent {
 public interface PlayerEvent {
@@ -37,9 +39,13 @@ public interface PlayerEvent {
     @Environment(EnvType.CLIENT) Event<ClientPlayerRespawn> CLIENT_PLAYER_RESPAWN = EventFactory.createLoop(ClientPlayerRespawn.class);
     @Environment(EnvType.CLIENT) Event<ClientPlayerRespawn> CLIENT_PLAYER_RESPAWN = EventFactory.createLoop(ClientPlayerRespawn.class);
     Event<PlayerAdvancement> PLAYER_ADVANCEMENT = EventFactory.createLoop(PlayerAdvancement.class);
     Event<PlayerAdvancement> PLAYER_ADVANCEMENT = EventFactory.createLoop(PlayerAdvancement.class);
     Event<PlayerClone> PLAYER_CLONE = EventFactory.createLoop(PlayerClone.class);
     Event<PlayerClone> PLAYER_CLONE = EventFactory.createLoop(PlayerClone.class);
+    Event<CraftItem> CRAFT_ITEM = EventFactory.createLoop(CraftItem.class);
     Event<SmeltItem> SMELT_ITEM = EventFactory.createLoop(SmeltItem.class);
     Event<SmeltItem> SMELT_ITEM = EventFactory.createLoop(SmeltItem.class);
     Event<PickupItemPredicate> PICKUP_ITEM_PRE = EventFactory.createInteractionResult(PickupItemPredicate.class);
     Event<PickupItemPredicate> PICKUP_ITEM_PRE = EventFactory.createInteractionResult(PickupItemPredicate.class);
     Event<PickupItem> PICKUP_ITEM_POST = EventFactory.createLoop(PickupItem.class);
     Event<PickupItem> PICKUP_ITEM_POST = EventFactory.createLoop(PickupItem.class);
+    Event<DropItem> DROP_ITEM = EventFactory.createLoop(DropItem.class);
+    Event<OpenMenu> OPEN_MENU = EventFactory.createLoop(OpenMenu.class);
+    Event<CloseMenu> CLOSE_MENU = EventFactory.createLoop(CloseMenu.class);
     
     
     interface PlayerJoin {
     interface PlayerJoin {
         void join(ServerPlayer player);
         void join(ServerPlayer player);
@@ -61,16 +67,32 @@ public interface PlayerEvent {
         void award(ServerPlayer player, Advancement advancement);
         void award(ServerPlayer player, Advancement advancement);
     }
     }
     
     
+    interface CraftItem {
+        void craft(Player player, ItemStack smelted, Container inventory);
+    }
+    
     interface SmeltItem {
     interface SmeltItem {
         void smelt(Player player, ItemStack smelted);
         void smelt(Player player, ItemStack smelted);
     }
     }
     
     
     interface PickupItemPredicate {
     interface PickupItemPredicate {
-        InteractionResult canPickup(Player player, ItemEntity entity, ItemStack smelted);
+        InteractionResult canPickup(Player player, ItemEntity entity, ItemStack stack);
     }
     }
     
     
     interface PickupItem {
     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)
     @Environment(EnvType.CLIENT)

+ 12 - 0
fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinPlayer.java

@@ -16,12 +16,17 @@
 
 
 package me.shedaniel.architectury.mixin.fabric;
 package me.shedaniel.architectury.mixin.fabric;
 
 
+import me.shedaniel.architectury.event.events.PlayerEvent;
 import me.shedaniel.architectury.event.events.TickEvent;
 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.entity.player.Player;
+import net.minecraft.world.item.ItemStack;
 import org.spongepowered.asm.mixin.Mixin;
 import org.spongepowered.asm.mixin.Mixin;
 import org.spongepowered.asm.mixin.injection.At;
 import org.spongepowered.asm.mixin.injection.At;
 import org.spongepowered.asm.mixin.injection.Inject;
 import org.spongepowered.asm.mixin.injection.Inject;
 import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
 import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
 
 
 @Mixin(Player.class)
 @Mixin(Player.class)
 public class MixinPlayer {
 public class MixinPlayer {
@@ -34,4 +39,11 @@ public class MixinPlayer {
     private void postTick(CallbackInfo ci) {
     private void postTick(CallbackInfo ci) {
         TickEvent.PLAYER_POST.invoker().tick((Player) (Object) this);
         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<ItemEntity> cir) {
+        if (PlayerEvent.DROP_ITEM.invoker().drop((Player) (Object) this, cir.getReturnValue()) == InteractionResult.FAIL) {
+            cir.setReturnValue(null);
+        }
+    }
 }
 }

+ 27 - 0
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);
+    }
+}

+ 25 - 0
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 me.shedaniel.architectury.event.events.PlayerEvent;
 import net.minecraft.server.level.ServerPlayer;
 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.Mixin;
 import org.spongepowered.asm.mixin.injection.At;
 import org.spongepowered.asm.mixin.injection.At;
 import org.spongepowered.asm.mixin.injection.Inject;
 import org.spongepowered.asm.mixin.injection.Inject;
 import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
 import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+
+import java.util.OptionalInt;
 
 
 @Mixin(ServerPlayer.class)
 @Mixin(ServerPlayer.class)
 public class MixinServerPlayer {
 public class MixinServerPlayer {
@@ -29,4 +35,23 @@ public class MixinServerPlayer {
     private void restoreFrom(ServerPlayer serverPlayer, boolean bl, CallbackInfo ci) {
     private void restoreFrom(ServerPlayer serverPlayer, boolean bl, CallbackInfo ci) {
         PlayerEvent.PLAYER_CLONE.invoker().clone((ServerPlayer) (Object) this, serverPlayer, bl);
         PlayerEvent.PLAYER_CLONE.invoker().clone((ServerPlayer) (Object) this, serverPlayer, bl);
     }
     }
+    
+    @Inject(method = "openMenu", at = @At("RETURN"))
+    private void openMenu(MenuProvider menuProvider, CallbackInfoReturnable<OptionalInt> 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);
+    }
 }
 }

+ 2 - 2
fabric/src/main/resources/architectury.mixins.json

@@ -13,8 +13,8 @@
   ],
   ],
   "mixins": [
   "mixins": [
     "ExplosionPreInvoker", "LivingDeathInvoker", "MixinCommands", "MixinExplosion", "MixinFurnaceResultSlot", "MixinItemEntity", "MixinLivingEntity",
     "ExplosionPreInvoker", "LivingDeathInvoker", "MixinCommands", "MixinExplosion", "MixinFurnaceResultSlot", "MixinItemEntity", "MixinLivingEntity",
-    "MixinPlayer", "MixinPlayerAdvancements", "MixinPlayerList", "MixinServerGamePacketListenerImpl", "MixinServerLevel", "MixinServerPlayer",
-    "PlayerAttackInvoker"
+    "MixinPlayer", "MixinPlayerAdvancements", "MixinPlayerList", "MixinResultSlot", "MixinServerGamePacketListenerImpl", "MixinServerLevel",
+    "MixinServerPlayer", "PlayerAttackInvoker"
   ],
   ],
   "injectors": {
   "injectors": {
     "defaultRequire": 1
     "defaultRequire": 1

+ 22 - 0
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.ServerChatEvent;
 import net.minecraftforge.event.TickEvent.*;
 import net.minecraftforge.event.TickEvent.*;
 import net.minecraftforge.event.entity.EntityJoinWorldEvent;
 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.LivingAttackEvent;
 import net.minecraftforge.event.entity.living.LivingDeathEvent;
 import net.minecraftforge.event.entity.living.LivingDeathEvent;
 import net.minecraftforge.event.entity.player.AdvancementEvent;
 import net.minecraftforge.event.entity.player.AdvancementEvent;
 import net.minecraftforge.event.entity.player.EntityItemPickupEvent;
 import net.minecraftforge.event.entity.player.EntityItemPickupEvent;
 import net.minecraftforge.event.entity.player.ItemTooltipEvent;
 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.entity.player.PlayerEvent.*;
 import net.minecraftforge.event.world.ExplosionEvent.Detonate;
 import net.minecraftforge.event.world.ExplosionEvent.Detonate;
 import net.minecraftforge.event.world.ExplosionEvent.Start;
 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
         @SubscribeEvent
         public static void event(ItemSmeltedEvent event) {
         public static void event(ItemSmeltedEvent event) {
             PlayerEvent.SMELT_ITEM.invoker().smelt(event.getPlayer(), event.getSmelting());
             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) {
         public static void event(ItemPickupEvent event) {
             PlayerEvent.PICKUP_ITEM_POST.invoker().pickup(event.getPlayer(), event.getOriginalEntity(), event.getStack());
             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)
     @OnlyIn(Dist.DEDICATED_SERVER)