diff --git a/src/main/java/org/dragonet/proxy/data/inventory/ContainerId.java b/src/main/java/org/dragonet/proxy/data/inventory/ContainerId.java index b082459a3..51793d91f 100644 --- a/src/main/java/org/dragonet/proxy/data/inventory/ContainerId.java +++ b/src/main/java/org/dragonet/proxy/data/inventory/ContainerId.java @@ -4,6 +4,7 @@ * Created on 2017/10/21. */ public enum ContainerId { + NONE(1), INVENTORY(0), FIRST(1), diff --git a/src/main/java/org/dragonet/proxy/data/inventory/PEWindowConstantID.java b/src/main/java/org/dragonet/proxy/data/inventory/PEWindowConstantID.java deleted file mode 100644 index 0207bbc83..000000000 --- a/src/main/java/org/dragonet/proxy/data/inventory/PEWindowConstantID.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * GNU LESSER GENERAL PUBLIC LICENSE - * Version 3, 29 June 2007 - * - * Copyright (C) 2007 Free Software Foundation, Inc. - * Everyone is permitted to copy and distribute verbatim copies - * of this license document, but changing it is not allowed. - * - * You can view LICENCE file for details. - * - * @author The Dragonet Team - */ -package org.dragonet.proxy.data.inventory; - -public enum PEWindowConstantID { - PLAYER_INVENTORY(0x00), - PLAYER_ARMOR(0x78), - PLAYER_CREATIVE(0x79); - - private final byte id; - - PEWindowConstantID(int id) { - this.id = (byte) id; - } - - public byte getId() { - return id; - } -} diff --git a/src/main/java/org/dragonet/proxy/network/InventoryTranslatorRegister.java b/src/main/java/org/dragonet/proxy/network/InventoryTranslatorRegister.java index 4a8ff3c8f..0784415a5 100644 --- a/src/main/java/org/dragonet/proxy/network/InventoryTranslatorRegister.java +++ b/src/main/java/org/dragonet/proxy/network/InventoryTranslatorRegister.java @@ -21,7 +21,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.server.window.ServerOpenWindowPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.window.ServerSetSlotPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.window.ServerWindowItemsPacket; -import org.dragonet.proxy.data.inventory.PEWindowConstantID; +import org.dragonet.proxy.data.inventory.ContainerId; import org.dragonet.proxy.network.cache.CachedWindow; import org.dragonet.proxy.network.translator.ItemBlockTranslator; import org.dragonet.proxy.network.translator.inv.ChestWindowTranslator; @@ -44,7 +44,7 @@ public static PEPacket[] sendPlayerInventory(UpstreamSession session) { CachedWindow win = session.getWindowCache().getPlayerInventory(); // Translate and send InventoryContentPacket ret = new InventoryContentPacket(); - ret.windowId = PEWindowConstantID.PLAYER_INVENTORY.getId(); + ret.windowId = ContainerId.INVENTORY.getId(); ret.items = new Slot[40]; // hotbar for (int i = 36; i < 45; i++) { @@ -66,7 +66,7 @@ public static PEPacket[] sendPlayerInventory(UpstreamSession session) { public static void open(UpstreamSession session, ServerOpenWindowPacket win) { closeOpened(session, true); if (TRANSLATORS.containsKey(win.getType())) { - CachedWindow cached = new CachedWindow(win.getWindowId(), win.getType(), win.getSlots()); + CachedWindow cached = new CachedWindow(win.getWindowId(), win.getType(), win.getSlots() + 36/* player inventory */); session.getWindowCache().cacheWindow(cached); TRANSLATORS.get(win.getType()).open(session, cached); com.github.steveice10.packetlib.packet.Packet[] items = session.getWindowCache().getCachedPackets(win.getWindowId()); @@ -79,7 +79,6 @@ public static void open(UpstreamSession session, ServerOpenWindowPacket win) { } } } - System.out.println("Window " + win.getWindowId() + " opened !"); } else { // Not supported session.getDownstream().send(new ClientCloseWindowPacket(win.getWindowId())); @@ -90,7 +89,6 @@ public static void closeOpened(UpstreamSession session, boolean byServer) { if (session.getDataCache().containsKey(CacheKey.WINDOW_OPENED_ID)) { // There is already a window opened int id = (int) session.getDataCache().remove(CacheKey.WINDOW_OPENED_ID); - System.out.println("Window " + id + " closed !"); if (byServer) { session.sendPacket(new ContainerClosePacket(id), true); } else { @@ -150,7 +148,6 @@ public static void updateSlot(UpstreamSession session, ServerSetSlotPacket packe return; } CachedWindow win = session.getWindowCache().get(openedId); - System.out.println("WIN=" + win.slots.length + ", REQ_SLOT=" + packet.getSlot()); if (win.size <= packet.getSlot()) { session.getDownstream().send(new ClientCloseWindowPacket(packet.getWindowId())); return; diff --git a/src/main/java/org/dragonet/proxy/network/cache/CachedWindow.java b/src/main/java/org/dragonet/proxy/network/cache/CachedWindow.java index ebcca7db7..44bfbde70 100644 --- a/src/main/java/org/dragonet/proxy/network/cache/CachedWindow.java +++ b/src/main/java/org/dragonet/proxy/network/cache/CachedWindow.java @@ -20,27 +20,21 @@ import java.util.Map; public class CachedWindow { - // vars - public final int windowId; - /** - * The type of this window on remote side, -1 for player inventory. - */ - public final WindowType pcType; - public final int size; - public String title = "Window"; - public final Map properties = Collections.synchronizedMap(new HashMap()); - public ItemStack[] slots; - // constructor - public CachedWindow(int windowId, WindowType pcType, int size) { - this.windowId = windowId; - this.pcType = pcType; - this.size = size + 36; //add player inventory slots - slots = new ItemStack[this.size]; - } - - // public - - // private + public final int windowId; + /** + * The type of this window on remote side, -1 for player inventory. + */ + public final WindowType pcType; + public final int size; + public String title = "Window"; + public final Map properties = Collections.synchronizedMap(new HashMap()); + public ItemStack[] slots; + public CachedWindow(int windowId, WindowType pcType, int size) { + this.windowId = windowId; + this.pcType = pcType; + this.size = size; + slots = new ItemStack[this.size]; + } } diff --git a/src/main/java/org/dragonet/proxy/network/cache/WindowCache.java b/src/main/java/org/dragonet/proxy/network/cache/WindowCache.java index a3986dcc7..abbb41af9 100644 --- a/src/main/java/org/dragonet/proxy/network/cache/WindowCache.java +++ b/src/main/java/org/dragonet/proxy/network/cache/WindowCache.java @@ -19,71 +19,70 @@ import java.util.Map; import com.github.steveice10.packetlib.packet.Packet; +import java.util.concurrent.atomic.AtomicInteger; import org.dragonet.proxy.network.UpstreamSession; public final class WindowCache { - // vars - private final UpstreamSession upstream; - private final Map windows = Collections - .synchronizedMap(new HashMap()); - private final Map> cachedItems = Collections - .synchronizedMap(new HashMap>()); - // constructor - public WindowCache(UpstreamSession upstream) { - this.upstream = upstream; + private final UpstreamSession upstream; + private final Map windows = Collections + .synchronizedMap(new HashMap()); + private final Map> cachedItems = Collections + .synchronizedMap(new HashMap>()); + + public AtomicInteger currentTransactionId = new AtomicInteger(); - CachedWindow inv = new CachedWindow(0, null, 45); - windows.put(0, inv); - } + public WindowCache(UpstreamSession upstream) { + this.upstream = upstream; - // public - public UpstreamSession getUpstream() { - return upstream; - } + CachedWindow inv = new CachedWindow(0, null, 45); + windows.put(0, inv); + } - public CachedWindow getPlayerInventory() { - return windows.get(0); - } + // public + public UpstreamSession getUpstream() { + return upstream; + } - // We do not do translations here, do it in InventoryTranslatorRegister - public void cacheWindow(CachedWindow win) { - windows.put(win.windowId, win); - } + public CachedWindow getPlayerInventory() { + return windows.get(0); + } - public CachedWindow removeWindow(int id) { - return windows.remove(id); - } + // We do not do translations here, do it in InventoryTranslatorRegister + public void cacheWindow(CachedWindow win) { + windows.put(win.windowId, win); + } - public CachedWindow get(int id) { - return windows.get(id); - } + public CachedWindow removeWindow(int id) { + return windows.remove(id); + } - public boolean hasWindow(int id) { - return windows.containsKey(id); - } + public CachedWindow get(int id) { + return windows.get(id); + } - public void newCachedPacket(int windowId, Packet packet) { - List packets = null; - synchronized (cachedItems) { - packets = cachedItems.get(windowId); - if (packets == null) { - packets = new ArrayList<>(); - cachedItems.put(windowId, packets); - } - } - packets.add(packet); - } + public boolean hasWindow(int id) { + return windows.containsKey(id); + } - public Packet[] getCachedPackets(int windowId) { - List packets = null; - packets = cachedItems.remove(windowId); - if (packets == null) { - return null; - } - return packets.toArray(new Packet[0]); - } - - // private + public void newCachedPacket(int windowId, Packet packet) { + List packets = null; + synchronized (cachedItems) { + packets = cachedItems.get(windowId); + if (packets == null) { + packets = new ArrayList<>(); + cachedItems.put(windowId, packets); + } + } + packets.add(packet); + } + public Packet[] getCachedPackets(int windowId) { + List packets = null; + packets = cachedItems.remove(windowId); + if (packets == null) { + return null; + } + return packets.toArray(new Packet[0]); + } } diff --git a/src/main/java/org/dragonet/proxy/network/translator/ItemBlockTranslator.java b/src/main/java/org/dragonet/proxy/network/translator/ItemBlockTranslator.java index c67bad216..148c69b89 100644 --- a/src/main/java/org/dragonet/proxy/network/translator/ItemBlockTranslator.java +++ b/src/main/java/org/dragonet/proxy/network/translator/ItemBlockTranslator.java @@ -100,6 +100,7 @@ public class ItemBlockTranslator { swap(255, 252); //structure_block //ITEMS + toPEOverride(343, 342); //minecart_furnace (unavailable on PE) swap(416, 425); //armor_stand horsearmorleather toPCOverride(425, 417); //horsearmorleather horsearmoriron (unavailable on PC) @@ -111,7 +112,8 @@ public class ItemBlockTranslator { swap(447, new ItemEntry(333, 4)); //acacia_boat swap(448, new ItemEntry(333, 5)); //dark_oak_boat - swap(449, 450); //totem shulker_shell + swap(449, 450); //totem + swap(450, 445); //shulker_shell swap(2256, 500); //record_13 swap(2257, 501); //record_cat @@ -338,18 +340,8 @@ public static org.dragonet.proxy.data.nbt.tag.CompoundTag translateBlockEntityTo } public static ItemStack translateToPC(Slot slot) { - ItemStack item; - org.dragonet.proxy.data.nbt.tag.CompoundTag tag = slot.tag; - if (tag != null && tag.contains(DRAGONET_COMPOUND)) { - item = new ItemStack(tag.getCompound(DRAGONET_COMPOUND).getShort("id"), - tag.getCompound(DRAGONET_COMPOUND).getShort("amount"), - tag.getCompound(DRAGONET_COMPOUND).getShort("data")); - } else { - ItemEntry entry = translateToPC(slot.id, slot.damage); - item = new ItemStack(entry.id, slot.count, entry.damage != null ? entry.damage : slot.damage); - } - - return item; + ItemEntry entry = translateToPC(slot.id, slot.damage); + return new ItemStack(entry.id, slot.count, entry.damage != null ? entry.damage : slot.damage); //TODO NBT } public static BlockFace translateToPC(int face) { @@ -381,8 +373,8 @@ private static void toPEOverride(int fromPc, ItemEntry toPe) { PC_TO_PE_OVERRIDE.put(fromPc, toPe); } - private static void toPCOverride(int fromEc, int toPc) { - PE_TO_PC_OVERRIDE.put(fromEc, new ItemEntry(toPc)); + private static void toPCOverride(int fromPc, int toPc) { + PE_TO_PC_OVERRIDE.put(fromPc, new ItemEntry(toPc)); } private static void toPCOverride(int fromPc, ItemEntry toPe) { diff --git a/src/main/java/org/dragonet/proxy/network/translator/inv/ChestWindowTranslator.java b/src/main/java/org/dragonet/proxy/network/translator/inv/ChestWindowTranslator.java index 6d1828d70..fe8723ec0 100644 --- a/src/main/java/org/dragonet/proxy/network/translator/inv/ChestWindowTranslator.java +++ b/src/main/java/org/dragonet/proxy/network/translator/inv/ChestWindowTranslator.java @@ -12,7 +12,6 @@ */ package org.dragonet.proxy.network.translator.inv; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.dragonet.proxy.data.inventory.InventoryType; import org.dragonet.proxy.network.CacheKey; import org.dragonet.proxy.network.UpstreamSession; @@ -61,8 +60,6 @@ public void updateSlot(UpstreamSession session, CachedWindow win, int slotIndex) pk.slotId = slotIndex; pk.windowId = win.windowId; session.sendPacket(pk, true); - System.out.println("update window " + + win.windowId + " slot " + slotIndex); -// sendContent(session, window);// TOO LAZY LOL } private void sendContent(UpstreamSession session, CachedWindow win) { @@ -73,6 +70,5 @@ private void sendContent(UpstreamSession session, CachedWindow win) { pk.items[i] = ItemBlockTranslator.translateSlotToPE(win.slots[i]); } session.sendPacket(pk, true); - System.out.println("update window " + + win.windowId + " set all content"); } } diff --git a/src/main/java/org/dragonet/proxy/network/translator/pe/PEInventoryTransactionPacketTranslator.java b/src/main/java/org/dragonet/proxy/network/translator/pe/PEInventoryTransactionPacketTranslator.java index 8f7a5f696..5f5fee620 100644 --- a/src/main/java/org/dragonet/proxy/network/translator/pe/PEInventoryTransactionPacketTranslator.java +++ b/src/main/java/org/dragonet/proxy/network/translator/pe/PEInventoryTransactionPacketTranslator.java @@ -4,9 +4,11 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import com.github.steveice10.mc.protocol.data.game.entity.player.InteractAction; +import com.github.steveice10.mc.protocol.data.game.window.ClickItemParam; import com.github.steveice10.mc.protocol.data.game.window.DropItemParam; import com.github.steveice10.mc.protocol.data.game.window.WindowAction; import com.github.steveice10.mc.protocol.data.game.window.WindowActionParam; +import com.github.steveice10.mc.protocol.data.game.window.WindowType; import com.github.steveice10.mc.protocol.data.game.world.block.BlockFace; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerActionPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerInteractEntityPacket; @@ -17,13 +19,16 @@ import com.github.steveice10.packetlib.packet.Packet; import java.util.ArrayList; import java.util.List; + +import org.dragonet.proxy.data.inventory.ContainerId; import org.dragonet.proxy.network.CacheKey; import org.dragonet.proxy.network.UpstreamSession; import org.dragonet.proxy.network.cache.CachedEntity; +import org.dragonet.proxy.network.cache.CachedWindow; +import org.dragonet.proxy.network.cache.WindowCache; import org.dragonet.proxy.network.translator.IPEPacketTranslator; import org.dragonet.proxy.network.translator.ItemBlockTranslator; import org.dragonet.proxy.protocol.packets.InventoryTransactionPacket; -import static org.dragonet.proxy.protocol.packets.InventoryTransactionPacket.*; import org.dragonet.proxy.protocol.type.InventoryTransactionAction; import org.dragonet.proxy.protocol.type.Slot; import org.dragonet.proxy.protocol.type.transaction.data.ReleaseItemData; @@ -42,31 +47,77 @@ public class PEInventoryTransactionPacketTranslator implements IPEPacketTranslat @Override public Packet[] translate(UpstreamSession session, InventoryTransactionPacket packet) { //debug -// System.out.println("InventoryTransactionPacket type : " + DebugTools.getAllFields(packet)); -// for(InventoryTransactionAction action : packet.actions) { -// System.out.println(DebugTools.getAllFields(action)); +// if (packet.transactionType == InventoryTransactionPacket.TYPE_NORMAL) { +// System.out.println(">>>>============================"); +//// System.out.println("InventoryTransactionPacket type: \n" + DebugTools.getAllFields(packet)); +//// System.out.println("-------------"); +// for (InventoryTransactionAction action : packet.actions) { +// System.out.println(DebugTools.getAllFields(action)); +// } +// System.out.println("<<<<============================"); // } + // /!\ THIS IS A SIMPLE HANDLING WITHOUT JAVA DENY TRANSACTION switch (packet.transactionType) { - case TYPE_NORMAL: //0 + case InventoryTransactionPacket.TYPE_NORMAL: //0 INVENTORY & CHEST System.out.println("TYPE_NORMAL"); - List packets = new ArrayList(); + Slot cursor = null; + if (packet.actions.length <= 2 && packet.actions[0].sourceType == InventoryTransactionAction.SOURCE_WORLD && packet.actions[1].containerId == ContainerId.INVENTORY.getId()) //main inventory + { + // drop item + ClientPlayerActionPacket act = new ClientPlayerActionPacket( + com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction.DROP_ITEM, + new Position(0, 0, 0), + BlockFace.DOWN); + return new Packet[]{act}; + } + if (packet.actions.length == 2 && packet.actions[0].sourceType == InventoryTransactionAction.SOURCE_CONTAINER && packet.actions[1].containerId == ContainerId.CURSOR.getId()) { + // desktop version: click on an item (maybe pick/place/merge/swap) - for (InventoryTransactionAction action : packet.actions) { - if (action.sourceType == InventoryTransactionAction.SOURCE_WORLD) //main inventory - { - ClientPlayerActionPacket act = new ClientPlayerActionPacket( - com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction.DROP_ITEM, - new Position(0, 0, 0), - BlockFace.DOWN); - packets.add(act); + cursor = packet.actions[1].newItem; //set the cursor + int container = packet.actions[0].containerId; + int slot = packet.actions[0].slotId; + if (container == 0) { // if 0, source is player inv + if (slot > 5 && slot <= 9) { + System.out.println("interact in player inventory (stuff)"); + } + if (slot > 9 && slot <= 36) { + System.out.println("interact in player inventory (inventory)"); + } + if (slot > 36 && slot <= 45) { + System.out.println("interact in player inventory (hotbar)"); + } + container = (int) session.getDataCache().get(CacheKey.WINDOW_OPENED_ID); + slot += 18; //normal chest 0 -> 26 + inv 27 -> 62 } + System.out.println("interact in chest (" + container + ") slot " + slot); + + // send action to server + ClientWindowActionPacket windowActionPacket = new ClientWindowActionPacket( + container, //window id + session.getWindowCache().currentTransactionId.incrementAndGet(), //transaction id + slot, //slot + ItemBlockTranslator.translateToPC(cursor), + WindowAction.CLICK_ITEM, + (WindowActionParam) ClickItemParam.LEFT_CLICK + ); + session.getDownstream().send(windowActionPacket); + + // after the previous one, we can detect SHIFT click or move items on mobile devices + if (packet.actions.length == 2 && packet.actions[0].sourceType == InventoryTransactionAction.SOURCE_CONTAINER && packet.actions[1].sourceType == InventoryTransactionAction.SOURCE_CONTAINER) { + // mobile version: move item + // desktop version: SHIFT-click item + System.out.println("Move item from " + packet.actions[0].containerId + " slot " + packet.actions[0].slotId + + " to " + packet.actions[1].containerId + " slot " + packet.actions[1].slotId); + } + + System.out.println("Cursor set to " + cursor); } - return packets.toArray(new Packet[]{}); - case TYPE_MISMATCH: //1 + return null; // it's okay to return null + case InventoryTransactionPacket.TYPE_MISMATCH: //1 System.out.println("TYPE_MISMATCH"); break; - case TYPE_USE_ITEM: //2 + case InventoryTransactionPacket.TYPE_USE_ITEM: //2 System.out.println("TYPE_USE_ITEM"); UseItemData useItemData = (UseItemData) packet.transactionData; if (useItemData.blockPos.equals(new BlockPosition(0, 0, 0))) { @@ -97,7 +148,7 @@ public Packet[] translate(UpstreamSession session, InventoryTransactionPacket pa } } - case TYPE_USE_ITEM_ON_ENTITY: //3 + case InventoryTransactionPacket.TYPE_USE_ITEM_ON_ENTITY: //3 System.out.println("TYPE_USE_ITEM_ON_ENTITY"); UseItemOnEntityData useItemOnEntityData = (UseItemOnEntityData) packet.transactionData; CachedEntity cachedEntity = session.getEntityCache().getByLocalEID(useItemOnEntityData.entityRuntimeId); @@ -113,7 +164,7 @@ public Packet[] translate(UpstreamSession session, InventoryTransactionPacket pa interractAction ); return new Packet[]{interractPacket}; - case TYPE_RELEASE_ITEM: //4 + case InventoryTransactionPacket.TYPE_RELEASE_ITEM: //4 System.out.println("TYPE_RELEASE_ITEM"); ReleaseItemData releaseItemData = (ReleaseItemData) packet.transactionData; // ClientPlayerActionPacket act = new ClientPlayerActionPacket( diff --git a/src/main/java/org/dragonet/proxy/protocol/type/Slot.java b/src/main/java/org/dragonet/proxy/protocol/type/Slot.java index 48b0520d4..5d3f66410 100644 --- a/src/main/java/org/dragonet/proxy/protocol/type/Slot.java +++ b/src/main/java/org/dragonet/proxy/protocol/type/Slot.java @@ -42,4 +42,16 @@ public Slot(int id, int damage, int count, CompoundTag tag) { public Slot clone() { return new Slot(id, damage, count, tag); } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + buffer.append("Slot{"); + buffer.append("id=" + id); + buffer.append(", damage=" + damage); + buffer.append(", count=" + count); + buffer.append(", tag=" + tag); + buffer.append("}"); + return buffer.toString(); + } }