diff --git a/src/main/java/dev/dubhe/gugle/carpet/api/menu/control/Button.java b/src/main/java/dev/dubhe/gugle/carpet/api/menu/control/Button.java index a7d1f12..6dadaf9 100644 --- a/src/main/java/dev/dubhe/gugle/carpet/api/menu/control/Button.java +++ b/src/main/java/dev/dubhe/gugle/carpet/api/menu/control/Button.java @@ -24,6 +24,7 @@ public class Button { private final ItemStack onItem; private final ItemStack offItem; CompoundTag compoundTag = new CompoundTag(); + public static final String GCA_CLEAR = "GcaClear"; private final List turnOnConsumers = new ArrayList<>(); @@ -69,7 +70,7 @@ public Button(boolean defaultState, Item onItem, Item offItem, int itemCount) { public Button(boolean defaultState, Item onItem, Item offItem, int itemCount, Component onText, Component offText) { this.flag = defaultState; - this.compoundTag.putBoolean("GcaClear", true); + this.compoundTag.putBoolean(GCA_CLEAR, true); ItemStack onItemStack = new ItemStack(onItem, itemCount); onItemStack.set(DataComponents.CUSTOM_DATA, CustomData.of(compoundTag)); @@ -84,7 +85,7 @@ public Button(boolean defaultState, Item onItem, Item offItem, int itemCount, Co public Button(boolean defaultState, @NotNull ItemStack onItem, @NotNull ItemStack offItem) { this.flag = defaultState; - this.compoundTag.putBoolean("GcaClear", true); + this.compoundTag.putBoolean(GCA_CLEAR, true); ItemStack onItemStack = onItem.copy(); onItemStack.set(DataComponents.CUSTOM_DATA, CustomData.of(compoundTag.copy())); diff --git a/src/main/java/dev/dubhe/gugle/carpet/mixin/AbstractContainerMenuMixin.java b/src/main/java/dev/dubhe/gugle/carpet/mixin/AbstractContainerMenuMixin.java index 3ae28ff..f1d6797 100644 --- a/src/main/java/dev/dubhe/gugle/carpet/mixin/AbstractContainerMenuMixin.java +++ b/src/main/java/dev/dubhe/gugle/carpet/mixin/AbstractContainerMenuMixin.java @@ -1,5 +1,6 @@ package dev.dubhe.gugle.carpet.mixin; +import dev.dubhe.gugle.carpet.api.menu.control.Button; import net.minecraft.core.component.DataComponents; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -26,10 +27,10 @@ private void doClick(int slotIndex, int button, ClickType clickType, Player play Slot slot = gca$self.getSlot(slotIndex); ItemStack itemStack = slot.getItem(); CustomData customData = itemStack.get(DataComponents.CUSTOM_DATA); - if (customData == null || customData.copyTag().get("GcaClear") == null) { + if (customData == null || customData.copyTag().get(Button.GCA_CLEAR) == null) { return; } - if (customData.copyTag().getBoolean("GcaClear")) { + if (customData.copyTag().getBoolean(Button.GCA_CLEAR)) { itemStack.setCount(0); ci.cancel(); } diff --git a/src/main/java/dev/dubhe/gugle/carpet/mixin/ItemStackMixin.java b/src/main/java/dev/dubhe/gugle/carpet/mixin/ItemStackMixin.java index fa8e301..dff3573 100644 --- a/src/main/java/dev/dubhe/gugle/carpet/mixin/ItemStackMixin.java +++ b/src/main/java/dev/dubhe/gugle/carpet/mixin/ItemStackMixin.java @@ -2,16 +2,24 @@ import carpet.patches.EntityPlayerMPFake; import dev.dubhe.gugle.carpet.GcaSetting; +import dev.dubhe.gugle.carpet.api.menu.control.Button; import dev.dubhe.gugle.carpet.tools.FakePlayerAutoReplaceTool; import dev.dubhe.gugle.carpet.tools.FakePlayerAutoReplenishment; +import net.minecraft.core.component.DataComponentMap; +import net.minecraft.core.component.DataComponents; +import net.minecraft.core.component.PatchedDataComponentMap; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.CustomData; import net.minecraft.world.level.Level; +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; @@ -19,6 +27,13 @@ @Mixin(ItemStack.class) abstract class ItemStackMixin { + @Shadow + public abstract Item getItem(); + + @Shadow + @Final + PatchedDataComponentMap components; + @Inject(method = "use", at = @At("HEAD")) private void use(Level level, Player player, InteractionHand usedHand, CallbackInfoReturnable> cir) { if (GcaSetting.fakePlayerAutoReplenishment && player instanceof EntityPlayerMPFake fakePlayer) { @@ -32,5 +47,14 @@ private void hurtAndBreak(int i, LivingEntity livingEntity, EquipmentSlot equipm FakePlayerAutoReplaceTool.autoReplaceTool(fakePlayer); } } + + @Inject(method = "getComponents", at = @At("HEAD"), cancellable = true) + private void getComponents(CallbackInfoReturnable cir) { + CustomData customData = this.components.get(DataComponents.CUSTOM_DATA); + if (customData == null || customData.copyTag().get(Button.GCA_CLEAR) == null) { + return; + } + cir.setReturnValue(this.components); + } } diff --git a/src/main/java/dev/dubhe/gugle/carpet/mixin/PlayerMixin.java b/src/main/java/dev/dubhe/gugle/carpet/mixin/PlayerMixin.java index b85239a..3a23cdd 100644 --- a/src/main/java/dev/dubhe/gugle/carpet/mixin/PlayerMixin.java +++ b/src/main/java/dev/dubhe/gugle/carpet/mixin/PlayerMixin.java @@ -9,6 +9,7 @@ import dev.dubhe.gugle.carpet.tools.FakePlayerEnderChestContainer; import dev.dubhe.gugle.carpet.tools.FakePlayerInventoryContainer; import dev.dubhe.gugle.carpet.tools.FakePlayerInventoryMenu; +import net.minecraft.client.player.RemotePlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.SimpleMenuProvider; @@ -40,11 +41,22 @@ private void tick(CallbackInfo ci) { @WrapOperation(method = "interactOn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;interact(Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/InteractionHand;)Lnet/minecraft/world/InteractionResult;")) private InteractionResult interactOn(Entity entity, Player player, InteractionHand hand, Operation original) { - if (!(entity instanceof EntityPlayerMPFake fakePlayer)) { - return original.call(entity, player, hand); + if (entity instanceof EntityPlayerMPFake fakePlayer) { + // 打开物品栏 + return this.openInventory(player, fakePlayer); + } else if (entity instanceof RemotePlayer) { + // 在客户端中,玩家可以与客户端的被交互玩家交互并返回PASS,这时交互玩家手上如果拿着可以使用的物品,则物品会被使用 + // 所以如果判断被交互实体是客户端玩家,返回SUCCESS + return InteractionResult.SUCCESS; } + return original.call(entity, player, hand); + } + + @Unique + private InteractionResult openInventory(Player player, EntityPlayerMPFake fakePlayer) { SimpleMenuProvider provider = null; if (player.isShiftKeyDown()) { + // 打开末影箱 if (GcaSetting.openFakePlayerEnderChest) { provider = new SimpleMenuProvider( (i, inventory, p) -> ChestMenu.sixRows( @@ -54,6 +66,7 @@ private InteractionResult interactOn(Entity entity, Player player, InteractionHa ComponentTranslate.trans("gca.player.ender_chest", fakePlayer.getDisplayName()) ); } else { + // 打开额外功能菜单 provider = new SimpleMenuProvider( (i, inventory, p) -> ChestMenu.threeRows( i, inventory, @@ -63,6 +76,7 @@ private InteractionResult interactOn(Entity entity, Player player, InteractionHa ); } } else if (GcaSetting.openFakePlayerInventory) { + // 打开物品栏 provider = new SimpleMenuProvider( (i, inventory, p) -> new FakePlayerInventoryMenu( i, inventory, @@ -71,9 +85,11 @@ private InteractionResult interactOn(Entity entity, Player player, InteractionHa ComponentTranslate.trans("gca.player.inventory", fakePlayer.getDisplayName()) ); } - if (provider != null) { - player.openMenu(provider); + + if (provider == null) { + return InteractionResult.PASS; } - return InteractionResult.SUCCESS; + player.openMenu(provider); + return InteractionResult.CONSUME; } }