From 9bf54d1723d0a59c09575986ec843b0e9c72c034 Mon Sep 17 00:00:00 2001 From: Term4 Date: Wed, 24 Jun 2026 22:14:38 -0500 Subject: [PATCH 1/2] 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 a7b3ff04179744eb9a2f8e4aa3389e6ea35eb694 Mon Sep 17 00:00:00 2001 From: Term4 Date: Thu, 25 Jun 2026 20:29:31 -0500 Subject: [PATCH 2/2] 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) {