From 175b9974898188c809a0337f80718ca727b65645 Mon Sep 17 00:00:00 2001 From: Term4 Date: Wed, 24 Jun 2026 22:14:38 -0500 Subject: [PATCH 1/3] Update BlockItemPacketRewriter1_9.java --- .../rewriter/BlockItemPacketRewriter1_9.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/common/src/main/java/com/viaversion/viarewind/protocol/v1_9to1_8/rewriter/BlockItemPacketRewriter1_9.java b/common/src/main/java/com/viaversion/viarewind/protocol/v1_9to1_8/rewriter/BlockItemPacketRewriter1_9.java index 4963eacfe..9e4c399c6 100644 --- a/common/src/main/java/com/viaversion/viarewind/protocol/v1_9to1_8/rewriter/BlockItemPacketRewriter1_9.java +++ b/common/src/main/java/com/viaversion/viarewind/protocol/v1_9to1_8/rewriter/BlockItemPacketRewriter1_9.java @@ -116,6 +116,21 @@ protected void registerPackets() { final Item item = wrapper.passthrough(Types.ITEM1_8); handleItemToClient(wrapper.user(), item); + if (windowId == -2) { + // 1.8 has no window -2 (set player-inventory slot directly); remap to window 0 with the menu slot. + final int windowSlot; + if (slot >= 0 && slot <= 8) windowSlot = slot + 36; + else if (slot >= 36 && slot <= 39) windowSlot = 44 - slot; + else if (slot == 40) windowSlot = 45; + else windowSlot = slot; + if (windowSlot == 45) { + wrapper.cancel(); + return; + } + wrapper.set(Types.BYTE, 0, (byte) 0); + wrapper.set(Types.SHORT, 0, (short) windowSlot); + return; + } if (windowId == 0 && slot == 45) { wrapper.cancel(); return; From cd9354993f1b3c402dbf12d754c54b5b27d0cfce Mon Sep 17 00:00:00 2001 From: Term4 Date: Thu, 25 Jun 2026 20:29:31 -0500 Subject: [PATCH 2/3] Handled saddle and body armor, added container tracking --- .../rewriter/BlockItemPacketRewriter1_9.java | 32 ++++++++++++++++--- .../v1_9to1_8/storage/WindowTracker.java | 20 ++++++++++++ 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/common/src/main/java/com/viaversion/viarewind/protocol/v1_9to1_8/rewriter/BlockItemPacketRewriter1_9.java b/common/src/main/java/com/viaversion/viarewind/protocol/v1_9to1_8/rewriter/BlockItemPacketRewriter1_9.java index 9e4c399c6..b64962eb2 100644 --- a/common/src/main/java/com/viaversion/viarewind/protocol/v1_9to1_8/rewriter/BlockItemPacketRewriter1_9.java +++ b/common/src/main/java/com/viaversion/viarewind/protocol/v1_9to1_8/rewriter/BlockItemPacketRewriter1_9.java @@ -79,8 +79,14 @@ protected void registerPackets() { protocol.registerClientbound(ClientboundPackets1_9.OPEN_SCREEN, wrapper -> { final short windowId = wrapper.passthrough(Types.UNSIGNED_BYTE); final String windowType = wrapper.passthrough(Types.STRING); + wrapper.passthrough(Types.COMPONENT); // title + final short slotCount = wrapper.passthrough(Types.UNSIGNED_BYTE); - wrapper.user().get(WindowTracker.class).put(windowId, windowType); + final WindowTracker tracker = wrapper.user().get(WindowTracker.class); + tracker.put(windowId, windowType); + // 1.8 brewing has no fuel slot; ViaRewind drops it, so the client sees one fewer. + final boolean brewing = windowType.equalsIgnoreCase("minecraft:brewing_stand"); + tracker.openWindow(windowId, brewing ? slotCount - 1 : slotCount); }); protocol.registerClientbound(ClientboundPackets1_9.CONTAINER_SET_CONTENT, wrapper -> { @@ -117,13 +123,29 @@ protected void registerPackets() { handleItemToClient(wrapper.user(), item); if (windowId == -2) { - // 1.8 has no window -2 (set player-inventory slot directly); remap to window 0 with the menu slot. + // 1.8 has no window -2 (set a player-inv slot by raw index, ignoring the open container) — retarget it. + final WindowTracker tracker = wrapper.user().get(WindowTracker.class); + final short openWindow = tracker.openWindowId(); + if (openWindow != 0) { + // Foreign container open: 1.8 only applies player-inv changes through it (main=size.., hotbar=size+27..). + final int size = tracker.openWindowSize(); + final int containerSlot; + if (slot >= 0 && slot <= 8) containerSlot = size + 27 + slot; + else if (slot >= 9 && slot <= 35) containerSlot = size + slot - 9; + else { // armor/offhand: no slot in a foreign container + wrapper.cancel(); + return; + } + wrapper.set(Types.BYTE, 0, (byte) openWindow); + wrapper.set(Types.SHORT, 0, (short) containerSlot); + return; + } + // Otherwise window 0 with the menu slot. final int windowSlot; if (slot >= 0 && slot <= 8) windowSlot = slot + 36; + else if (slot >= 9 && slot <= 35) windowSlot = slot; else if (slot >= 36 && slot <= 39) windowSlot = 44 - slot; - else if (slot == 40) windowSlot = 45; - else windowSlot = slot; - if (windowSlot == 45) { + else { // offhand/body/saddle: no 1.8 equivalent wrapper.cancel(); return; } diff --git a/common/src/main/java/com/viaversion/viarewind/protocol/v1_9to1_8/storage/WindowTracker.java b/common/src/main/java/com/viaversion/viarewind/protocol/v1_9to1_8/storage/WindowTracker.java index e95f180b7..9286b64a3 100644 --- a/common/src/main/java/com/viaversion/viarewind/protocol/v1_9to1_8/storage/WindowTracker.java +++ b/common/src/main/java/com/viaversion/viarewind/protocol/v1_9to1_8/storage/WindowTracker.java @@ -38,6 +38,9 @@ public class WindowTracker extends StoredObject { private final HashMap brewingItems = new HashMap<>(); private final Map enchantmentProperties = new HashMap<>(); + private short openWindowId = 0; // 0 = none open + private int openWindowSize = 0; // open window's container slots, excluding the player inventory + public WindowTracker(UserConnection user) { super(user); } @@ -83,6 +86,23 @@ public void put(short windowId, String type) { public void remove(short windowId) { types.remove(windowId); brewingItems.remove(windowId); + if (windowId == openWindowId) { + openWindowId = 0; + openWindowSize = 0; + } + } + + public void openWindow(short windowId, int slotCount) { + openWindowId = windowId; + openWindowSize = slotCount; + } + + public short openWindowId() { + return openWindowId; + } + + public int openWindowSize() { + return openWindowSize; } public Item[] getBrewingItems(short windowId) { From 9726bbdd60d3fb6659011329e90110e08b8e4fbe Mon Sep 17 00:00:00 2001 From: Beanes Date: Sat, 4 Jul 2026 19:58:59 +0200 Subject: [PATCH 3/3] Add proper inventory size detection --- .../rewriter/BlockItemPacketRewriter1_9.java | 20 ++++++++++++++++--- .../v1_9to1_8/storage/WindowTracker.java | 2 +- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/common/src/main/java/com/viaversion/viarewind/protocol/v1_9to1_8/rewriter/BlockItemPacketRewriter1_9.java b/common/src/main/java/com/viaversion/viarewind/protocol/v1_9to1_8/rewriter/BlockItemPacketRewriter1_9.java index b64962eb2..7b4988469 100644 --- a/common/src/main/java/com/viaversion/viarewind/protocol/v1_9to1_8/rewriter/BlockItemPacketRewriter1_9.java +++ b/common/src/main/java/com/viaversion/viarewind/protocol/v1_9to1_8/rewriter/BlockItemPacketRewriter1_9.java @@ -84,9 +84,7 @@ protected void registerPackets() { final WindowTracker tracker = wrapper.user().get(WindowTracker.class); tracker.put(windowId, windowType); - // 1.8 brewing has no fuel slot; ViaRewind drops it, so the client sees one fewer. - final boolean brewing = windowType.equalsIgnoreCase("minecraft:brewing_stand"); - tracker.openWindow(windowId, brewing ? slotCount - 1 : slotCount); + tracker.openWindow(windowId, clientInventorySize(windowType, slotCount)); }); protocol.registerClientbound(ClientboundPackets1_9.CONTAINER_SET_CONTENT, wrapper -> { @@ -229,6 +227,22 @@ protected void registerRewrites() { enchantmentRewriter.registerEnchantment(70, "§7Mending"); } + static int clientInventorySize(String windowType, int packetSlotCount) { + // The client only uses the packet's slot count when constructing dynamic inventories. + // Fixed menus construct their own slots; use the translated 1.8 layout for those. + return switch (windowType) { + case "minecraft:furnace", "minecraft:villager", "minecraft:anvil" -> 3; + case "minecraft:brewing_stand" -> 4; + case "minecraft:beacon" -> 1; + case "minecraft:dispenser", "minecraft:dropper" -> 9; + case "minecraft:enchanting_table" -> 2; + case "minecraft:crafting_table" -> 10; + case "minecraft:hopper" -> packetSlotCount; + case "EntityHorse" -> packetSlotCount > 2 ? 17 : 2; + default -> packetSlotCount / 9 * 9; + }; + } + @Override public Item handleItemToClient(UserConnection connection, Item item) { if (item == null) return null; diff --git a/common/src/main/java/com/viaversion/viarewind/protocol/v1_9to1_8/storage/WindowTracker.java b/common/src/main/java/com/viaversion/viarewind/protocol/v1_9to1_8/storage/WindowTracker.java index 9286b64a3..d52add432 100644 --- a/common/src/main/java/com/viaversion/viarewind/protocol/v1_9to1_8/storage/WindowTracker.java +++ b/common/src/main/java/com/viaversion/viarewind/protocol/v1_9to1_8/storage/WindowTracker.java @@ -39,7 +39,7 @@ public class WindowTracker extends StoredObject { private final Map enchantmentProperties = new HashMap<>(); private short openWindowId = 0; // 0 = none open - private int openWindowSize = 0; // open window's container slots, excluding the player inventory + private int openWindowSize = 0; // Translated client container slots, excluding the player inventory public WindowTracker(UserConnection user) { super(user);