diff --git a/src/main/java/fi/dy/masa/tweakeroo/config/Callbacks.java b/src/main/java/fi/dy/masa/tweakeroo/config/Callbacks.java index e866e6423..789028805 100644 --- a/src/main/java/fi/dy/masa/tweakeroo/config/Callbacks.java +++ b/src/main/java/fi/dy/masa/tweakeroo/config/Callbacks.java @@ -10,27 +10,20 @@ import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.hit.HitResult; import net.minecraft.util.math.BlockPos; -import fi.dy.masa.malilib.config.IConfigBase; + import fi.dy.masa.malilib.config.IConfigBoolean; -import fi.dy.masa.malilib.config.IHotkeyTogglable; import fi.dy.masa.malilib.config.options.ConfigBoolean; import fi.dy.masa.malilib.gui.GuiBase; -import fi.dy.masa.malilib.hotkeys.IHotkeyCallback; -import fi.dy.masa.malilib.hotkeys.IKeybind; -import fi.dy.masa.malilib.hotkeys.KeyAction; -import fi.dy.masa.malilib.hotkeys.KeyCallbackAdjustable; -import fi.dy.masa.malilib.hotkeys.KeyCallbackToggleBooleanConfigWithMessage; +import fi.dy.masa.malilib.hotkeys.*; import fi.dy.masa.malilib.interfaces.IValueChangeCallback; +import fi.dy.masa.malilib.render.InventoryOverlayScreen; import fi.dy.masa.malilib.util.InfoUtils; import fi.dy.masa.malilib.util.StringUtils; import fi.dy.masa.tweakeroo.gui.GuiConfigs; import fi.dy.masa.tweakeroo.mixin.IMixinAbstractBlock; import fi.dy.masa.tweakeroo.mixin.IMixinSimpleOption; -import fi.dy.masa.tweakeroo.util.CameraEntity; -import fi.dy.masa.tweakeroo.util.InventoryUtils; -import fi.dy.masa.tweakeroo.util.MiscUtils; -import fi.dy.masa.tweakeroo.util.PlacementRestrictionMode; -import fi.dy.masa.tweakeroo.util.SnapAimMode; +import fi.dy.masa.tweakeroo.renderer.InventoryOverlayHandler; +import fi.dy.masa.tweakeroo.util.*; public class Callbacks { @@ -82,6 +75,7 @@ public static void init(MinecraftClient mc) Hotkeys.HOTBAR_SWAP_2.getKeybind().setCallback(callbackGeneric); Hotkeys.HOTBAR_SWAP_3.getKeybind().setCallback(callbackGeneric); Hotkeys.HOTBAR_SCROLL.getKeybind().setCallback(callbackGeneric); + Hotkeys.INVENTORY_PREVIEW_TOGGLE_SCREEN.getKeybind().setCallback(callbackGeneric); Hotkeys.OPEN_CONFIG_GUI.getKeybind().setCallback(callbackGeneric); Hotkeys.PLACEMENT_RESTRICTION_MODE_COLUMN.getKeybind().setCallback(callbackGeneric); Hotkeys.PLACEMENT_RESTRICTION_MODE_DIAGONAL.getKeybind().setCallback(callbackGeneric); @@ -448,6 +442,18 @@ else if (key == Hotkeys.ZOOM_ACTIVATE.getKeybind()) //String.format("%s%.1f%s", GuiBase.TXT_GREEN, Configs.Generic.ZOOM_FOV.getDoubleValue(), GuiBase.TXT_RST)); } } + else if (key == Hotkeys.INVENTORY_PREVIEW_TOGGLE_SCREEN.getKeybind()) + { + if (mc.currentScreen instanceof InventoryOverlayScreen) + { + mc.setScreen(null); + } + else if (FeatureToggle.TWEAK_INVENTORY_PREVIEW.getBooleanValue() && + Hotkeys.INVENTORY_PREVIEW.getKeybind().isKeybindHeld()) + { + InventoryOverlayHandler.getInstance().refreshInventoryOverlay(mc, Configs.Generic.SHULKER_DISPLAY_BACKGROUND_COLOR.getBooleanValue()); + } + } return false; } diff --git a/src/main/java/fi/dy/masa/tweakeroo/config/Hotkeys.java b/src/main/java/fi/dy/masa/tweakeroo/config/Hotkeys.java index f5599b5a7..b01e37800 100644 --- a/src/main/java/fi/dy/masa/tweakeroo/config/Hotkeys.java +++ b/src/main/java/fi/dy/masa/tweakeroo/config/Hotkeys.java @@ -37,6 +37,7 @@ public class Hotkeys public static final ConfigHotkey HOTBAR_SWAP_2 = new ConfigHotkey("hotbarSwap2", "").apply(HOTKEY_KEY); public static final ConfigHotkey HOTBAR_SWAP_3 = new ConfigHotkey("hotbarSwap3", "").apply(HOTKEY_KEY); public static final ConfigHotkey INVENTORY_PREVIEW = new ConfigHotkey("inventoryPreview", "LEFT_ALT", KeybindSettings.PRESS_ALLOWEXTRA).apply(HOTKEY_KEY); + public static final ConfigHotkey INVENTORY_PREVIEW_TOGGLE_SCREEN = new ConfigHotkey("inventoryPreviewToggleScreen", "BUTTON_3", KeybindSettings.create(KeybindSettings.Context.ANY, KeyAction.PRESS, true, true, false, true)).apply(HOTKEY_KEY); public static final ConfigHotkey OPEN_CONFIG_GUI = new ConfigHotkey("openConfigGui", "X,C").apply(HOTKEY_KEY); public static final ConfigHotkey PLACEMENT_Y_MIRROR = new ConfigHotkey("placementYMirror", "", KeybindSettings.PRESS_ALLOWEXTRA).apply(HOTKEY_KEY); public static final ConfigHotkey PLAYER_INVENTORY_PEEK = new ConfigHotkey("playerInventoryPeek", "", KeybindSettings.PRESS_ALLOWEXTRA).apply(HOTKEY_KEY); @@ -83,6 +84,7 @@ public class Hotkeys HOTBAR_SWAP_2, HOTBAR_SWAP_3, INVENTORY_PREVIEW, + INVENTORY_PREVIEW_TOGGLE_SCREEN, OPEN_CONFIG_GUI, PLACEMENT_Y_MIRROR, PLAYER_INVENTORY_PEEK, diff --git a/src/main/java/fi/dy/masa/tweakeroo/data/ServerDataSyncer.java b/src/main/java/fi/dy/masa/tweakeroo/data/ServerDataSyncer.java index 0375f3f16..6cfc94b45 100644 --- a/src/main/java/fi/dy/masa/tweakeroo/data/ServerDataSyncer.java +++ b/src/main/java/fi/dy/masa/tweakeroo/data/ServerDataSyncer.java @@ -2,8 +2,8 @@ import java.util.*; import java.util.concurrent.ConcurrentHashMap; -import javax.annotation.Nullable; -import com.llamalad7.mixinextras.lib.apache.commons.tuple.Pair; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.Nullable; import com.mojang.datafixers.util.Either; import net.minecraft.block.BlockEntityProvider; @@ -35,6 +35,7 @@ import net.minecraft.world.World; import fi.dy.masa.malilib.interfaces.IClientTickHandler; +import fi.dy.masa.malilib.interfaces.IDataSyncer; import fi.dy.masa.malilib.network.ClientPlayHandler; import fi.dy.masa.malilib.network.IPluginClientPlayHandler; import fi.dy.masa.malilib.util.Constants; @@ -52,7 +53,7 @@ import fi.dy.masa.tweakeroo.network.ServuxTweaksPacket; @SuppressWarnings({"deprecation"}) -public class ServerDataSyncer implements IClientTickHandler +public class ServerDataSyncer implements IClientTickHandler, IDataSyncer { private static final ServerDataSyncer INSTANCE = new ServerDataSyncer(); public static ServerDataSyncer getInstance() @@ -78,13 +79,15 @@ public static ServerDataSyncer getInstance() private final Map> transactionToBlockPosOrEntityId = new HashMap<>(); private ClientWorld clientWorld; + @Override @Nullable public World getWorld() { return WorldUtils.getBestWorld(mc); } - private ClientWorld getClientWorld() + @Override + public ClientWorld getClientWorld() { if (this.clientWorld == null) { @@ -182,6 +185,7 @@ public IPluginClientPlayHandler getNetworkHandler() return HANDLER; } + @Override public void reset(boolean isLogout) { if (isLogout) @@ -247,6 +251,7 @@ private void tickCache() } } + @Override public @Nullable NbtCompound getFromBlockEntityCacheNbt(BlockPos pos) { if (this.blockEntityCache.containsKey(pos)) @@ -257,6 +262,7 @@ private void tickCache() return null; } + @Override public @Nullable BlockEntity getFromBlockEntityCache(BlockPos pos) { if (this.blockEntityCache.containsKey(pos)) @@ -267,6 +273,7 @@ private void tickCache() return null; } + @Override public @Nullable NbtCompound getFromEntityCacheNbt(int entityId) { if (this.entityCache.containsKey(entityId)) @@ -277,6 +284,7 @@ private void tickCache() return null; } + @Override public @Nullable Entity getFromEntityCache(int entityId) { if (this.entityCache.containsKey(entityId)) @@ -336,12 +344,14 @@ public int getEntityCacheCount() return this.entityCache.size(); } + @Override public void onGameInit() { ClientPlayHandler.getInstance().registerClientPlayHandler(HANDLER); HANDLER.registerPlayPayload(ServuxTweaksPacket.Payload.ID, ServuxTweaksPacket.Payload.CODEC, IPluginClientPlayHandler.BOTH_CLIENT); } + @Override public void onWorldPre() { if (DataManager.getInstance().hasIntegratedServer() == false) @@ -350,6 +360,7 @@ public void onWorldPre() } } + @Override public void onWorldJoin() { // NO-OP @@ -398,6 +409,7 @@ public void onPacketFailure() this.hasInValidServux = true; } + @Override public @Nullable Pair requestBlockEntity(World world, BlockPos pos) { if (this.blockEntityCache.containsKey(pos)) @@ -431,7 +443,8 @@ else if (world.getBlockState(pos).getBlock() instanceof BlockEntityProvider) return null; } - public @Nullable Pair requestEntity(int entityId) + @Override + public @Nullable Pair requestEntity(World world, int entityId) { if (this.entityCache.containsKey(entityId)) { @@ -464,6 +477,7 @@ else if (world.getBlockState(pos).getBlock() instanceof BlockEntityProvider) return null; } + @Override @Nullable public Inventory getBlockInventory(World world, BlockPos pos, boolean useNbt) { @@ -536,8 +550,9 @@ public Inventory getBlockInventory(World world, BlockPos pos, boolean useNbt) return null; } + @Override @Nullable - public Inventory getEntityInventory(int entityId, boolean useNbt) + public Inventory getEntityInventory(World world, int entityId, boolean useNbt) { if (this.entityCache.containsKey(entityId) && this.getWorld() != null) { @@ -581,7 +596,7 @@ else if (entity instanceof PiglinEntity) if (FeatureToggle.TWEAK_SERVER_DATA_SYNC.getBooleanValue()) { - this.requestEntity(entityId); + this.requestEntity(world, entityId); } return null; @@ -641,6 +656,7 @@ private void requestServuxEntityData(int entityId) } } + @Override @Nullable public BlockEntity handleBlockEntityData(BlockPos pos, NbtCompound nbt, @Nullable Identifier type) { @@ -717,6 +733,7 @@ public BlockEntity handleBlockEntityData(BlockPos pos, NbtCompound nbt, @Nullabl return null; } + @Override @Nullable public Entity handleEntityData(int entityId, NbtCompound nbt) { @@ -750,11 +767,13 @@ public Entity handleEntityData(int entityId, NbtCompound nbt) return entity; } + @Override public void handleBulkEntityData(int transactionId, NbtCompound nbt) { // todo } + @Override public void handleVanillaQueryNbt(int transactionId, NbtCompound nbt) { Either either = this.transactionToBlockPosOrEntityId.remove(transactionId); diff --git a/src/main/java/fi/dy/masa/tweakeroo/event/RenderHandler.java b/src/main/java/fi/dy/masa/tweakeroo/event/RenderHandler.java index d33dfdb70..c8fc48ef4 100644 --- a/src/main/java/fi/dy/masa/tweakeroo/event/RenderHandler.java +++ b/src/main/java/fi/dy/masa/tweakeroo/event/RenderHandler.java @@ -1,6 +1,6 @@ package fi.dy.masa.tweakeroo.event; -import com.llamalad7.mixinextras.lib.apache.commons.tuple.Pair; +import org.apache.commons.lang3.tuple.Pair; import org.joml.Matrix4f; import com.mojang.blaze3d.systems.RenderSystem; @@ -25,7 +25,6 @@ import fi.dy.masa.malilib.gui.GuiBase; import fi.dy.masa.malilib.interfaces.IRenderer; -import fi.dy.masa.malilib.render.InventoryOverlay; import fi.dy.masa.malilib.util.ActiveMode; import fi.dy.masa.malilib.util.Color4f; import fi.dy.masa.malilib.util.InventoryUtils; @@ -35,8 +34,8 @@ import fi.dy.masa.tweakeroo.config.FeatureToggle; import fi.dy.masa.tweakeroo.config.Hotkeys; import fi.dy.masa.tweakeroo.data.ServerDataSyncer; +import fi.dy.masa.tweakeroo.renderer.InventoryOverlayHandler; import fi.dy.masa.tweakeroo.renderer.RenderUtils; -import fi.dy.masa.tweakeroo.util.RayTraceUtils; public class RenderHandler implements IRenderer { @@ -70,12 +69,16 @@ else if (FeatureToggle.TWEAK_HOTBAR_SCROLL.getBooleanValue() && if (FeatureToggle.TWEAK_INVENTORY_PREVIEW.getBooleanValue() && Hotkeys.INVENTORY_PREVIEW.getKeybind().isKeybindHeld()) { + /* InventoryOverlay.Context context = RayTraceUtils.getTargetInventory(mc); if (context != null) { RenderUtils.renderInventoryOverlay(context, drawContext); } + */ + + InventoryOverlayHandler.getInstance().getRenderContext(drawContext, profiler, mc); } if (FeatureToggle.TWEAK_PLAYER_INVENTORY_PEEK.getBooleanValue() && @@ -135,7 +138,7 @@ else if (stack.isOf(Items.ENDER_CHEST) && Configs.Generic.SHULKER_DISPLAY_ENDER_ if (player != null) { - Pair pair = ServerDataSyncer.getInstance().requestEntity(player.getId()); + Pair pair = ServerDataSyncer.getInstance().requestEntity(world, player.getId()); NbtCompound nbt = new NbtCompound(); EnderChestInventory inv; diff --git a/src/main/java/fi/dy/masa/tweakeroo/renderer/InventoryOverlayHandler.java b/src/main/java/fi/dy/masa/tweakeroo/renderer/InventoryOverlayHandler.java new file mode 100644 index 000000000..20b299137 --- /dev/null +++ b/src/main/java/fi/dy/masa/tweakeroo/renderer/InventoryOverlayHandler.java @@ -0,0 +1,500 @@ +package fi.dy.masa.tweakeroo.renderer; + +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.Nullable; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockEntityProvider; +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.block.entity.EnderChestBlockEntity; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.mob.PiglinEntity; +import net.minecraft.entity.passive.AbstractHorseEntity; +import net.minecraft.entity.passive.VillagerEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.inventory.EnderChestInventory; +import net.minecraft.inventory.Inventory; +import net.minecraft.inventory.SimpleInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.registry.Registries; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.hit.EntityHitResult; +import net.minecraft.util.hit.HitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.profiler.Profiler; +import net.minecraft.world.World; + +import fi.dy.masa.malilib.interfaces.IDataSyncer; +import fi.dy.masa.malilib.interfaces.IInventoryOverlayHandler; +import fi.dy.masa.malilib.render.InventoryOverlay; +import fi.dy.masa.malilib.util.Constants; +import fi.dy.masa.malilib.util.EntityUtils; +import fi.dy.masa.malilib.util.InventoryUtils; +import fi.dy.masa.malilib.util.WorldUtils; +import fi.dy.masa.malilib.util.nbt.NbtBlockUtils; +import fi.dy.masa.malilib.util.nbt.NbtKeys; +import fi.dy.masa.tweakeroo.Reference; +import fi.dy.masa.tweakeroo.config.Configs; +import fi.dy.masa.tweakeroo.data.ServerDataSyncer; +import fi.dy.masa.tweakeroo.mixin.IMixinAbstractHorseEntity; +import fi.dy.masa.tweakeroo.mixin.IMixinPiglinEntity; +import fi.dy.masa.tweakeroo.util.RayTraceUtils; + +public class InventoryOverlayHandler implements IInventoryOverlayHandler +{ + private static final InventoryOverlayHandler INSTANCE = new InventoryOverlayHandler(); + public static InventoryOverlayHandler getInstance() { return INSTANCE; } + + InventoryOverlay.Context context; + InventoryOverlay.Refresher refresher; + IDataSyncer syncer; + + private Pair lastBlockEntityContext; + private Pair lastEntityContext; + + public InventoryOverlayHandler() + { + this.lastBlockEntityContext = null; + this.lastEntityContext = null; + this.context = null; + this.syncer = null; + this.refresher = null; + } + + @Override + public String getModId() + { + return Reference.MOD_ID; + } + + @Override + public IDataSyncer getDataSyncer() + { + if (this.syncer == null) + { + this.syncer = ServerDataSyncer.getInstance(); + } + + return this.syncer; + } + + @Override + public void setDataSyncer(IDataSyncer syncer) + { + this.syncer = syncer; + } + + @Override + public InventoryOverlay.Refresher getRefreshHandler() + { + if (this.refresher == null) + { + this.refresher = new Refresher(); + } + + return this.refresher; + } + + @Override + public boolean isEmpty() + { + return this.context == null; + } + + @Override + public @Nullable InventoryOverlay.Context getRenderContextNullable() + { + return this.context; + } + + @Override + public @Nullable InventoryOverlay.Context getRenderContext(DrawContext drawContext, Profiler profiler, MinecraftClient mc) + { + profiler.push(this.getClass().getName() + "_inventory_overlay"); + this.getTargetInventory(mc); + + if (!this.isEmpty()) + { + this.renderInventoryOverlay(this.getRenderContextNullable(), drawContext, mc, Configs.Generic.SHULKER_DISPLAY_BACKGROUND_COLOR.getBooleanValue()); + } + + profiler.pop(); + + return this.getRenderContextNullable(); + } + + @Override + public @Nullable InventoryOverlay.Context getTargetInventory(MinecraftClient mc) + { + World world = WorldUtils.getBestWorld(mc); + Entity cameraEntity = EntityUtils.getCameraEntity(); + this.context = null; + + if (mc.player == null || world == null) + { + return null; + } + + if (cameraEntity == mc.player && world instanceof ServerWorld) + { + // We need to get the player from the server world (if available, ie. in single player), + // so that the player itself won't be included in the ray trace + Entity serverPlayer = world.getPlayerByUuid(mc.player.getUuid()); + + if (serverPlayer != null) + { + cameraEntity = serverPlayer; + } + } + + HitResult trace = RayTraceUtils.getRayTraceFromEntity(world, cameraEntity, false); + NbtCompound nbt = new NbtCompound(); + + if (trace == null || trace.getType() == HitResult.Type.MISS) + { + return null; + } + + if (trace.getType() == HitResult.Type.BLOCK) + { + BlockPos pos = ((BlockHitResult) trace).getBlockPos(); + BlockState state = world.getBlockState(pos); + Block blockTmp = state.getBlock(); + BlockEntity be = null; + + //Tweakeroo.logger.warn("getTarget():1: pos [{}], state [{}]", pos.toShortString(), state.toString()); + + if (blockTmp instanceof BlockEntityProvider) + { + if (world instanceof ServerWorld) + { + be = world.getWorldChunk(pos).getBlockEntity(pos); + + if (be != null) + { + nbt = be.createNbtWithIdentifyingData(world.getRegistryManager()); + } + } + else + { + Pair pair = this.requestBlockEntityAt(world, pos); + + if (pair != null) + { + nbt = pair.getRight(); + } + } + + //Tweakeroo.logger.warn("getTarget():2: pos [{}], be [{}], nbt [{}]", pos.toShortString(), be != null, nbt != null); + InventoryOverlay.Context ctx = getTargetInventoryFromBlock(world, pos, be, nbt); + //dumpContext(ctx); + + if (this.lastBlockEntityContext != null && !this.lastBlockEntityContext.getLeft().equals(pos)) + { + this.lastBlockEntityContext = null; + } + + if (ctx != null && ctx.inv() != null) + { + this.lastBlockEntityContext = Pair.of(pos, ctx); + this.context = ctx; + return ctx; + } + else if (this.lastBlockEntityContext != null && this.lastBlockEntityContext.getLeft().equals(pos)) + { + this.context = this.lastBlockEntityContext.getRight(); + return this.context; + } + } + + return null; + } + else if (trace.getType() == HitResult.Type.ENTITY) + { + Entity entity = ((EntityHitResult) trace).getEntity(); + + if (world instanceof ServerWorld) + { + entity.saveSelfNbt(nbt); + } + else + { + Pair pair = ServerDataSyncer.getInstance().requestEntity(world, entity.getId()); + + if (pair != null) + { + nbt = pair.getRight(); + } + } + + //Tweakeroo.logger.error("getTarget(): Entity [{}] raw NBT [{}]", entity.getId(), nbt.toString()); + InventoryOverlay.Context ctx = getTargetInventoryFromEntity(world.getEntityById(entity.getId()), nbt); + //dumpContext(ctx); + + if (this.lastEntityContext != null && !this.lastEntityContext.getLeft().equals(entity.getId())) + { + this.lastEntityContext = null; + } + + if (ctx != null && ctx.inv() != null) + { + this.lastEntityContext = Pair.of(entity.getId(), ctx); + this.context = ctx; + return ctx; + } + // Non-Inventory/Empty Entity + else if (ctx != null && + (ctx.type() == InventoryOverlay.InventoryRenderType.WOLF || + ctx.type() == InventoryOverlay.InventoryRenderType.VILLAGER || + ctx.type() == InventoryOverlay.InventoryRenderType.HORSE || + ctx.type() == InventoryOverlay.InventoryRenderType.PLAYER || + ctx.type() == InventoryOverlay.InventoryRenderType.ARMOR_STAND || + ctx.type() == InventoryOverlay.InventoryRenderType.LIVING_ENTITY)) + { + this.lastEntityContext = Pair.of(entity.getId(), ctx); + this.context = ctx; + return ctx; + } + else if (this.lastEntityContext != null && this.lastEntityContext.getLeft().equals(entity.getId())) + { + this.context = this.lastEntityContext.getRight(); + return this.context; + } + } + + return null; + } + + @Override + public @Nullable InventoryOverlay.Context getTargetInventoryFromBlock(World world, BlockPos pos, @Nullable BlockEntity be, NbtCompound nbt) + { + Inventory inv; + + if (world == null) return null; + + if (be != null) + { + if (nbt.isEmpty()) + { + nbt = be.createNbtWithIdentifyingData(world.getRegistryManager()); + } + + inv = InventoryUtils.getInventory(world, pos); + } + else + { + if (nbt.isEmpty()) + { + Pair pair = this.requestBlockEntityAt(world, pos); + + if (pair != null) + { + nbt = pair.getRight(); + } + } + + inv = ServerDataSyncer.getInstance().getBlockInventory(world, pos, false); + } + + BlockEntityType beType = nbt != null ? NbtBlockUtils.getBlockEntityTypeFromNbt(nbt) : null; + + if ((beType != null && beType.equals(BlockEntityType.ENDER_CHEST)) || + be instanceof EnderChestBlockEntity) + { + if (MinecraftClient.getInstance().player != null) + { + PlayerEntity player = world.getPlayerByUuid(MinecraftClient.getInstance().player.getUuid()); + + if (player != null) + { + // Fetch your own EnderItems from Server ... + Pair enderPair = ServerDataSyncer.getInstance().requestEntity(world, player.getId()); + EnderChestInventory enderItems; + + if (enderPair != null && enderPair.getRight() != null && enderPair.getRight().contains(NbtKeys.ENDER_ITEMS)) + { + enderItems = InventoryUtils.getPlayerEnderItemsFromNbt(enderPair.getRight(), world.getRegistryManager()); + } + else + { + enderItems = player.getEnderChestInventory(); + } + + if (enderItems != null) + { + inv = enderItems; + } + } + } + } + + if (nbt != null && !nbt.isEmpty()) + { + //Tweakeroo.logger.warn("getTargetInventoryFromBlock(): rawNbt: [{}]", nbt.toString()); + + Inventory inv2 = InventoryUtils.getNbtInventory(nbt, inv != null ? inv.size() : -1, world.getRegistryManager()); + + if (inv == null) + { + inv = inv2; + } + } + + //Tweakeroo.logger.warn("getTarget():3: pos [{}], inv [{}], be [{}], nbt [{}]", pos.toShortString(), inv != null, be != null, nbt != null ? nbt.getString("id") : new NbtCompound()); + + if (inv == null || nbt == null) + { + return null; + } + + this.context = new InventoryOverlay.Context(InventoryOverlay.getBestInventoryType(inv, nbt), inv, be != null ? be : world.getBlockEntity(pos), null, nbt, this.getRefreshHandler()); + + return this.context; + } + + @Override + public @Nullable InventoryOverlay.Context getTargetInventoryFromEntity(Entity entity, NbtCompound nbt) + { + Inventory inv = null; + LivingEntity entityLivingBase = null; + + if (entity instanceof LivingEntity) + { + entityLivingBase = (LivingEntity) entity; + } + + if (entity instanceof Inventory) + { + inv = (Inventory) entity; + } + else if (entity instanceof PlayerEntity player) + { + inv = new SimpleInventory(player.getInventory().main.toArray(new ItemStack[36])); + } + else if (entity instanceof VillagerEntity) + { + inv = ((VillagerEntity) entity).getInventory(); + } + else if (entity instanceof AbstractHorseEntity) + { + inv = ((IMixinAbstractHorseEntity) entity).tweakeroo_getHorseInventory(); + } + else if (entity instanceof PiglinEntity) + { + inv = ((IMixinPiglinEntity) entity).tweakeroo_inventory(); + } + if (!nbt.isEmpty()) + { + Inventory inv2; + + //Tweakeroo.logger.warn("getTargetInventoryFromEntity(): rawNbt: [{}]", nbt.toString()); + + // Fix for empty horse inv + if (inv != null && + nbt.contains(NbtKeys.ITEMS) && + nbt.getList(NbtKeys.ITEMS, Constants.NBT.TAG_COMPOUND).size() > 1) + { + if (entity instanceof AbstractHorseEntity) + { + inv2 = InventoryUtils.getNbtInventoryHorseFix(nbt, -1, entity.getRegistryManager()); + } + else + { + inv2 = InventoryUtils.getNbtInventory(nbt, -1, entity.getRegistryManager()); + } + + inv = null; + } + // Fix for saddled horse, no inv + else if (inv != null && + inv.size() == 1 && + nbt.contains(NbtKeys.SADDLE)) + { + inv2 = InventoryUtils.getNbtInventoryHorseFix(nbt, -1, entity.getRegistryManager()); + inv = null; + } + // Fix for empty Villager/Piglin inv + else if (inv != null && inv.size() == 8 && + nbt.contains(NbtKeys.INVENTORY) && + !nbt.getList(NbtKeys.INVENTORY, Constants.NBT.TAG_COMPOUND).isEmpty()) + { + inv2 = InventoryUtils.getNbtInventory(nbt, 8, entity.getRegistryManager()); + inv = null; + } + else + { + inv2 = InventoryUtils.getNbtInventory(nbt, inv != null ? inv.size() : -1, entity.getRegistryManager()); + + if (inv2 != null) + { + inv = null; + } + } + + //Tweakeroo.logger.error("getTargetInventoryFromEntity(): inv.size [{}], inv2.size [{}]", inv != null ? inv.size() : "null", inv2 != null ? inv2.size() : "null"); + + if (inv2 != null) + { + inv = inv2; + } + } + + if (inv == null && entityLivingBase == null) + { + return null; + } + + this.context = new InventoryOverlay.Context(inv != null ? InventoryOverlay.getBestInventoryType(inv, nbt) : InventoryOverlay.getInventoryType(nbt), + inv, null, entityLivingBase, nbt, this.getRefreshHandler()); + + return this.context; + } + + private static void dumpContext(InventoryOverlay.Context ctx) + { + System.out.print("Context Dump --> "); + + if (ctx == null) + { + System.out.print("NULL!\n"); + return; + } + + System.out.printf("\nTYPE: [%s]\n", ctx.type().name()); + System.out.printf("BE : [%s]\n", ctx.be() != null ? Registries.BLOCK_ENTITY_TYPE.getId(ctx.be().getType()) : ""); + System.out.printf("ENT : [%s]\n", ctx.entity() != null ? Registries.ENTITY_TYPE.getId(ctx.entity().getType()) : ""); + System.out.printf("INV : [%s]\n", ctx.inv() != null ? "size: "+ctx.inv().size()+"/ empty: "+ctx.inv().isEmpty() : ""); + System.out.printf("NBT : [%s]\n", ctx.nbt() != null ? ctx.nbt().toString() : ""); + + System.out.print("--> EOF\n"); + } + + public static class Refresher implements InventoryOverlay.Refresher + { + + @Override + public InventoryOverlay.Context onContextRefresh(InventoryOverlay.Context data, World world) + { + // Refresh data + if (data.be() != null) + { + InventoryOverlayHandler.getInstance().requestBlockEntityAt(world, data.be().getPos()); + data = InventoryOverlayHandler.getInstance().getTargetInventoryFromBlock(data.be().getWorld(), data.be().getPos(), data.be(), data.nbt()); + } + else if (data.entity() != null) + { + InventoryOverlayHandler.getInstance().getDataSyncer().requestEntity(world, data.entity().getId()); + data = InventoryOverlayHandler.getInstance().getTargetInventoryFromEntity(data.entity(), data.nbt()); + } + + return data; + } + } +} diff --git a/src/main/java/fi/dy/masa/tweakeroo/renderer/RenderUtils.java b/src/main/java/fi/dy/masa/tweakeroo/renderer/RenderUtils.java index 99233b46b..d86e492c5 100644 --- a/src/main/java/fi/dy/masa/tweakeroo/renderer/RenderUtils.java +++ b/src/main/java/fi/dy/masa/tweakeroo/renderer/RenderUtils.java @@ -118,6 +118,7 @@ public static void renderHotbarSwapOverlay(MinecraftClient mc, DrawContext drawC } } + // OG Method public static void renderInventoryOverlay(InventoryOverlay.Context context, DrawContext drawContext) { MinecraftClient mc = MinecraftClient.getInstance(); diff --git a/src/main/java/fi/dy/masa/tweakeroo/util/InventoryUtils.java b/src/main/java/fi/dy/masa/tweakeroo/util/InventoryUtils.java index cc6c98cc4..e4421dbf3 100644 --- a/src/main/java/fi/dy/masa/tweakeroo/util/InventoryUtils.java +++ b/src/main/java/fi/dy/masa/tweakeroo/util/InventoryUtils.java @@ -1,11 +1,11 @@ package fi.dy.masa.tweakeroo.util; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.*; import java.util.function.Predicate; import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -15,7 +15,6 @@ import net.minecraft.component.type.AttributeModifiersComponent; import net.minecraft.component.type.ItemEnchantmentsComponent; import net.minecraft.enchantment.Enchantment; -import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.enchantment.Enchantments; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; @@ -34,7 +33,6 @@ import net.minecraft.registry.RegistryKey; import net.minecraft.registry.RegistryWrapper; import net.minecraft.registry.entry.RegistryEntry; -import net.minecraft.registry.tag.EnchantmentTags; import net.minecraft.screen.PlayerScreenHandler; import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.slot.Slot; @@ -48,6 +46,7 @@ import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.intprovider.UniformIntProvider; import net.minecraft.world.World; + import fi.dy.masa.malilib.gui.Message; import fi.dy.masa.malilib.util.Constants; import fi.dy.masa.malilib.util.GuiUtils; diff --git a/src/main/java/fi/dy/masa/tweakeroo/util/RayTraceUtils.java b/src/main/java/fi/dy/masa/tweakeroo/util/RayTraceUtils.java index 874b9bbaa..c390aa04d 100644 --- a/src/main/java/fi/dy/masa/tweakeroo/util/RayTraceUtils.java +++ b/src/main/java/fi/dy/masa/tweakeroo/util/RayTraceUtils.java @@ -3,28 +3,9 @@ import java.util.List; import java.util.Optional; import javax.annotation.Nonnull; -import com.llamalad7.mixinextras.lib.apache.commons.tuple.Pair; -import org.jetbrains.annotations.Nullable; -import net.minecraft.block.Block; -import net.minecraft.block.BlockEntityProvider; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.block.entity.EnderChestBlockEntity; -import net.minecraft.client.MinecraftClient; import net.minecraft.entity.Entity; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.mob.PiglinEntity; -import net.minecraft.entity.passive.AbstractHorseEntity; -import net.minecraft.entity.passive.VillagerEntity; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.inventory.EnderChestInventory; -import net.minecraft.inventory.Inventory; -import net.minecraft.inventory.SimpleInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.server.world.ServerWorld; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.hit.EntityHitResult; import net.minecraft.util.hit.HitResult; @@ -34,22 +15,8 @@ import net.minecraft.world.RaycastContext; import net.minecraft.world.World; -import fi.dy.masa.malilib.render.InventoryOverlay; -import fi.dy.masa.malilib.util.Constants; -import fi.dy.masa.malilib.util.EntityUtils; -import fi.dy.masa.malilib.util.InventoryUtils; -import fi.dy.masa.malilib.util.WorldUtils; -import fi.dy.masa.malilib.util.nbt.NbtBlockUtils; -import fi.dy.masa.malilib.util.nbt.NbtKeys; -import fi.dy.masa.tweakeroo.data.ServerDataSyncer; -import fi.dy.masa.tweakeroo.mixin.IMixinAbstractHorseEntity; -import fi.dy.masa.tweakeroo.mixin.IMixinPiglinEntity; - public class RayTraceUtils { - private static Pair lastBlockEntityContext = null; - private static Pair lastEntityContext = null; - @Nonnull public static HitResult getRayTraceFromEntity(World worldIn, Entity entityIn, boolean useLiquids) { @@ -106,304 +73,4 @@ public static HitResult getRayTraceFromEntity(World worldIn, Entity entityIn, bo return result; } - - public static @Nullable InventoryOverlay.Context getTargetInventory(MinecraftClient mc) - { - World world = WorldUtils.getBestWorld(mc); - Entity cameraEntity = EntityUtils.getCameraEntity(); - - if (mc.player == null || world == null) - { - return null; - } - - if (cameraEntity == mc.player && world instanceof ServerWorld) - { - // We need to get the player from the server world (if available, ie. in single player), - // so that the player itself won't be included in the ray trace - Entity serverPlayer = world.getPlayerByUuid(mc.player.getUuid()); - - if (serverPlayer != null) - { - cameraEntity = serverPlayer; - } - } - - HitResult trace = getRayTraceFromEntity(world, cameraEntity, false); - NbtCompound nbt = new NbtCompound(); - - if (trace.getType() == HitResult.Type.BLOCK) - { - BlockPos pos = ((BlockHitResult) trace).getBlockPos(); - BlockState state = world.getBlockState(pos); - Block blockTmp = state.getBlock(); - BlockEntity be = null; - - //Tweakeroo.logger.warn("getTarget():1: pos [{}], state [{}]", pos.toShortString(), state.toString()); - - if (blockTmp instanceof BlockEntityProvider) - { - if (world instanceof ServerWorld) - { - be = world.getWorldChunk(pos).getBlockEntity(pos); - - if (be != null) - { - nbt = be.createNbtWithIdentifyingData(world.getRegistryManager()); - } - } - else - { - Pair pair = ServerDataSyncer.getInstance().requestBlockEntity(world, pos); - - if (pair != null) - { - nbt = pair.getRight(); - } - } - - //Tweakeroo.logger.warn("getTarget():2: pos [{}], be [{}], nbt [{}]", pos.toShortString(), be != null, nbt != null); - - InventoryOverlay.Context ctx = getTargetInventoryFromBlock(world, pos, be, nbt); - - if (lastBlockEntityContext != null && !lastBlockEntityContext.getLeft().equals(pos)) - { - lastBlockEntityContext = null; - } - - if (ctx != null && ctx.inv() != null) - { - lastBlockEntityContext = Pair.of(pos, ctx); - return ctx; - } - else if (lastBlockEntityContext != null && lastBlockEntityContext.getLeft().equals(pos)) - { - return lastBlockEntityContext.getRight(); - } - } - - return null; - } - else if (trace.getType() == HitResult.Type.ENTITY) - { - Entity entity = ((EntityHitResult) trace).getEntity(); - - if (world instanceof ServerWorld) - { - entity.saveSelfNbt(nbt); - } - else - { - Pair pair = ServerDataSyncer.getInstance().requestEntity(entity.getId()); - - if (pair != null) - { - nbt = pair.getRight(); - } - } - - //Tweakeroo.logger.error("getTarget(): Entity [{}] raw NBT [{}]", entity.getId(), nbt.toString()); - InventoryOverlay.Context ctx = getTargetInventoryFromEntity(world.getEntityById(entity.getId()), nbt); - - if (lastEntityContext != null && !lastEntityContext.getLeft().equals(entity.getId())) - { - lastEntityContext = null; - } - - if (ctx != null && ctx.inv() != null) - { - lastEntityContext = Pair.of(entity.getId(), ctx); - return ctx; - } - // Non-Inventory/Empty Entity - else if (ctx != null && - (ctx.type() == InventoryOverlay.InventoryRenderType.WOLF || - ctx.type() == InventoryOverlay.InventoryRenderType.VILLAGER || - ctx.type() == InventoryOverlay.InventoryRenderType.HORSE || - ctx.type() == InventoryOverlay.InventoryRenderType.PLAYER || - ctx.type() == InventoryOverlay.InventoryRenderType.ARMOR_STAND || - ctx.type() == InventoryOverlay.InventoryRenderType.LIVING_ENTITY)) - { - lastEntityContext = Pair.of(entity.getId(), ctx); - return ctx; - } - else if (lastEntityContext != null && lastEntityContext.getLeft().equals(entity.getId())) - { - return lastEntityContext.getRight(); - } - } - - return null; - } - - public static @Nullable InventoryOverlay.Context getTargetInventoryFromBlock(World world, BlockPos pos, @Nullable BlockEntity be, NbtCompound nbt) - { - Inventory inv; - - if (be != null) - { - if (nbt.isEmpty()) - { - nbt = be.createNbtWithIdentifyingData(world.getRegistryManager()); - } - inv = fi.dy.masa.malilib.util.InventoryUtils.getInventory(world, pos); - } - else - { - if (nbt.isEmpty()) - { - Pair pair = ServerDataSyncer.getInstance().requestBlockEntity(world, pos); - - if (pair != null) - { - nbt = pair.getRight(); - } - } - - inv = ServerDataSyncer.getInstance().getBlockInventory(world, pos, false); - } - - BlockEntityType beType = nbt != null ? NbtBlockUtils.getBlockEntityTypeFromNbt(nbt) : null; - - if ((beType != null && beType.equals(BlockEntityType.ENDER_CHEST)) || - be instanceof EnderChestBlockEntity) - { - if (MinecraftClient.getInstance().player != null) - { - PlayerEntity player = world.getPlayerByUuid(MinecraftClient.getInstance().player.getUuid()); - - if (player != null) - { - // Fetch your own EnderItems from Server ... - Pair enderPair = ServerDataSyncer.getInstance().requestEntity(player.getId()); - EnderChestInventory enderItems; - - if (enderPair != null && enderPair.getRight() != null && enderPair.getRight().contains(NbtKeys.ENDER_ITEMS)) - { - enderItems = InventoryUtils.getPlayerEnderItemsFromNbt(enderPair.getRight(), world.getRegistryManager()); - } - else - { - enderItems = player.getEnderChestInventory(); - } - - if (enderItems != null) - { - inv = enderItems; - } - } - } - } - - if (nbt != null && !nbt.isEmpty()) - { - Inventory inv2 = fi.dy.masa.malilib.util.InventoryUtils.getNbtInventory(nbt, inv != null ? inv.size() : -1, world.getRegistryManager()); - - if (inv == null) - { - inv = inv2; - } - } - - //Tweakeroo.logger.warn("getTarget():3: pos [{}], inv [{}], be [{}], nbt [{}]", pos.toShortString(), inv != null, be != null, nbt != null ? nbt.getString("id") : new NbtCompound()); - - if (inv == null || nbt == null) - { - return null; - } - - return new InventoryOverlay.Context(InventoryOverlay.getBestInventoryType(inv, nbt), inv, be != null ? be : world.getBlockEntity(pos), null, nbt); - } - - public static @Nullable InventoryOverlay.Context getTargetInventoryFromEntity(Entity entity, NbtCompound nbt) - { - Inventory inv = null; - LivingEntity entityLivingBase = null; - - if (entity instanceof LivingEntity) - { - entityLivingBase = (LivingEntity) entity; - } - - if (entity instanceof Inventory) - { - inv = (Inventory) entity; - } - else if (entity instanceof PlayerEntity player) - { - inv = new SimpleInventory(player.getInventory().main.toArray(new ItemStack[36])); - } - else if (entity instanceof VillagerEntity) - { - inv = ((VillagerEntity) entity).getInventory(); - } - else if (entity instanceof AbstractHorseEntity) - { - inv = ((IMixinAbstractHorseEntity) entity).tweakeroo_getHorseInventory(); - } - else if (entity instanceof PiglinEntity) - { - inv = ((IMixinPiglinEntity) entity).tweakeroo_inventory(); - } - if (!nbt.isEmpty()) - { - Inventory inv2; - - //Tweakeroo.logger.warn("getTargetInventoryFromEntity(): rawNbt: [{}]", nbt.toString()); - - // Fix for empty horse inv - if (inv != null && - nbt.contains(NbtKeys.ITEMS) && - nbt.getList(NbtKeys.ITEMS, Constants.NBT.TAG_COMPOUND).size() > 1) - { - if (entity instanceof AbstractHorseEntity) - { - inv2 = InventoryUtils.getNbtInventoryHorseFix(nbt, -1, entity.getRegistryManager()); - } - else - { - inv2 = InventoryUtils.getNbtInventory(nbt, -1, entity.getRegistryManager()); - } - inv = null; - } - // Fix for saddled horse, no inv - else if (inv != null && nbt.contains(NbtKeys.SADDLE)) - { - inv2 = InventoryUtils.getNbtInventoryHorseFix(nbt, -1, entity.getRegistryManager()); - inv = null; - } - // Fix for empty Villager/Piglin inv - else if (inv != null && inv.size() == 8 && - nbt.contains(NbtKeys.INVENTORY) && - !nbt.getList(NbtKeys.INVENTORY, Constants.NBT.TAG_COMPOUND).isEmpty()) - { - inv2 = InventoryUtils.getNbtInventory(nbt, 8, entity.getRegistryManager()); - inv = null; - } - else - { - inv2 = InventoryUtils.getNbtInventory(nbt, inv != null ? inv.size() : -1, entity.getRegistryManager()); - - if (inv2 != null) - { - inv = null; - } - } - - //Tweakeroo.logger.error("getTargetInventoryFromEntity(): inv.size [{}], inv2.size [{}]", inv != null ? inv.size() : "null", inv2 != null ? inv2.size() : "null"); - - if (inv2 != null) - { - inv = inv2; - } - } - - if (inv == null && entityLivingBase == null) - { - return null; - } - - return new InventoryOverlay.Context(inv != null ? InventoryOverlay.getBestInventoryType(inv, nbt) : InventoryOverlay.getInventoryType(nbt), - inv, null, entityLivingBase, nbt); - } } diff --git a/src/main/resources/assets/tweakeroo/lang/en_us.json b/src/main/resources/assets/tweakeroo/lang/en_us.json index f1620c180..87021b6b1 100644 --- a/src/main/resources/assets/tweakeroo/lang/en_us.json +++ b/src/main/resources/assets/tweakeroo/lang/en_us.json @@ -427,6 +427,7 @@ "tweakeroo.config.hotkey.name.hotbarSwap2": "hotbarSwap2", "tweakeroo.config.hotkey.name.hotbarSwap3": "hotbarSwap3", "tweakeroo.config.hotkey.name.inventoryPreview": "inventoryPreview", + "tweakeroo.config.hotkey.name.inventoryPreviewToggleScreen": "inventoryPreviewToggleScreen", "tweakeroo.config.hotkey.name.openConfigGui": "openConfigGui", "tweakeroo.config.hotkey.name.placementYMirror": "placementYMirror", "tweakeroo.config.hotkey.name.playerInventoryPeek": "playerInventoryPeek", @@ -471,7 +472,8 @@ "tweakeroo.config.hotkey.comment.hotbarSwap1": "Swap the hotbar with the top-most inventory row", "tweakeroo.config.hotkey.comment.hotbarSwap2": "Swap the hotbar with the middle inventory row", "tweakeroo.config.hotkey.comment.hotbarSwap3": "Swap the hotbar with the bottom-most inventory row", - "tweakeroo.config.hotkey.comment.inventoryPreview": "The key to activate the inventory preview feature\n§6Deprecated in favor of the 1.21+ MiniHUD version", + "tweakeroo.config.hotkey.comment.inventoryPreview": "The key to activate the inventory preview feature", + "tweakeroo.config.hotkey.comment.inventoryPreviewToggleScreen": "Open a screen for inventory preview\nYou can use your mouse to see tooltips", "tweakeroo.config.hotkey.comment.openConfigGui": "The key open the in-game config GUI", "tweakeroo.config.hotkey.comment.placementYMirror": "The key to mirror the targeted y-position within the block", "tweakeroo.config.hotkey.comment.playerInventoryPeek": "The key to activate the player inventory peek/preview feature", diff --git a/src/main/resources/assets/tweakeroo/lang/zh_cn.json b/src/main/resources/assets/tweakeroo/lang/zh_cn.json index 071fae91b..cf71a2f6c 100644 --- a/src/main/resources/assets/tweakeroo/lang/zh_cn.json +++ b/src/main/resources/assets/tweakeroo/lang/zh_cn.json @@ -415,6 +415,7 @@ "tweakeroo.config.hotkey.name.hotbarSwap2": "中层快捷切换", "tweakeroo.config.hotkey.name.hotbarSwap3": "底层快捷切换", "tweakeroo.config.hotkey.name.inventoryPreview": "容器预览(已弃用)§f", + "tweakeroo.config.hotkey.name.inventoryPreviewToggleScreen": "容器预览鼠标释放", "tweakeroo.config.hotkey.name.openConfigGui": "打开配置界面", "tweakeroo.config.hotkey.name.placementYMirror": "Y 轴镜像放置", "tweakeroo.config.hotkey.name.playerInventoryPeek": "玩家背包预览", @@ -458,7 +459,8 @@ "tweakeroo.config.hotkey.comment.hotbarSwap1": "按下快捷键时,将物品栏与背包顶层一行交换", "tweakeroo.config.hotkey.comment.hotbarSwap2": "按下快捷键时,将物品栏与背包中层一行交换", "tweakeroo.config.hotkey.comment.hotbarSwap3": "按下快捷键时,将物品栏与背包底层一行交换", - "tweakeroo.config.hotkey.comment.inventoryPreview": "按下快捷键时,可预览容器内的物品。 \n§c已弃用,在 1.21+ 版本的 MiniHUD 中已经实现了此功能§f", + "tweakeroo.config.hotkey.comment.inventoryPreview": "按下快捷键时,可预览容器内的物品。", + "tweakeroo.config.hotkey.comment.inventoryPreviewToggleScreen": "按下后释放鼠标指针,以便查看具体的物品信息。", "tweakeroo.config.hotkey.comment.openConfigGui": "打开 Tweakeroo 配置界面的快捷键", "tweakeroo.config.hotkey.comment.placementYMirror": "按下快捷键时,将方块以 Y 轴镜像的方式放置出来。\n需要开启 §6[工具] -> [Y轴镜像放置]§r", "tweakeroo.config.hotkey.comment.playerInventoryPeek": "激活 §6[玩家背包预览]§r 功能的热键", diff --git a/src/main/resources/assets/tweakeroo/lang/zh_tw.json b/src/main/resources/assets/tweakeroo/lang/zh_tw.json index b4bc62f9a..969a6df9e 100644 --- a/src/main/resources/assets/tweakeroo/lang/zh_tw.json +++ b/src/main/resources/assets/tweakeroo/lang/zh_tw.json @@ -415,6 +415,7 @@ "tweakeroo.config.hotkey.name.hotbarSwap2": "中層快捷切換", "tweakeroo.config.hotkey.name.hotbarSwap3": "底層快捷切換", "tweakeroo.config.hotkey.name.inventoryPreview": "容器預覽(已棄用)§f", + "tweakeroo.config.hotkey.name.inventoryPreviewToggleScreen": "容器預覽滑鼠釋放", "tweakeroo.config.hotkey.name.openConfigGui": "開啟設定介面", "tweakeroo.config.hotkey.name.placementYMirror": "Y 軸鏡像放置", "tweakeroo.config.hotkey.name.playerInventoryPeek": "玩家背包預覽", @@ -458,7 +459,8 @@ "tweakeroo.config.hotkey.comment.hotbarSwap1": "按下快捷鍵時,將物品欄與背包頂層一行交換", "tweakeroo.config.hotkey.comment.hotbarSwap2": "按下快捷鍵時,將物品欄與背包中層一行交換", "tweakeroo.config.hotkey.comment.hotbarSwap3": "按下快捷鍵時,將物品欄與背包底層一行交換", - "tweakeroo.config.hotkey.comment.inventoryPreview": "按下快捷鍵時,可預覽容器內的物品。 \n§c已棄用,在 1.21+ 版本的 MiniHUD 中已經實現了此功能§f", + "tweakeroo.config.hotkey.comment.inventoryPreview": "按下快捷鍵時,可預覽容器內的物品。", + "tweakeroo.config.hotkey.comment.inventoryPreviewToggleScreen": "按下後釋放滑鼠指標,以便檢視具體的物品資訊。", "tweakeroo.config.hotkey.comment.openConfigGui": "開啟 Tweakeroo 設定介面的快捷鍵", "tweakeroo.config.hotkey.comment.placementYMirror": "按下快捷鍵時,將方塊以 Y 軸鏡像的方式放置出來。\n需要開啟 §6[工具] -> [Y軸鏡像放置]§r", "tweakeroo.config.hotkey.comment.playerInventoryPeek": "啟動 §6[玩家背包預覽]§r 功能的快速鍵",