From cbe2082066fe0b39e16f3407b4815095731f387d Mon Sep 17 00:00:00 2001 From: cdqtzrc <3286637847@qq.com> Date: Sat, 15 Jun 2024 21:37:43 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E4=B8=80=E5=A4=84=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=E9=87=8C=E7=9A=84=E9=94=99=E5=88=AB=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dev/dubhe/gugle/carpet/tools/FakePlayerInventoryMenu.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/dev/dubhe/gugle/carpet/tools/FakePlayerInventoryMenu.java b/src/main/java/dev/dubhe/gugle/carpet/tools/FakePlayerInventoryMenu.java index dd6b05e..7a77353 100644 --- a/src/main/java/dev/dubhe/gugle/carpet/tools/FakePlayerInventoryMenu.java +++ b/src/main/java/dev/dubhe/gugle/carpet/tools/FakePlayerInventoryMenu.java @@ -27,7 +27,7 @@ public FakePlayerInventoryMenu(int i, Inventory inventory, Container container) return ItemStack.EMPTY; } } else if (slotStack.getItem() instanceof ArmorItem armorItem) { - // 如果是盔甲,移动的盔甲槽 + // 如果是盔甲,移动到盔甲槽 int ordinal = armorItem.getType().ordinal(); if (moveToArmor(slotStack, ordinal) || moveToInventory(slotStack)) { return ItemStack.EMPTY; From 6b35988bf2701fd3b57869017d9a452ae6cf0e3d Mon Sep 17 00:00:00 2001 From: cdqtzrc <3286637847@qq.com> Date: Wed, 19 Jun 2024 23:09:42 +0800 Subject: [PATCH 2/2] MC1.21 --- build.gradle | 2 +- gradle.properties | 6 +- gradle/wrapper/gradle-wrapper.properties | 2 +- .../dev/dubhe/gugle/carpet/GcaExtension.java | 16 +-- .../api/{Function.java => Consumer.java} | 3 +- .../gugle/carpet/api/menu/control/Button.java | 50 ++++---- .../gugle/carpet/api/tools/text/Color.java | 33 +++--- .../mixin/AbstractContainerMenuMixin.java | 26 +++-- .../gugle/carpet/mixin/AxeItemMixin.java | 7 +- .../gugle/carpet/mixin/EntityInvoker.java | 11 ++ .../mixin/EntityPlayerMPFakeInvoker.java | 17 +++ .../gugle/carpet/mixin/ItemStackMixin.java | 9 +- .../gugle/carpet/mixin/PlayerAccessor.java | 14 +++ .../dubhe/gugle/carpet/mixin/PlayerMixin.java | 48 ++++---- .../gugle/carpet/mixin/ServerLevelMixin.java | 8 +- .../carpet/mixin/ServerPlaceRecipeMixin.java | 12 +- .../gugle/carpet/mixin/SignBlockMixin.java | 11 +- .../tools/FakePlayerAutoReplenishment.java | 110 ++++++++++-------- .../tools/FakePlayerInventoryContainer.java | 48 +++----- .../carpet/tools/FakePlayerInventoryMenu.java | 3 +- .../carpet/tools/FakePlayerResident.java | 110 ++++++++++++++---- src/main/resources/gca.mixins.json | 7 +- 22 files changed, 335 insertions(+), 218 deletions(-) rename src/main/java/dev/dubhe/gugle/carpet/api/{Function.java => Consumer.java} (73%) create mode 100644 src/main/java/dev/dubhe/gugle/carpet/mixin/EntityInvoker.java create mode 100644 src/main/java/dev/dubhe/gugle/carpet/mixin/EntityPlayerMPFakeInvoker.java create mode 100644 src/main/java/dev/dubhe/gugle/carpet/mixin/PlayerAccessor.java diff --git a/build.gradle b/build.gradle index 7941b5b..953b6de 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '0.12-SNAPSHOT' + id 'fabric-loom' version '1.6-SNAPSHOT' id 'maven-publish' } diff --git a/gradle.properties b/gradle.properties index 3b96ab7..c74e11c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,8 +2,8 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://modmuss50.me/fabric.html -minecraft_version=1.20.1 -loader_version=0.14.21 +minecraft_version=1.21 +loader_version=0.15.11 # parchment_version=2022.08.14 # Mod Properties mod_version=2.8.0 @@ -11,5 +11,5 @@ build_number=undefined maven_group=dev.dubhe.gugle archives_base_name=gugle-carpet-addition -carpet_core_version=4573334 +carpet_core_version=5425253 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index aa991fc..17655d0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/dev/dubhe/gugle/carpet/GcaExtension.java b/src/main/java/dev/dubhe/gugle/carpet/GcaExtension.java index e147f5f..f81f88e 100644 --- a/src/main/java/dev/dubhe/gugle/carpet/GcaExtension.java +++ b/src/main/java/dev/dubhe/gugle/carpet/GcaExtension.java @@ -7,7 +7,7 @@ import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import dev.dubhe.gugle.carpet.api.Function; +import dev.dubhe.gugle.carpet.api.Consumer; import dev.dubhe.gugle.carpet.api.tools.text.ComponentTranslate; import dev.dubhe.gugle.carpet.tools.FakePlayerEnderChestContainer; import dev.dubhe.gugle.carpet.tools.FakePlayerInventoryContainer; @@ -40,12 +40,12 @@ public class GcaExtension implements CarpetExtension, ModInitializer { public static final Logger LOGGER = LogManager.getLogger(MOD_ID); public static @NotNull ResourceLocation id(String path) { - return new ResourceLocation(MOD_ID, path); + return ResourceLocation.fromNamespaceAndPath(MOD_ID, path); } public static final HashMap> fakePlayerInventoryContainerMap = new HashMap<>(); - public static final List> planFunction = new ArrayList<>(); + public static final List> planFunction = new ArrayList<>(); static { CarpetServer.manageExtension(new GcaExtension()); @@ -54,7 +54,7 @@ public class GcaExtension implements CarpetExtension, ModInitializer { @Override public void onPlayerLoggedIn(ServerPlayer player) { GcaExtension.fakePlayerInventoryContainerMap.put(player, Map.entry( - new FakePlayerInventoryContainer(player), new FakePlayerEnderChestContainer(player) + new FakePlayerInventoryContainer(player), new FakePlayerEnderChestContainer(player) )); } @@ -77,13 +77,7 @@ public static void onServerStop(MinecraftServer server) { fakePlayerList.add(username, FakePlayerResident.save(player)); }); File file = server.getWorldPath(LevelResource.ROOT).resolve("fake_player.gca.json").toFile(); - if (!file.isFile()) { - try { - file.createNewFile(); - } catch (IOException e) { - GcaExtension.LOGGER.error(e.getMessage(), e); - } - } + // 文件不需要存在 try (BufferedWriter bfw = Files.newBufferedWriter(file.toPath(), StandardCharsets.UTF_8)) { bfw.write(GSON.toJson(fakePlayerList)); } catch (IOException e) { diff --git a/src/main/java/dev/dubhe/gugle/carpet/api/Function.java b/src/main/java/dev/dubhe/gugle/carpet/api/Consumer.java similarity index 73% rename from src/main/java/dev/dubhe/gugle/carpet/api/Function.java rename to src/main/java/dev/dubhe/gugle/carpet/api/Consumer.java index 0424cae..b48d00c 100644 --- a/src/main/java/dev/dubhe/gugle/carpet/api/Function.java +++ b/src/main/java/dev/dubhe/gugle/carpet/api/Consumer.java @@ -1,7 +1,6 @@ package dev.dubhe.gugle.carpet.api; @FunctionalInterface -public interface Function { - +public interface Consumer { void accept(); } 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 b86047a..a7d1f12 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 @@ -1,8 +1,9 @@ package dev.dubhe.gugle.carpet.api.menu.control; -import dev.dubhe.gugle.carpet.api.Function; +import dev.dubhe.gugle.carpet.api.Consumer; import dev.dubhe.gugle.carpet.api.tools.text.Color; import dev.dubhe.gugle.carpet.api.tools.text.ComponentTranslate; +import net.minecraft.core.component.DataComponents; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Style; @@ -10,6 +11,7 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; +import net.minecraft.world.item.component.CustomData; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -23,9 +25,9 @@ public class Button { private final ItemStack offItem; CompoundTag compoundTag = new CompoundTag(); - private final List turnOnFunctions = new ArrayList<>(); + private final List turnOnConsumers = new ArrayList<>(); - private final List turnOffFunctions = new ArrayList<>(); + private final List turnOffConsumers = new ArrayList<>(); public Button() { this(true, Items.BARRIER, Items.STRUCTURE_VOID); @@ -49,8 +51,8 @@ public Button(boolean defaultState, Component onText, Component offText) { public Button(boolean defaultState, String key) { this(defaultState, Items.BARRIER, Items.STRUCTURE_VOID, 1, - ComponentTranslate.trans(key, Color.GREEN, Style.EMPTY.withBold(true).withItalic(false), ComponentTranslate.trans("gca.button.on")), - ComponentTranslate.trans(key, Color.RED, Style.EMPTY.withBold(true).withItalic(false), ComponentTranslate.trans("gca.button.off")) + ComponentTranslate.trans(key, Color.GREEN, Style.EMPTY.withBold(true).withItalic(false), ComponentTranslate.trans("gca.button.on")), + ComponentTranslate.trans(key, Color.RED, Style.EMPTY.withBold(true).withItalic(false), ComponentTranslate.trans("gca.button.off")) ); } @@ -60,8 +62,8 @@ public Button(boolean defaultState, Item onItem, Item offItem) { public Button(boolean defaultState, Item onItem, Item offItem, int itemCount) { this(defaultState, onItem, offItem, itemCount, - ComponentTranslate.trans("gca.button.on", Color.GREEN, Style.EMPTY.withBold(true).withItalic(false)), - ComponentTranslate.trans("gca.button.off", Color.RED, Style.EMPTY.withBold(true).withItalic(false)) + ComponentTranslate.trans("gca.button.on", Color.GREEN, Style.EMPTY.withBold(true).withItalic(false)), + ComponentTranslate.trans("gca.button.off", Color.RED, Style.EMPTY.withBold(true).withItalic(false)) ); } @@ -70,13 +72,13 @@ public Button(boolean defaultState, Item onItem, Item offItem, int itemCount, Co this.compoundTag.putBoolean("GcaClear", true); ItemStack onItemStack = new ItemStack(onItem, itemCount); - onItemStack.setTag(compoundTag.copy()); - onItemStack.setHoverName(onText); + onItemStack.set(DataComponents.CUSTOM_DATA, CustomData.of(compoundTag)); + onItemStack.set(DataComponents.ITEM_NAME, onText); this.onItem = onItemStack; ItemStack offItemStack = new ItemStack(offItem, itemCount); - offItemStack.setTag(compoundTag.copy()); - offItemStack.setHoverName(offText); + offItemStack.set(DataComponents.CUSTOM_DATA, CustomData.of(compoundTag.copy())); + offItemStack.set(DataComponents.ITEM_NAME, offText); this.offItem = offItemStack; } @@ -85,11 +87,11 @@ public Button(boolean defaultState, @NotNull ItemStack onItem, @NotNull ItemStac this.compoundTag.putBoolean("GcaClear", true); ItemStack onItemStack = onItem.copy(); - onItemStack.setTag(compoundTag.copy()); + onItemStack.set(DataComponents.CUSTOM_DATA, CustomData.of(compoundTag.copy())); this.onItem = onItemStack; ItemStack offItemStack = offItem.copy(); - offItemStack.setTag(compoundTag.copy()); + offItemStack.set(DataComponents.CUSTOM_DATA, CustomData.of(compoundTag.copy())); this.offItem = offItemStack; } @@ -117,9 +119,9 @@ public void checkButton(Container container, int slot) { public void updateButton(@NotNull Container container, int slot, @NotNull ItemStack onItemStack, ItemStack offItemStack) { if (!( - container.getItem(slot).is(onItemStack.getItem()) || - container.getItem(slot).is(offItemStack.getItem()) || - container.getItem(slot).isEmpty() + container.getItem(slot).is(onItemStack.getItem()) || + container.getItem(slot).is(offItemStack.getItem()) || + container.getItem(slot).isEmpty() )) { return; } @@ -130,12 +132,12 @@ public void updateButton(@NotNull Container container, int slot, @NotNull ItemSt } } - public void addTurnOnFunction(Function function) { - this.turnOnFunctions.add(function); + public void addTurnOnFunction(Consumer consumer) { + this.turnOnConsumers.add(consumer); } - public void addTurnOffFunction(Function function) { - this.turnOffFunctions.add(function); + public void addTurnOffFunction(Consumer consumer) { + this.turnOffConsumers.add(consumer); } public void turnOnWithoutFunction() { @@ -157,14 +159,14 @@ public void turnOff() { } public void runTurnOnFunction() { - for (Function turnOnFunction : this.turnOnFunctions) { - turnOnFunction.accept(); + for (Consumer turnOnConsumer : this.turnOnConsumers) { + turnOnConsumer.accept(); } } public void runTurnOffFunction() { - for (Function turnOffFunction : this.turnOffFunctions) { - turnOffFunction.accept(); + for (Consumer turnOffConsumer : this.turnOffConsumers) { + turnOffConsumer.accept(); } } diff --git a/src/main/java/dev/dubhe/gugle/carpet/api/tools/text/Color.java b/src/main/java/dev/dubhe/gugle/carpet/api/tools/text/Color.java index d8d36a9..b3550f0 100644 --- a/src/main/java/dev/dubhe/gugle/carpet/api/tools/text/Color.java +++ b/src/main/java/dev/dubhe/gugle/carpet/api/tools/text/Color.java @@ -2,39 +2,40 @@ import net.minecraft.network.chat.TextColor; +@SuppressWarnings("unused") public class Color { - public static final TextColor BLACK = TextColor.parseColor("#000000"); + public static final TextColor BLACK = TextColor.parseColor("#000000").getOrThrow(); - public static final TextColor DARK_BLUE = TextColor.parseColor("#0000AA"); + public static final TextColor DARK_BLUE = TextColor.parseColor("#0000AA").getOrThrow(); - public static final TextColor DARK_GREEN = TextColor.parseColor("#00AA00"); + public static final TextColor DARK_GREEN = TextColor.parseColor("#00AA00").getOrThrow(); - public static final TextColor DARK_AQUA = TextColor.parseColor("#00AAAA"); + public static final TextColor DARK_AQUA = TextColor.parseColor("#00AAAA").getOrThrow(); - public static final TextColor DARK_RED = TextColor.parseColor("#AA0000"); + public static final TextColor DARK_RED = TextColor.parseColor("#AA0000").getOrThrow(); - public static final TextColor DARK_PURPLE = TextColor.parseColor("#AA00AA"); + public static final TextColor DARK_PURPLE = TextColor.parseColor("#AA00AA").getOrThrow(); - public static final TextColor GOLD = TextColor.parseColor("#FFAA00"); + public static final TextColor GOLD = TextColor.parseColor("#FFAA00").getOrThrow(); - public static final TextColor GARY = TextColor.parseColor("#AAAAAA"); + public static final TextColor GARY = TextColor.parseColor("#AAAAAA").getOrThrow(); - public static final TextColor DARK_GARY = TextColor.parseColor("#555555"); + public static final TextColor DARK_GARY = TextColor.parseColor("#555555").getOrThrow(); - public static final TextColor BLUE = TextColor.parseColor("#5555FF"); + public static final TextColor BLUE = TextColor.parseColor("#5555FF").getOrThrow(); - public static final TextColor GREEN = TextColor.parseColor("#55FF55"); + public static final TextColor GREEN = TextColor.parseColor("#55FF55").getOrThrow(); - public static final TextColor AQUA = TextColor.parseColor("#55FFFF"); + public static final TextColor AQUA = TextColor.parseColor("#55FFFF").getOrThrow(); - public static final TextColor RED = TextColor.parseColor("#FF5555"); + public static final TextColor RED = TextColor.parseColor("#FF5555").getOrThrow(); - public static final TextColor LIGHT_PURPLE = TextColor.parseColor("#FF55FF"); + public static final TextColor LIGHT_PURPLE = TextColor.parseColor("#FF55FF").getOrThrow(); - public static final TextColor YELLOW = TextColor.parseColor("#FFFF55"); + public static final TextColor YELLOW = TextColor.parseColor("#FFFF55").getOrThrow(); - public static final TextColor WHITE = TextColor.parseColor("#FFFFFF"); + public static final TextColor WHITE = TextColor.parseColor("#FFFFFF").getOrThrow(); private Color() { } 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 1e65df7..3ae28ff 100644 --- a/src/main/java/dev/dubhe/gugle/carpet/mixin/AbstractContainerMenuMixin.java +++ b/src/main/java/dev/dubhe/gugle/carpet/mixin/AbstractContainerMenuMixin.java @@ -1,10 +1,12 @@ package dev.dubhe.gugle.carpet.mixin; +import net.minecraft.core.component.DataComponents; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.ClickType; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.CustomData; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -14,20 +16,22 @@ @Mixin(AbstractContainerMenu.class) abstract class AbstractContainerMenuMixin { @Unique - AbstractContainerMenu gca$self = (AbstractContainerMenu)(Object)this; + private final AbstractContainerMenu gca$self = (AbstractContainerMenu) (Object) this; @Inject(method = "doClick", at = @At("HEAD"), cancellable = true) - private void doClick(int mouseX, int mouseY, ClickType clickType, Player player, CallbackInfo ci) { - if (mouseX < 0) return; - Slot slot = gca$self.getSlot(mouseX); + private void doClick(int slotIndex, int button, ClickType clickType, Player player, CallbackInfo ci) { + if (slotIndex < 0) { + return; + } + Slot slot = gca$self.getSlot(slotIndex); ItemStack itemStack = slot.getItem(); - if (itemStack.getTag() != null) { - if (itemStack.getTag().get("GcaClear") != null) { - if (itemStack.getTag().getBoolean("GcaClear")) { - itemStack.setCount(0); - ci.cancel(); - } - } + CustomData customData = itemStack.get(DataComponents.CUSTOM_DATA); + if (customData == null || customData.copyTag().get("GcaClear") == null) { + return; + } + if (customData.copyTag().getBoolean("GcaClear")) { + itemStack.setCount(0); + ci.cancel(); } } } diff --git a/src/main/java/dev/dubhe/gugle/carpet/mixin/AxeItemMixin.java b/src/main/java/dev/dubhe/gugle/carpet/mixin/AxeItemMixin.java index 027a5b8..e5f083a 100644 --- a/src/main/java/dev/dubhe/gugle/carpet/mixin/AxeItemMixin.java +++ b/src/main/java/dev/dubhe/gugle/carpet/mixin/AxeItemMixin.java @@ -13,11 +13,14 @@ @Mixin(AxeItem.class) abstract class AxeItemMixin { - @Inject(method = "useOn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/AxeItem;getStripped(Lnet/minecraft/world/level/block/state/BlockState;)Ljava/util/Optional;"), cancellable = true) + @Inject(method = "useOn", at = @At(value = "HEAD"), cancellable = true) private void stripped(@NotNull UseOnContext context, CallbackInfoReturnable cir) { ItemStack itemStack = context.getItemInHand(); String name = itemStack.getHoverName().getString(); - if (!name.contains("Strip") && !name.contains("去皮") && GcaSetting.betterWoodStrip) { + if (GcaSetting.betterWoodStrip) { + if (name.contains("Strip") || name.contains("去皮")) { + return; + } cir.setReturnValue(InteractionResult.PASS); } } diff --git a/src/main/java/dev/dubhe/gugle/carpet/mixin/EntityInvoker.java b/src/main/java/dev/dubhe/gugle/carpet/mixin/EntityInvoker.java new file mode 100644 index 0000000..be2eaf9 --- /dev/null +++ b/src/main/java/dev/dubhe/gugle/carpet/mixin/EntityInvoker.java @@ -0,0 +1,11 @@ +package dev.dubhe.gugle.carpet.mixin; + +import net.minecraft.world.entity.Entity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(Entity.class) +public interface EntityInvoker { + @Invoker("unsetRemoved") + void invokerUnsetRemoved(); +} diff --git a/src/main/java/dev/dubhe/gugle/carpet/mixin/EntityPlayerMPFakeInvoker.java b/src/main/java/dev/dubhe/gugle/carpet/mixin/EntityPlayerMPFakeInvoker.java new file mode 100644 index 0000000..e55e26e --- /dev/null +++ b/src/main/java/dev/dubhe/gugle/carpet/mixin/EntityPlayerMPFakeInvoker.java @@ -0,0 +1,17 @@ +package dev.dubhe.gugle.carpet.mixin; + +import carpet.patches.EntityPlayerMPFake; +import com.mojang.authlib.GameProfile; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +import java.util.Optional; +import java.util.concurrent.CompletableFuture; + +@Mixin(EntityPlayerMPFake.class) +public interface EntityPlayerMPFakeInvoker { + @Invoker(value = "fetchGameProfile", remap = false) + static CompletableFuture> invokerFetchGameProfile(String name) { + throw new AssertionError(); + } +} 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 057e4b9..fa8e301 100644 --- a/src/main/java/dev/dubhe/gugle/carpet/mixin/ItemStackMixin.java +++ b/src/main/java/dev/dubhe/gugle/carpet/mixin/ItemStackMixin.java @@ -6,6 +6,7 @@ import dev.dubhe.gugle.carpet.tools.FakePlayerAutoReplenishment; 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.ItemStack; @@ -16,8 +17,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.function.Consumer; - @Mixin(ItemStack.class) abstract class ItemStackMixin { @Inject(method = "use", at = @At("HEAD")) @@ -27,9 +26,9 @@ private void use(Level level, Player player, InteractionHand usedHand, CallbackI } } - @Inject(method = "hurtAndBreak", at = @At("HEAD")) - private void hurtAndBreak(int amount, T entity, Consumer onBroken, CallbackInfo ci) { - if (GcaSetting.fakePlayerAutoReplaceTool && entity instanceof EntityPlayerMPFake fakePlayer) { + @Inject(method = "hurtAndBreak(ILnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/entity/EquipmentSlot;)V", at = @At("HEAD")) + private void hurtAndBreak(int i, LivingEntity livingEntity, EquipmentSlot equipmentSlot, CallbackInfo ci) { + if (GcaSetting.fakePlayerAutoReplaceTool && livingEntity instanceof EntityPlayerMPFake fakePlayer) { FakePlayerAutoReplaceTool.autoReplaceTool(fakePlayer); } } diff --git a/src/main/java/dev/dubhe/gugle/carpet/mixin/PlayerAccessor.java b/src/main/java/dev/dubhe/gugle/carpet/mixin/PlayerAccessor.java new file mode 100644 index 0000000..6916e9f --- /dev/null +++ b/src/main/java/dev/dubhe/gugle/carpet/mixin/PlayerAccessor.java @@ -0,0 +1,14 @@ +package dev.dubhe.gugle.carpet.mixin; + +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.world.entity.player.Player; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(Player.class) +public interface PlayerAccessor { + @Accessor("DATA_PLAYER_MODE_CUSTOMISATION") + static EntityDataAccessor getCustomisationData() { + throw new AssertionError(); + } +} 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 166d50a..b85239a 100644 --- a/src/main/java/dev/dubhe/gugle/carpet/mixin/PlayerMixin.java +++ b/src/main/java/dev/dubhe/gugle/carpet/mixin/PlayerMixin.java @@ -1,13 +1,14 @@ package dev.dubhe.gugle.carpet.mixin; import carpet.patches.EntityPlayerMPFake; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import dev.dubhe.gugle.carpet.GcaExtension; import dev.dubhe.gugle.carpet.GcaSetting; import dev.dubhe.gugle.carpet.api.tools.text.ComponentTranslate; import dev.dubhe.gugle.carpet.tools.FakePlayerEnderChestContainer; import dev.dubhe.gugle.carpet.tools.FakePlayerInventoryContainer; import dev.dubhe.gugle.carpet.tools.FakePlayerInventoryMenu; -import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.SimpleMenuProvider; @@ -18,7 +19,6 @@ import org.spongepowered.asm.mixin.Unique; 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 java.util.Map; @@ -30,43 +30,45 @@ abstract class PlayerMixin { @Inject(method = "tick", at = @At("RETURN")) private void tick(CallbackInfo ci) { - if (gca$self instanceof ServerPlayer serverPlayer && - serverPlayer instanceof EntityPlayerMPFake && serverPlayer.isAlive()) { - Map.Entry entry = GcaExtension.fakePlayerInventoryContainerMap.get(gca$self); + if (gca$self instanceof EntityPlayerMPFake fakePlayer && fakePlayer.isAlive()) { + Map.Entry entry + = GcaExtension.fakePlayerInventoryContainerMap.get(gca$self); entry.getKey().tick(); entry.getValue().tick(); } } - @Redirect(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) { - if (!(entity instanceof EntityPlayerMPFake fakePlayer)) return entity.interact(player, hand); + @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); + } SimpleMenuProvider provider = null; if (player.isShiftKeyDown()) { if (GcaSetting.openFakePlayerEnderChest) { provider = new SimpleMenuProvider( - (i, inventory, p) -> ChestMenu.sixRows( - i, inventory, - GcaExtension.fakePlayerInventoryContainerMap.get(fakePlayer).getValue() - ), - ComponentTranslate.trans("gca.player.ender_chest", fakePlayer.getDisplayName()) + (i, inventory, p) -> ChestMenu.sixRows( + i, inventory, + GcaExtension.fakePlayerInventoryContainerMap.get(fakePlayer).getValue() + ), + ComponentTranslate.trans("gca.player.ender_chest", fakePlayer.getDisplayName()) ); } else { provider = new SimpleMenuProvider( - (i, inventory, p) -> ChestMenu.threeRows( - i, inventory, - GcaExtension.fakePlayerInventoryContainerMap.get(fakePlayer).getValue() - ), - ComponentTranslate.trans("gca.player.other_controller", fakePlayer.getDisplayName()) + (i, inventory, p) -> ChestMenu.threeRows( + i, inventory, + GcaExtension.fakePlayerInventoryContainerMap.get(fakePlayer).getValue() + ), + ComponentTranslate.trans("gca.player.other_controller", fakePlayer.getDisplayName()) ); } } else if (GcaSetting.openFakePlayerInventory) { provider = new SimpleMenuProvider( - (i, inventory, p) -> new FakePlayerInventoryMenu( - i, inventory, - GcaExtension.fakePlayerInventoryContainerMap.get(fakePlayer).getKey() - ), - ComponentTranslate.trans("gca.player.inventory", fakePlayer.getDisplayName()) + (i, inventory, p) -> new FakePlayerInventoryMenu( + i, inventory, + GcaExtension.fakePlayerInventoryContainerMap.get(fakePlayer).getKey() + ), + ComponentTranslate.trans("gca.player.inventory", fakePlayer.getDisplayName()) ); } if (provider != null) { diff --git a/src/main/java/dev/dubhe/gugle/carpet/mixin/ServerLevelMixin.java b/src/main/java/dev/dubhe/gugle/carpet/mixin/ServerLevelMixin.java index b81cc38..16a2549 100644 --- a/src/main/java/dev/dubhe/gugle/carpet/mixin/ServerLevelMixin.java +++ b/src/main/java/dev/dubhe/gugle/carpet/mixin/ServerLevelMixin.java @@ -1,7 +1,7 @@ package dev.dubhe.gugle.carpet.mixin; import dev.dubhe.gugle.carpet.GcaExtension; -import dev.dubhe.gugle.carpet.api.Function; +import dev.dubhe.gugle.carpet.api.Consumer; import net.minecraft.server.level.ServerLevel; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -22,8 +22,8 @@ abstract class ServerLevelMixin { @Inject(method = "tick", at = @At("RETURN")) private void tick(BooleanSupplier hasTimeLeft, CallbackInfo ci) { long gameTime = gca$self.getLevel().getGameTime(); - List> remove = new ArrayList<>(); - for (Map.Entry pair : GcaExtension.planFunction) { + List> remove = new ArrayList<>(); + for (Map.Entry pair : GcaExtension.planFunction) { if (pair.getKey() == gameTime) { pair.getValue().accept(); remove.add(pair); @@ -31,7 +31,7 @@ private void tick(BooleanSupplier hasTimeLeft, CallbackInfo ci) { remove.add(pair); } } - for (Map.Entry pair : remove) { + for (Map.Entry pair : remove) { GcaExtension.planFunction.remove(pair); } } diff --git a/src/main/java/dev/dubhe/gugle/carpet/mixin/ServerPlaceRecipeMixin.java b/src/main/java/dev/dubhe/gugle/carpet/mixin/ServerPlaceRecipeMixin.java index 31b3c83..ebcbae9 100644 --- a/src/main/java/dev/dubhe/gugle/carpet/mixin/ServerPlaceRecipeMixin.java +++ b/src/main/java/dev/dubhe/gugle/carpet/mixin/ServerPlaceRecipeMixin.java @@ -1,20 +1,20 @@ package dev.dubhe.gugle.carpet.mixin; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import dev.dubhe.gugle.carpet.GcaSetting; import it.unimi.dsi.fastutil.ints.IntList; import net.minecraft.recipebook.ServerPlaceRecipe; import net.minecraft.world.entity.player.StackedContents; -import net.minecraft.world.item.crafting.Recipe; -import org.jetbrains.annotations.NotNull; +import net.minecraft.world.item.crafting.RecipeHolder; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(ServerPlaceRecipe.class) abstract class ServerPlaceRecipeMixin { - @Redirect(method = "handleRecipeClicked", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/StackedContents;getBiggestCraftableStack(Lnet/minecraft/world/item/crafting/Recipe;Lit/unimi/dsi/fastutil/ints/IntList;)I")) - private int handleRecipeClicked(@NotNull StackedContents instance, Recipe recipe, IntList intList) { - int i = instance.getBiggestCraftableStack(recipe, intList); + @WrapOperation(method = "handleRecipeClicked", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/StackedContents;getBiggestCraftableStack(Lnet/minecraft/world/item/crafting/RecipeHolder;Lit/unimi/dsi/fastutil/ints/IntList;)I")) + private int handleRecipeClicked(StackedContents instance, RecipeHolder recipeHolder, IntList intList, Operation original) { + int i = original.call(instance, recipeHolder, intList); return GcaSetting.betterQuickCrafting ? i - 1 : i; } } diff --git a/src/main/java/dev/dubhe/gugle/carpet/mixin/SignBlockMixin.java b/src/main/java/dev/dubhe/gugle/carpet/mixin/SignBlockMixin.java index 4e0a021..49e3cd0 100644 --- a/src/main/java/dev/dubhe/gugle/carpet/mixin/SignBlockMixin.java +++ b/src/main/java/dev/dubhe/gugle/carpet/mixin/SignBlockMixin.java @@ -3,7 +3,6 @@ import dev.dubhe.gugle.carpet.GcaSetting; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; @@ -23,15 +22,17 @@ abstract class SignBlockMixin { @Unique private final SignBlock gca$self = (SignBlock) (Object) this; - @Inject(method = "use", at = @At(value = "INVOKE",target = "Lnet/minecraft/world/level/Level;playSound(Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/core/BlockPos;Lnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;)V"), cancellable = true) - public void use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit, CallbackInfoReturnable cir) { + @Inject(method = "useWithoutItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;playSound(Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/core/BlockPos;Lnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;)V"), cancellable = true) + public void use(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult blockHitResult, CallbackInfoReturnable cir) { if (GcaSetting.betterSignInteraction && gca$self instanceof WallSignBlock) { Direction direction = state.getValue(WallSignBlock.FACING); BlockPos blockPos = pos.relative(direction, -1); BlockState blockState = level.getBlockState(blockPos); BlockHitResult hitResult = new BlockHitResult(Vec3.atCenterOf(blockPos), direction, blockPos, false); - if (blockState.getBlock() instanceof WallSignBlock) return; - else blockState.use(level, player, hand, hitResult); + if (blockState.getBlock() instanceof WallSignBlock) { + return; + } + blockState.useWithoutItem(level, player, hitResult); cir.setReturnValue(InteractionResult.SUCCESS); } } diff --git a/src/main/java/dev/dubhe/gugle/carpet/tools/FakePlayerAutoReplenishment.java b/src/main/java/dev/dubhe/gugle/carpet/tools/FakePlayerAutoReplenishment.java index 476f89a..0719c98 100644 --- a/src/main/java/dev/dubhe/gugle/carpet/tools/FakePlayerAutoReplenishment.java +++ b/src/main/java/dev/dubhe/gugle/carpet/tools/FakePlayerAutoReplenishment.java @@ -1,16 +1,13 @@ package dev.dubhe.gugle.carpet.tools; import net.minecraft.core.NonNullList; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.Tag; +import net.minecraft.core.component.DataComponents; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; +import net.minecraft.world.item.component.ItemContainerContents; import org.jetbrains.annotations.NotNull; -import java.util.Iterator; - public class FakePlayerAutoReplenishment { public static void autoReplenishment(@NotNull Player fakePlayer) { @@ -19,52 +16,73 @@ public static void autoReplenishment(@NotNull Player fakePlayer) { replenishment(fakePlayer.getOffhandItem(), itemStackList); } - public static void replenishment(@NotNull ItemStack itemStack, NonNullList itemStackList) { - int rs = itemStack.getMaxStackSize() / 8; - if (itemStack.isEmpty()) return; - if (itemStack.getCount() > rs) return; - int count = itemStack.getMaxStackSize() / 2; - if (count <= rs) return; - global: - for (ItemStack itemStack1 : itemStackList) { - if (itemStack1.isEmpty() || itemStack1 == itemStack) continue; - if (ItemStack.isSameItemSameTags(itemStack1, itemStack)) { - if (itemStack1.getCount() > count) { - itemStack.setCount(itemStack.getCount() + count); - itemStack1.setCount(itemStack1.getCount() - count); + private static void replenishment(@NotNull ItemStack itemStack, NonNullList itemStackList) { + int base = itemStack.getMaxStackSize() / 8; + if (itemStack.isEmpty() || (itemStack.getCount() > base)) { + return; + } + int half = itemStack.getMaxStackSize() / 2; + if (half <= base) { + return; + } + for (ItemStack eachItem : itemStackList) { + if (eachItem.isEmpty() || (eachItem == itemStack)) { + continue; + } + if (ItemStack.isSameItemSameComponents(eachItem, itemStack)) { + if (eachItem.getCount() > half) { + itemStack.setCount(itemStack.getCount() + half); + eachItem.setCount(eachItem.getCount() - half); } else { - itemStack.setCount(itemStack.getCount() + itemStack1.getCount()); - itemStack1.setCount(0); + itemStack.setCount(itemStack.getCount() + eachItem.getCount()); + eachItem.setCount(0); } break; - } else if (itemStack1.is(Items.SHULKER_BOX) && itemStack1.hasTag()) { - CompoundTag nbt = itemStack1.getTagElement("BlockEntityTag"); - if (nbt != null && nbt.contains("Items", Tag.TAG_LIST)) { - ListTag tagList = nbt.getList("Items", Tag.TAG_COMPOUND); - Iterator iterator = tagList.iterator(); - int index = -1; - while (iterator.hasNext()) { - index += 1; - Tag next = iterator.next(); - CompoundTag tag = next.getId() == 10 ? (CompoundTag) next : new CompoundTag(); - ItemStack stack = ItemStack.of(tag); - if (!ItemStack.isSameItemSameTags(stack, itemStack)) continue; - if (stack.getCount() > count) { - itemStack.setCount(itemStack.getCount() + count); - stack.setCount(stack.getCount() - count); - } else { - itemStack.setCount(itemStack.getCount() + stack.getCount()); - stack.setCount(0); - } - if (!stack.isEmpty()) { - CompoundTag newTag = stack.save(new CompoundTag()); - newTag.putByte("Slot", tag.getByte("Slot")); - tagList.set(index, newTag); - } else iterator.remove(); - break global; - } + } else if (eachItem.is(Items.SHULKER_BOX)) { + int result = pickItemFromBox(eachItem, itemStack, half); + if (result == 0) { + continue; } + itemStack.grow(result); } } } + + // 从潜影盒拿取物品,请注意:在创造模式下使用鼠标中键复制物品(不是指选取方块)时,物品组件仅被浅拷贝。 + private static int pickItemFromBox(ItemStack shulkerBox, ItemStack itemStack, int count) { + ItemContainerContents contents = shulkerBox.get(DataComponents.CONTAINER); + // 潜影盒没有容器组件 + if (contents == null) { + return 0; + } + for (ItemStack stack : contents.nonEmptyItems()) { + if (ItemStack.isSameItemSameComponents(itemStack, stack)) { + int temp; + if (stack.getCount() >= count) { + stack.shrink(count); + temp = count; + } else { + temp = stack.getCount(); + stack.setCount(0); + } + ifIsEmptyClear(shulkerBox); + return temp; + } + } + return 0; + } + + // 如果潜影盒为空,将物品栏组件替换为空以保证潜影盒堆叠的正常运行 + private static void ifIsEmptyClear(ItemStack shulkerBox) { + ItemContainerContents contents = shulkerBox.get(DataComponents.CONTAINER); + if (contents == null) { + return; + } + // 潜影盒中还有物品 + if (contents.nonEmptyItems().iterator().hasNext()) { + return; + } + // 潜影盒中已经没有物品了 + shulkerBox.set(DataComponents.CONTAINER, ItemContainerContents.EMPTY); + } } diff --git a/src/main/java/dev/dubhe/gugle/carpet/tools/FakePlayerInventoryContainer.java b/src/main/java/dev/dubhe/gugle/carpet/tools/FakePlayerInventoryContainer.java index b0287b5..b76e400 100644 --- a/src/main/java/dev/dubhe/gugle/carpet/tools/FakePlayerInventoryContainer.java +++ b/src/main/java/dev/dubhe/gugle/carpet/tools/FakePlayerInventoryContainer.java @@ -68,34 +68,18 @@ public boolean isEmpty() { } public Map.Entry, Integer> getItemSlot(int slot) { - switch (slot) { - case 0 -> { - return Map.entry(buttons, 0); - } - case 1, 2, 3, 4 -> { - return Map.entry(armor, 4 - slot); - } - case 5, 6 -> { - return Map.entry(buttons, slot - 4); - } - case 7 -> { - return Map.entry(offhand, 0); - } - case 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 -> { - return Map.entry(buttons, slot - 5); - } + return switch (slot) { + case 0 -> Map.entry(buttons, 0); + case 1, 2, 3, 4 -> Map.entry(armor, 4 - slot); + case 5, 6 -> Map.entry(buttons, slot - 4); + case 7 -> Map.entry(offhand, 0); + case 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 -> Map.entry(buttons, slot - 5); case 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44 -> { - return Map.entry(items, slot - 9); - } - case 45, 46, 47, 48, 49, 50, 51, 52, 53 -> { - return Map.entry(items, slot - 45); - } - default -> { - return null; - } - } + 36, 37, 38, 39, 40, 41, 42, 43, 44 -> Map.entry(items, slot - 9); + case 45, 46, 47, 48, 49, 50, 51, 52, 53 -> Map.entry(items, slot - 45); + default -> null; + }; } @Override @@ -109,15 +93,15 @@ private void createButton() { List