diff --git a/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_11_1to1_12/Protocol1_11_1To1_12.java b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_11_1to1_12/Protocol1_11_1To1_12.java index 94542771..0a3652c7 100644 --- a/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_11_1to1_12/Protocol1_11_1To1_12.java +++ b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_11_1to1_12/Protocol1_11_1To1_12.java @@ -15,6 +15,7 @@ import nl.matsv.viabackwards.api.BackwardsProtocol; import nl.matsv.viabackwards.api.entities.storage.EntityTracker; import nl.matsv.viabackwards.protocol.protocol1_11_1to1_12.data.ShoulderTracker; import nl.matsv.viabackwards.protocol.protocol1_11_1to1_12.packets.*; +import nl.matsv.viabackwards.protocol.protocol1_11_1to1_12.storage.InventoryTracker; import us.myles.ViaVersion.api.data.UserConnection; import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld; @@ -44,6 +45,7 @@ public class Protocol1_11_1To1_12 extends BackwardsProtocol { user.put(new EntityTracker(user)); user.put(new ShoulderTracker(user)); + user.put(new InventoryTracker(user)); // Init protocol in EntityTracker user.get(EntityTracker.class).initProtocol(this); diff --git a/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_11_1to1_12/packets/BlockItemPackets1_12.java b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_11_1to1_12/packets/BlockItemPackets1_12.java index 7c01bbe7..8ed1bcf8 100644 --- a/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_11_1to1_12/packets/BlockItemPackets1_12.java +++ b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_11_1to1_12/packets/BlockItemPackets1_12.java @@ -10,10 +10,12 @@ package nl.matsv.viabackwards.protocol.protocol1_11_1to1_12.packets; +import com.google.common.collect.Lists; import nl.matsv.viabackwards.api.rewriters.BlockItemRewriter; import nl.matsv.viabackwards.protocol.protocol1_11_1to1_12.Protocol1_11_1To1_12; import nl.matsv.viabackwards.protocol.protocol1_11_1to1_12.data.BlockColors; import nl.matsv.viabackwards.protocol.protocol1_11_1to1_12.data.MapColorMapping; +import nl.matsv.viabackwards.protocol.protocol1_11_1to1_12.storage.InventoryTracker; import nl.matsv.viabackwards.utils.Block; import us.myles.ViaVersion.api.PacketWrapper; import us.myles.ViaVersion.api.minecraft.BlockChangeRecord; @@ -27,14 +29,68 @@ import us.myles.ViaVersion.packets.State; import us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.types.Chunk1_9_3_4Type; import us.myles.ViaVersion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld; import us.myles.viaversion.libs.opennbt.tag.builtin.CompoundTag; +import us.myles.viaversion.libs.opennbt.tag.builtin.DoubleTag; import us.myles.viaversion.libs.opennbt.tag.builtin.ListTag; import java.util.Collections; +import java.util.Iterator; public class BlockItemPackets1_12 extends BlockItemRewriter { @Override protected void registerPackets(Protocol1_11_1To1_12 protocol) { - /* Item packets */ + /* Item packets */ + + // Confirm Transaction + protocol.registerOutgoing(State.PLAY, 0x11, 0x11, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.BYTE); // Window id + map(Type.SHORT); // Action number + map(Type.BOOLEAN); // Accepted + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper packetWrapper) throws Exception { + byte window = packetWrapper.get(Type.BYTE, 0); + boolean accepted = packetWrapper.get(Type.BOOLEAN, 0); + short actionNumber = packetWrapper.get(Type.SHORT, 0); + InventoryTracker tracker = packetWrapper.user().get(InventoryTracker.class); + + boolean clear = false; + Iterator it = Lists.reverse(tracker.getClicks()).iterator(); + while (it.hasNext()) { + InventoryTracker.ClickWindow entry = it.next(); + if (entry.actionNumber == actionNumber || clear) { + it.remove(); + clear = true; + } + } + if (!accepted) { + if (tracker.getLastTransactionWindow() == window && + tracker.getLastShiftTransaction() != -1) { + PacketWrapper confirm = packetWrapper.create(0x6); + confirm.write(Type.BYTE, window); + confirm.write(Type.SHORT, actionNumber); + confirm.write(Type.BOOLEAN, false); + confirm.sendToServer(Protocol1_11_1To1_12.class, true, true); + } + if (tracker.getClicks().size() != 0) { + InventoryTracker.ClickWindow entry = tracker.getClicks().get(0); + PacketWrapper click = packetWrapper.create(0x8); + click.write(Type.UNSIGNED_BYTE, entry.windowId); + click.write(Type.SHORT, entry.slot); + click.write(Type.BYTE, entry.button); + click.write(Type.SHORT, entry.actionNumber); + click.write(Type.VAR_INT, entry.mode); + CompoundTag tag = new CompoundTag(""); + tag.put(new DoubleTag("force reject", Double.NaN)); + click.write(Type.ITEM, new Item((short) 1, (byte) 1, (short) 1, tag)); + click.sendToServer(Protocol1_11_1To1_12.class, true, true); + } + } + } + }); + } + }); protocol.registerOutgoing(State.PLAY, 0x24, 0x24, new PacketRemapper() { @Override @@ -158,8 +214,35 @@ public class BlockItemPackets1_12 extends BlockItemRewriter { - Metadata data = e.getData(); + protocol.getEntityPackets(). - if (data.getMetaType().getType().equals(Type.ITEM)) // Is Item - data.setValue(handleItemToClient((Item) data.getValue())); + registerMetaHandler(). - return data; - }); + handle(e -> + + { + Metadata data = e.getData(); + + if (data.getMetaType().getType().equals(Type.ITEM)) // Is Item + data.setValue(handleItemToClient((Item) data.getValue())); + + return data; + }); // Client Status - protocol.registerIncoming(State.PLAY, 0x04, 0x03, new PacketRemapper() { - @Override - public void registerMap() { - map(Type.VAR_INT); // Action ID + protocol.registerIncoming(State.PLAY, 0x04, 0x03, new - handler(new PacketHandler() { + PacketRemapper() { @Override - public void handle(PacketWrapper wrapper) throws Exception { - // Open Inventory - if (wrapper.get(Type.VAR_INT, 0) == 2) - wrapper.cancel(); // TODO is this replaced by something else? + public void registerMap() { + map(Type.VAR_INT); // Action ID + + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + // Open Inventory + if (wrapper.get(Type.VAR_INT, 0) == 2) + wrapper.cancel(); // TODO is this replaced by something else? + } + }); } }); - } - }); } @Override diff --git a/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_11_1to1_12/packets/ChangedPacketIds1_12.java b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_11_1to1_12/packets/ChangedPacketIds1_12.java index 17e48b30..88ab112b 100644 --- a/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_11_1to1_12/packets/ChangedPacketIds1_12.java +++ b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_11_1to1_12/packets/ChangedPacketIds1_12.java @@ -92,7 +92,6 @@ public class ChangedPacketIds1_12 extends Rewriter { p.registerIncoming(State.PLAY, 0x03, 0x02); // Chat Message (Serverbound) // 0x04->0x03 Client Status handled in BlockItemPackets1_12.java p.registerIncoming(State.PLAY, 0x05, 0x04); // Client Settings - p.registerIncoming(State.PLAY, 0x06, 0x05); // Confirm Transaction (Serverbound) p.registerIncoming(State.PLAY, 0x07, 0x06); // Enchant Item // 0x08 -> 0x07 Click Window handled in BlockItemPackets1_12.java p.registerIncoming(State.PLAY, 0x09, 0x08); // Close Window (Serverbound) diff --git a/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_11_1to1_12/storage/InventoryTracker.java b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_11_1to1_12/storage/InventoryTracker.java new file mode 100644 index 00000000..956b307a --- /dev/null +++ b/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_11_1to1_12/storage/InventoryTracker.java @@ -0,0 +1,32 @@ +package nl.matsv.viabackwards.protocol.protocol1_11_1to1_12.storage; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import us.myles.ViaVersion.api.data.StoredObject; +import us.myles.ViaVersion.api.data.UserConnection; + +import java.util.ArrayList; + +@Getter +@Setter +public class InventoryTracker extends StoredObject { + private int lastTransactionWindow = -1; + private int lastShiftTransaction = -1; + // Workaround for https://github.com/Matsv/ViaBackwards/issues/48 + // Resent when it is rejected + private ArrayList clicks = new ArrayList<>(); + + public InventoryTracker(UserConnection user) { + super(user); + } + + @AllArgsConstructor + public static class ClickWindow { + public short windowId; + public short slot; + public byte button; + public short actionNumber; + public int mode; + } +}