From 3067c7274665fdd9d511e04dd94e05bd8cfea196 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Sat, 19 Oct 2019 23:54:30 -0800 Subject: [PATCH 001/109] Use chunk cache and fix ChunkPosition getChunkBlock() in ChunkPosition returned incorrect values when negative numbers were inputted. ChunkPosition did not function correctly when used as a key for maps because it did not override equals() and hashCode() --- .../player/JavaPlayerActionAckTranslator.java | 1 + .../java/world/JavaBlockChangeTranslator.java | 4 ++- .../java/world/JavaChunkDataTranslator.java | 1 + .../world/JavaMultiBlockChangeTranslator.java | 1 + .../connector/world/chunk/ChunkPosition.java | 32 +++++++++++++------ 5 files changed, 28 insertions(+), 11 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java index 3213a2fd..cf5c26bc 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java @@ -40,6 +40,7 @@ public class JavaPlayerActionAckTranslator extends PacketTranslator { @Override public void translate(ServerBlockChangePacket packet, GeyserSession session) { - UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); BlockChangeRecord record = packet.getRecord(); + session.getChunkCache().updateBlock(record.getPosition(), record.getBlock()); + UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); updateBlockPacket.setDataLayer(0); updateBlockPacket.setBlockPosition(Vector3i.from( record.getPosition().getX(), diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java index a620197e..2082157e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java @@ -18,6 +18,7 @@ public class JavaChunkDataTranslator extends PacketTranslator { Vector2i chunkPos = session.getLastChunkPosition(); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaMultiBlockChangeTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaMultiBlockChangeTranslator.java index 14864b8c..b78e366c 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaMultiBlockChangeTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaMultiBlockChangeTranslator.java @@ -40,6 +40,7 @@ public class JavaMultiBlockChangeTranslator extends PacketTranslator Date: Sun, 20 Oct 2019 13:25:41 -0800 Subject: [PATCH 002/109] Work on inventory transactions work in progress --- .../connector/inventory/Inventory.java | 27 +- .../connector/inventory/PlayerInventory.java | 14 +- .../network/session/GeyserSession.java | 8 + .../network/session/cache/InventoryCache.java | 12 - .../network/translators/TranslatorsInit.java | 46 ++-- .../BedrockContainerCloseTranslator.java | 56 ++++ ...BedrockInventoryTransactionTranslator.java | 254 +++++++++++++++++- .../inventory/ChestInventoryTranslator.java | 163 +++++++++++ .../DispenserInventoryTranslator.java | 87 ++++++ .../inventory/FurnaceInventoryTranslator.java | 108 ++++++++ .../inventory/GenericInventoryTranslator.java | 74 ----- .../inventory/HopperInventoryTranslator.java | 87 ++++++ .../inventory/InventoryTranslator.java | 62 ++++- .../inventory/PlayerInventoryTranslator.java | 138 ++++++++++ .../translators/item/ItemTranslator.java | 3 +- .../inventory/OpenWindowPacketTranslator.java | 22 -- .../window/JavaCloseWindowTranslator.java | 43 +++ .../JavaConfirmTransactionTranslator.java | 46 ++++ .../java/window/JavaSetSlotTranslator.java | 61 +++-- .../window/JavaWindowItemsTranslator.java | 20 +- .../window/JavaWindowPropertyTranslator.java | 24 ++ .../connector/utils/InventoryUtils.java | 128 +++------ 22 files changed, 1214 insertions(+), 269 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockContainerCloseTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/ChestInventoryTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/DispenserInventoryTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java delete mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/GenericInventoryTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/HopperInventoryTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java delete mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/java/inventory/OpenWindowPacketTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaCloseWindowTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaConfirmTransactionTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaWindowPropertyTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java b/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java index 801f670c..215ac597 100644 --- a/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java +++ b/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java @@ -27,6 +27,7 @@ package org.geysermc.connector.inventory; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.mc.protocol.data.game.window.WindowType; +import com.nukkitx.math.vector.Vector3i; import lombok.Getter; import lombok.Setter; @@ -42,9 +43,6 @@ public class Inventory { @Getter protected WindowType windowType; - @Getter - protected int size; - @Getter @Setter protected String title; @@ -53,20 +51,31 @@ public class Inventory { @Setter protected ItemStack[] items; - public Inventory(int id, WindowType windowType, int size) { - this("Inventory", id, windowType, size); + @Getter + @Setter + protected Vector3i holderPosition = Vector3i.ZERO; + + @Getter + @Setter + protected long holderId = -1; + + protected short transactionId = 1; + + public Inventory(int id, WindowType windowType) { + this("Inventory", id, windowType); } - public Inventory(String title, int id, WindowType windowType, int size) { + public Inventory(String title, int id, WindowType windowType) { this.title = title; this.id = id; this.windowType = windowType; - this.size = size; - - this.items = new ItemStack[size]; } public ItemStack getItem(int slot) { return items[slot]; } + + public short getNextTransactionId() { + return transactionId++; + } } diff --git a/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java b/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java index 424570b9..44ad3cb6 100644 --- a/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java +++ b/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java @@ -35,12 +35,22 @@ public class PlayerInventory extends Inventory { @Setter private int heldItemSlot; - public PlayerInventory() { - super(0, null, 45); + @Getter + private ItemStack cursor; + public PlayerInventory() { + super(0, null); + + items = new ItemStack[45]; heldItemSlot = 0; } + public void setCursor(ItemStack stack) { + if (stack != null && stack.getId() == 0) + stack = null; + cursor = stack; + } + public ItemStack getItemInHand() { return items[heldItemSlot]; } diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index a4f57c08..9bce0e7c 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -99,6 +99,14 @@ public class GeyserSession implements Player { @Setter private BlockFace blockDiggingFace = BlockFace.DOWN; + @Getter + @Setter + private int lastClickedSlot; + + @Getter + @Setter + private int reopeningWindow = -1; + public GeyserSession(GeyserConnector connector, BedrockServerSession bedrockServerSession) { this.connector = connector; this.upstream = new UpstreamSession(bedrockServerSession); diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/InventoryCache.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/InventoryCache.java index 4eea1de2..9277ce5d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/cache/InventoryCache.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/InventoryCache.java @@ -25,15 +25,12 @@ package org.geysermc.connector.network.session.cache; -import com.github.steveice10.packetlib.packet.Packet; import lombok.Getter; import lombok.Setter; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; public class InventoryCache { @@ -47,9 +44,6 @@ public class InventoryCache { @Getter private Map inventories = new HashMap(); - @Getter - private Map> cachedPackets = new HashMap>(); - public InventoryCache(GeyserSession session) { this.session = session; } @@ -65,10 +59,4 @@ public class InventoryCache { public void uncacheInventory(int id) { inventories.remove(id); } - - public void cachePacket(int id, Packet packet) { - List packets = cachedPackets.getOrDefault(id, new ArrayList()); - packets.add(packet); - cachedPackets.put(id, packets); - } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java index d4bc5b45..74c50dbf 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java @@ -25,6 +25,7 @@ package org.geysermc.connector.network.translators; +import com.github.steveice10.mc.protocol.data.game.window.WindowType; import com.github.steveice10.mc.protocol.packet.ingame.server.*; import com.github.steveice10.mc.protocol.packet.ingame.server.entity.*; import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerActionAckPacket; @@ -36,9 +37,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.server.scoreboard.ServerD import com.github.steveice10.mc.protocol.packet.ingame.server.scoreboard.ServerScoreboardObjectivePacket; import com.github.steveice10.mc.protocol.packet.ingame.server.scoreboard.ServerTeamPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.scoreboard.ServerUpdateScorePacket; -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 com.github.steveice10.mc.protocol.packet.ingame.server.window.*; import com.github.steveice10.mc.protocol.packet.ingame.server.world.*; import com.nukkitx.nbt.CompoundTagBuilder; import com.nukkitx.nbt.NbtUtils; @@ -48,25 +47,23 @@ import com.nukkitx.protocol.bedrock.packet.*; import lombok.Getter; import org.geysermc.connector.network.translators.bedrock.*; import org.geysermc.connector.network.translators.block.BlockTranslator; -import org.geysermc.connector.network.translators.inventory.GenericInventoryTranslator; -import org.geysermc.connector.network.translators.inventory.InventoryTranslator; +import org.geysermc.connector.network.translators.inventory.*; import org.geysermc.connector.network.translators.item.ItemTranslator; import org.geysermc.connector.network.translators.java.*; import org.geysermc.connector.network.translators.java.entity.*; import org.geysermc.connector.network.translators.java.entity.player.*; import org.geysermc.connector.network.translators.java.entity.spawn.*; -import org.geysermc.connector.network.translators.java.inventory.OpenWindowPacketTranslator; import org.geysermc.connector.network.translators.java.scoreboard.JavaDisplayScoreboardTranslator; import org.geysermc.connector.network.translators.java.scoreboard.JavaScoreboardObjectiveTranslator; import org.geysermc.connector.network.translators.java.scoreboard.JavaTeamTranslator; import org.geysermc.connector.network.translators.java.scoreboard.JavaUpdateScoreTranslator; -import org.geysermc.connector.network.translators.java.window.JavaOpenWindowTranslator; -import org.geysermc.connector.network.translators.java.window.JavaSetSlotTranslator; -import org.geysermc.connector.network.translators.java.window.JavaWindowItemsTranslator; +import org.geysermc.connector.network.translators.java.window.*; import org.geysermc.connector.network.translators.java.world.*; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.util.HashMap; +import java.util.Map; public class TranslatorsInit { @@ -77,7 +74,7 @@ public class TranslatorsInit { private static BlockTranslator blockTranslator; @Getter - private static InventoryTranslator inventoryTranslator = new GenericInventoryTranslator(); + private static Map inventoryTranslators = new HashMap(); private static final CompoundTag EMPTY_TAG = CompoundTagBuilder.builder().buildRootTag(); public static final byte[] EMPTY_LEVEL_CHUNK_DATA; @@ -132,9 +129,6 @@ public class TranslatorsInit { Registry.registerJava(ServerNotifyClientPacket.class, new JavaNotifyClientTranslator()); Registry.registerJava(ServerChunkDataPacket.class, new JavaChunkDataTranslator()); Registry.registerJava(ServerEntityDestroyPacket.class, new JavaEntityDestroyTranslator()); - Registry.registerJava(ServerWindowItemsPacket.class, new JavaWindowItemsTranslator()); - Registry.registerJava(ServerOpenWindowPacket.class, new JavaOpenWindowTranslator()); - Registry.registerJava(ServerSetSlotPacket.class, new JavaSetSlotTranslator()); Registry.registerJava(ServerScoreboardObjectivePacket.class, new JavaScoreboardObjectiveTranslator()); Registry.registerJava(ServerDisplayScoreboardPacket.class, new JavaDisplayScoreboardTranslator()); Registry.registerJava(ServerUpdateScorePacket.class, new JavaUpdateScoreTranslator()); @@ -142,7 +136,12 @@ public class TranslatorsInit { Registry.registerJava(ServerBlockChangePacket.class, new JavaBlockChangeTranslator()); Registry.registerJava(ServerMultiBlockChangePacket.class, new JavaMultiBlockChangeTranslator()); - Registry.registerJava(ServerOpenWindowPacket.class, new OpenWindowPacketTranslator()); + Registry.registerJava(ServerWindowItemsPacket.class, new JavaWindowItemsTranslator()); + Registry.registerJava(ServerOpenWindowPacket.class, new JavaOpenWindowTranslator()); + Registry.registerJava(ServerSetSlotPacket.class, new JavaSetSlotTranslator()); + Registry.registerJava(ServerCloseWindowPacket.class, new JavaCloseWindowTranslator()); + Registry.registerJava(ServerConfirmTransactionPacket.class, new JavaConfirmTransactionTranslator()); + Registry.registerJava(ServerWindowPropertyPacket.class, new JavaWindowPropertyTranslator()); Registry.registerBedrock(AnimatePacket.class, new BedrockAnimateTranslator()); Registry.registerBedrock(CommandRequestPacket.class, new BedrockCommandRequestTranslator()); @@ -153,6 +152,7 @@ public class TranslatorsInit { Registry.registerBedrock(SetLocalPlayerAsInitializedPacket.class, new BedrockPlayerInitializedTranslator()); Registry.registerBedrock(InteractPacket.class, new BedrockInteractTranslator()); Registry.registerBedrock(TextPacket.class, new BedrockTextTranslator()); + Registry.registerBedrock(ContainerClosePacket.class, new BedrockContainerCloseTranslator()); itemTranslator = new ItemTranslator(); blockTranslator = new BlockTranslator(); @@ -161,11 +161,17 @@ public class TranslatorsInit { } private static void registerInventoryTranslators() { - /*inventoryTranslators.put(WindowType.GENERIC_9X1, new GenericInventoryTranslator()); - inventoryTranslators.put(WindowType.GENERIC_9X2, new GenericInventoryTranslator()); - inventoryTranslators.put(WindowType.GENERIC_9X3, new GenericInventoryTranslator()); - inventoryTranslators.put(WindowType.GENERIC_9X4, new GenericInventoryTranslator()); - inventoryTranslators.put(WindowType.GENERIC_9X5, new GenericInventoryTranslator()); - inventoryTranslators.put(WindowType.GENERIC_9X6, new GenericInventoryTranslator());*/ + inventoryTranslators.put(null, new PlayerInventoryTranslator()); //player inventory + inventoryTranslators.put(WindowType.GENERIC_9X1, new ChestInventoryTranslator(9)); + inventoryTranslators.put(WindowType.GENERIC_9X2, new ChestInventoryTranslator(18)); + inventoryTranslators.put(WindowType.GENERIC_9X3, new ChestInventoryTranslator(27)); + inventoryTranslators.put(WindowType.GENERIC_9X4, new ChestInventoryTranslator(36)); + inventoryTranslators.put(WindowType.GENERIC_9X5, new ChestInventoryTranslator(45)); + inventoryTranslators.put(WindowType.GENERIC_9X6, new ChestInventoryTranslator(54)); + inventoryTranslators.put(WindowType.GENERIC_3X3, new DispenserInventoryTranslator()); + inventoryTranslators.put(WindowType.HOPPER, new HopperInventoryTranslator()); + inventoryTranslators.put(WindowType.FURNACE, new FurnaceInventoryTranslator()); + inventoryTranslators.put(WindowType.BLAST_FURNACE, new FurnaceInventoryTranslator()); + inventoryTranslators.put(WindowType.SMOKER, new FurnaceInventoryTranslator()); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockContainerCloseTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockContainerCloseTranslator.java new file mode 100644 index 00000000..de6a9d8c --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockContainerCloseTranslator.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.bedrock; + +import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientCloseWindowPacket; +import com.nukkitx.protocol.bedrock.packet.ContainerClosePacket; +import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.inventory.InventoryTranslator; +import org.geysermc.connector.utils.InventoryUtils; + +public class BedrockContainerCloseTranslator extends PacketTranslator { + + @Override + public void translate(ContainerClosePacket packet, GeyserSession session) { + byte windowId = packet.getWindowId() == -1 ? 0 : packet.getWindowId(); //player inventory + if (session.getReopeningWindow() != -1) { + Inventory inventory = session.getInventoryCache().getInventories().get(session.getReopeningWindow()); + session.setReopeningWindow(-1); + if (inventory != null) { + InventoryTranslator translator = TranslatorsInit.getInventoryTranslators().get(inventory.getWindowType()); + translator.openInventory(session, inventory); + translator.updateInventory(session, inventory); + return; + } + } + ClientCloseWindowPacket closeWindowPacket = new ClientCloseWindowPacket(windowId); + session.getDownstream().getSession().send(closeWindowPacket); + InventoryUtils.closeInventory(session, windowId); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java index 1e6b44a9..e3301604 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java @@ -25,6 +25,10 @@ package org.geysermc.connector.network.translators.bedrock; +import com.github.steveice10.mc.protocol.data.game.window.*; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.nukkitx.math.vector.Vector3f; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; 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; @@ -33,18 +37,266 @@ 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; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerUseItemPacket; -import com.nukkitx.math.vector.Vector3f; +import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientWindowActionPacket; +import com.nukkitx.protocol.bedrock.data.ContainerId; +import com.nukkitx.protocol.bedrock.data.InventoryAction; +import com.nukkitx.protocol.bedrock.data.InventorySource; +import com.nukkitx.protocol.bedrock.data.ItemData; +import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import com.nukkitx.protocol.bedrock.packet.InventoryTransactionPacket; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.PlayerEntity; +import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.inventory.InventoryTranslator; +import org.geysermc.connector.utils.InventoryUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; public class BedrockInventoryTransactionTranslator extends PacketTranslator { @Override public void translate(InventoryTransactionPacket packet, GeyserSession session) { switch (packet.getTransactionType()) { + case NORMAL: + Inventory inventory = session.getInventoryCache().getOpenInventory(); + if (inventory == null) + inventory = session.getInventory(); + InventoryTranslator translator; + translator = TranslatorsInit.getInventoryTranslators().get(inventory.getWindowType()); + //find the world interaction and/or cursor action if present + InventoryAction worldAction = null; + InventoryAction cursorAction = null; + for (InventoryAction action : packet.getActions()) { + if (action.getSource().getType() == InventorySource.Type.WORLD_INTERACTION) { + if (worldAction == null) { + worldAction = action; + } else { + return; + } + } else if (action.getSource().getContainerId() == ContainerId.CURSOR) { + if (cursorAction == null) { + cursorAction = action; + } else { + return; + } + } + } + if (packet.getActions().size() == 2) { + if (worldAction != null && worldAction.getSource().getFlag() == InventorySource.Flag.DROP_ITEM) { + //find container action + InventoryAction containerAction = null; + for (InventoryAction action : packet.getActions()) { + if (action.getSource().getType() == InventorySource.Type.CONTAINER || action.getSource().getType() == InventorySource.Type.UNTRACKED_INTERACTION_UI) { + containerAction = action; + break; + } + } + if (containerAction != null) { + //quick dropping from hotbar? + if (session.getInventoryCache().getOpenInventory() == null && containerAction.getSource().getContainerId() == ContainerId.INVENTORY) { + if (containerAction.getSlot() == session.getInventory().getHeldItemSlot()) { + ClientPlayerActionPacket actionPacket = new ClientPlayerActionPacket( + containerAction.getToItem().getCount() == 0 ? PlayerAction.DROP_ITEM_STACK : PlayerAction.DROP_ITEM, + new Position(0, 0, 0), BlockFace.DOWN); + session.getDownstream().getSession().send(actionPacket); + return; + } + } + boolean leftClick = containerAction.getToItem().getCount() == 0; + if (containerAction.getSource().getContainerId() != ContainerId.CURSOR) { //dropping directly from inventory + int javaSlot = translator.bedrockSlotToJava(containerAction); + ClientWindowActionPacket dropPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getNextTransactionId(), + javaSlot, null, WindowAction.DROP_ITEM, + leftClick ? DropItemParam.DROP_SELECTED_STACK : DropItemParam.DROP_FROM_SELECTED); + session.getDownstream().getSession().send(dropPacket); + return; + } else { //clicking outside of inventory + ClientWindowActionPacket dropPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getNextTransactionId(), + -999, null, WindowAction.CLICK_ITEM, + leftClick ? ClickItemParam.LEFT_CLICK : ClickItemParam.RIGHT_CLICK); + session.getDownstream().getSession().send(dropPacket); + return; + } + } + } else if (cursorAction != null) { + //find container action + InventoryAction containerAction = null; + for (InventoryAction action : packet.getActions()) { + if (action != cursorAction && (action.getSource().getType() == InventorySource.Type.CONTAINER || action.getSource().getType() == InventorySource.Type.UNTRACKED_INTERACTION_UI)) { + containerAction = action; + break; + } + } + if (containerAction != null) { + if (InventoryUtils.canCombine(cursorAction.getFromItem(), cursorAction.getToItem()) + && cursorAction.getToItem().getCount() > cursorAction.getFromItem().getCount()) { //fill stack + int javaSlot = session.getLastClickedSlot(); + ClientWindowActionPacket fillStackPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getNextTransactionId(), + javaSlot, null, WindowAction.FILL_STACK, FillStackParam.FILL); + session.getDownstream().getSession().send(fillStackPacket); + translator.updateInventory(session, inventory); //bedrock fill stack can sometimes differ from java version, refresh and let server change slots + System.out.println(fillStackPacket); + return; + } else { + //left/right click + int javaSlot = translator.bedrockSlotToJava(containerAction); + boolean rightClick; + if (cursorAction.getFromItem().getCount() == 0) { //picking up item + rightClick = containerAction.getToItem().getCount() != 0; + } else { //releasing item + rightClick = cursorAction.getToItem().getCount() != 0 && cursorAction.getFromItem().getCount() - cursorAction.getToItem().getCount() == 1; + } + ItemStack translatedCursor = TranslatorsInit.getItemTranslator().translateToJava(cursorAction.getFromItem()); + boolean refresh = !Objects.equals(session.getInventory().getCursor(), translatedCursor.getId() == 0 ? null : translatedCursor); //refresh slot if there is a cursor mismatch + ClientWindowActionPacket clickPacket = new ClientWindowActionPacket(inventory.getId(), + inventory.getNextTransactionId(), javaSlot, + refresh ? new ItemStack(1, 127, new CompoundTag("")) : InventoryUtils.fixNbt(TranslatorsInit.getItemTranslator().translateToJava(containerAction.getFromItem())), //send invalid item stack to refresh slot + WindowAction.CLICK_ITEM, rightClick ? ClickItemParam.RIGHT_CLICK : ClickItemParam.LEFT_CLICK); + System.out.println(clickPacket); + session.getDownstream().getSession().send(clickPacket); + inventory.getItems()[javaSlot] = TranslatorsInit.getItemTranslator().translateToJava(containerAction.getToItem()); + translator.updateSlot(session, inventory, javaSlot); + session.getInventory().setCursor(TranslatorsInit.getItemTranslator().translateToJava(cursorAction.getToItem())); + session.setLastClickedSlot(javaSlot); + return; + } + } + } else if (packet.getActions().stream().allMatch(p -> p.getSource().getType() == InventorySource.Type.CONTAINER || p.getSource().getType() == InventorySource.Type.UNTRACKED_INTERACTION_UI)) { + //either moving 1 item or swapping 2 slots (touchscreen or one slot shift click) + InventoryAction fromAction; + InventoryAction toAction; + //find source slot + if (packet.getActions().get(0).getFromItem().getCount() > packet.getActions().get(0).getToItem().getCount()) { + fromAction = packet.getActions().get(0); + toAction = packet.getActions().get(1); + } else { + fromAction = packet.getActions().get(1); + toAction = packet.getActions().get(0); + } + int fromSlot = translator.bedrockSlotToJava(fromAction); + int toSlot = translator.bedrockSlotToJava(toAction); + + //check if dealing with output only slot like furnace. this is to handle a situation where the output slot was partially emptied without right clicking (touchscreen or full inventory) + //this is only possible by shift clicking + if (translator.isOutputSlot(fromAction) && fromAction.getToItem().getCount() != 0) { + ClientWindowActionPacket shiftClickPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getNextTransactionId(), + fromSlot, InventoryUtils.fixNbt(inventory.getItem(fromSlot)), WindowAction.SHIFT_CLICK_ITEM, ShiftClickItemParam.LEFT_CLICK); + session.getDownstream().getSession().send(shiftClickPacket); + inventory.getItems()[toSlot] = TranslatorsInit.getItemTranslator().translateToJava(toAction.getToItem()); + inventory.getItems()[fromSlot] = TranslatorsInit.getItemTranslator().translateToJava(fromAction.getToItem()); + return; + } else { + //pickup fromAction item + ClientWindowActionPacket leftClick1Packet = new ClientWindowActionPacket(inventory.getId(), inventory.getNextTransactionId(), + fromSlot, InventoryUtils.fixNbt(TranslatorsInit.getItemTranslator().translateToJava(fromAction.getFromItem())), WindowAction.CLICK_ITEM, + ClickItemParam.LEFT_CLICK); + session.getDownstream().getSession().send(leftClick1Packet); + System.out.println(leftClick1Packet); + //release fromAction item into toAction slot + ClientWindowActionPacket leftClick2Packet = new ClientWindowActionPacket(inventory.getId(), inventory.getNextTransactionId(), + toSlot, InventoryUtils.fixNbt(TranslatorsInit.getItemTranslator().translateToJava(toAction.getFromItem())), WindowAction.CLICK_ITEM, + ClickItemParam.LEFT_CLICK); + session.getDownstream().getSession().send(leftClick2Packet); + System.out.println(leftClick2Packet); + //test if swapping two items or moving one item + //if swapping then complete it + if (fromAction.getToItem().getId() != 0) { + ClientWindowActionPacket leftClick3Packet = new ClientWindowActionPacket(inventory.getId(), inventory.getNextTransactionId(), + fromSlot, null, WindowAction.CLICK_ITEM, + ClickItemParam.LEFT_CLICK); + session.getDownstream().getSession().send(leftClick3Packet); + } + inventory.getItems()[toSlot] = TranslatorsInit.getItemTranslator().translateToJava(toAction.getToItem()); + inventory.getItems()[fromSlot] = TranslatorsInit.getItemTranslator().translateToJava(fromAction.getToItem()); + return; + } + } + } else if (packet.getActions().size() > 2) { + //shift click or fill stack? + ItemData firstItem; + if (packet.getActions().get(0).getFromItem().getId() != 0) { + firstItem = packet.getActions().get(0).getFromItem(); + } else { + firstItem = packet.getActions().get(0).getToItem(); + } + List sourceActions = new ArrayList<>(packet.getActions().size()); + List destActions = new ArrayList<>(packet.getActions().size()); + boolean sameItems = true; + for (InventoryAction action : packet.getActions()) { + if (action.getFromItem().getCount() > action.getToItem().getCount()) { + if (!InventoryUtils.canCombine(action.getFromItem(), firstItem)) + sameItems = false; + sourceActions.add(action); + } else { + if (!InventoryUtils.canCombine(action.getToItem(), firstItem)) + sameItems = false; + destActions.add(action); + } + } + if (sameItems) { + if (sourceActions.size() == 1) { //shift click + InventoryAction sourceAction = sourceActions.get(0); + //in java edition, shift clicked item must move across hotbar and main inventory + if (sourceAction.getSource().getContainerId() == ContainerId.INVENTORY) { + for (InventoryAction action : packet.getActions()) { + if (action != sourceAction && action.getSource().getContainerId() == ContainerId.INVENTORY) { + if ((sourceAction.getSlot() < 9 && action.getSlot() < 9) || (sourceAction.getSlot() >= 9 && action.getSlot() >= 9)) { + //shift click not compatible with java edition. refresh inventory and abort + translator.updateInventory(session, inventory); + return; + } + } + } + } + int javaSlot = translator.bedrockSlotToJava(sourceAction); + ClientWindowActionPacket shiftClickPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getNextTransactionId(), + javaSlot, InventoryUtils.fixNbt(inventory.getItem(javaSlot)), WindowAction.SHIFT_CLICK_ITEM, ShiftClickItemParam.LEFT_CLICK); + session.getDownstream().getSession().send(shiftClickPacket); + return; + } else if (destActions.size() == 1) { //fill stack + InventoryAction destAction = destActions.get(0); + int javaSlot; + if (destAction != cursorAction) { //if touchscreen + javaSlot = translator.bedrockSlotToJava(destAction); + ClientWindowActionPacket leftClickPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getNextTransactionId(), + javaSlot, InventoryUtils.fixNbt(inventory.getItem(javaSlot)), WindowAction.CLICK_ITEM, ClickItemParam.LEFT_CLICK); + session.getDownstream().getSession().send(leftClickPacket); + } else { + javaSlot = session.getLastClickedSlot(); + } + ClientWindowActionPacket fillStackPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getNextTransactionId(), + javaSlot, null, WindowAction.FILL_STACK, FillStackParam.FILL); + session.getDownstream().getSession().send(fillStackPacket); + if (destAction != cursorAction) { //if touchscreen + ClientWindowActionPacket leftClickPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getNextTransactionId(), + javaSlot, null, WindowAction.CLICK_ITEM, ClickItemParam.LEFT_CLICK); + session.getDownstream().getSession().send(leftClickPacket); + inventory.getItems()[javaSlot] = TranslatorsInit.getItemTranslator().translateToJava(destAction.getToItem()); + } + translator.updateInventory(session, inventory); + return; + } + } + } + + //refresh inventory, transaction was not translated + translator.updateInventory(session, inventory); + break; + case INVENTORY_MISMATCH: + InventorySlotPacket cursorPacket = new InventorySlotPacket(); + cursorPacket.setContainerId(ContainerId.CURSOR); + cursorPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(session.getInventory().getCursor())); + session.getUpstream().sendPacket(cursorPacket); + + Inventory inv = session.getInventoryCache().getOpenInventory(); + if (inv == null) + inv = session.getInventory(); + TranslatorsInit.getInventoryTranslators().get(inv.getWindowType()).updateInventory(session, inv); case ITEM_USE: if (packet.getActionType() == 1) { ClientPlayerUseItemPacket useItemPacket = new ClientPlayerUseItemPacket(Hand.MAIN_HAND); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/ChestInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/ChestInventoryTranslator.java new file mode 100644 index 00000000..bd2aa581 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/ChestInventoryTranslator.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.inventory; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; +import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.nbt.tag.CompoundTag; +import com.nukkitx.protocol.bedrock.data.ContainerId; +import com.nukkitx.protocol.bedrock.data.ContainerType; +import com.nukkitx.protocol.bedrock.data.InventoryAction; +import com.nukkitx.protocol.bedrock.data.ItemData; +import com.nukkitx.protocol.bedrock.packet.*; +import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.block.BlockEntry; +import org.geysermc.connector.world.GlobalBlockPalette; + +public class ChestInventoryTranslator extends InventoryTranslator { + public ChestInventoryTranslator(int size) { + super(size); + } + + @Override + public void prepareInventory(GeyserSession session, Inventory inventory) { + Vector3i position = session.getPlayerEntity().getPosition().toInt(); + position = position.add(Vector3i.UP); + UpdateBlockPacket blockPacket = new UpdateBlockPacket(); + blockPacket.setDataLayer(0); + blockPacket.setBlockPosition(position); + blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(54 << 4)); //chest + blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); + session.getUpstream().sendPacket(blockPacket); + if (size > 27) { + Vector3i pairPosition = position.add(Vector3i.UNIT_X); + blockPacket = new UpdateBlockPacket(); + blockPacket.setDataLayer(0); + blockPacket.setBlockPosition(pairPosition); + blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(54 << 4)); + blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); + session.getUpstream().sendPacket(blockPacket); + + CompoundTag tag = CompoundTag.EMPTY.toBuilder() + .stringTag("id", "Chest") + .intTag("x", position.getX()) + .intTag("y", position.getY()) + .intTag("z", position.getZ()) + .intTag("pairx", pairPosition.getX()) + .intTag("pairz", pairPosition.getZ()).buildRootTag(); + BlockEntityDataPacket dataPacket = new BlockEntityDataPacket(); + dataPacket.setData(tag); + dataPacket.setBlockPosition(position); + session.getUpstream().sendPacket(dataPacket); + + tag = CompoundTag.EMPTY.toBuilder() + .stringTag("id", "Chest") + .intTag("x", pairPosition.getX()) + .intTag("y", pairPosition.getY()) + .intTag("z", pairPosition.getZ()) + .intTag("pairx", position.getX()) + .intTag("pairz", position.getZ()).buildRootTag(); + dataPacket = new BlockEntityDataPacket(); + dataPacket.setData(tag); + dataPacket.setBlockPosition(pairPosition); + session.getUpstream().sendPacket(dataPacket); + } + inventory.setHolderPosition(position); + } + + @Override + public void openInventory(GeyserSession session, Inventory inventory) { + ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket(); + containerOpenPacket.setWindowId((byte) inventory.getId()); + containerOpenPacket.setType((byte) ContainerType.CONTAINER.id()); + containerOpenPacket.setBlockPosition(inventory.getHolderPosition()); + containerOpenPacket.setUniqueEntityId(inventory.getHolderId()); + session.getUpstream().sendPacket(containerOpenPacket); + } + + @Override + public void closeInventory(GeyserSession session, Inventory inventory) { + Vector3i holderPos = inventory.getHolderPosition(); + Position pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ()); + BlockEntry realBlock = session.getChunkCache().getBlockAt(pos); + UpdateBlockPacket blockPacket = new UpdateBlockPacket(); + blockPacket.setDataLayer(0); + blockPacket.setBlockPosition(holderPos); + blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(realBlock.getBedrockId() << 4 | realBlock.getBedrockData())); + session.getUpstream().sendPacket(blockPacket); + + if (this.size > 27) { + holderPos = holderPos.add(Vector3i.UNIT_X); + pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ()); + realBlock = session.getChunkCache().getBlockAt(pos); + blockPacket = new UpdateBlockPacket(); + blockPacket.setDataLayer(0); + blockPacket.setBlockPosition(holderPos); + blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(realBlock.getBedrockId() << 4 | realBlock.getBedrockData())); + session.getUpstream().sendPacket(blockPacket); + } + } + + @Override + public void updateProperty(GeyserSession session, Inventory inventory, int key, int value) { + } + + @Override + public void updateInventory(GeyserSession session, Inventory inventory) { + //need to pad empty slots for 1x9, 2x9, 4x9, and 5x9 + int paddedSize; + if (this.size > 27) { + paddedSize = 54; + } else { + paddedSize = 27; + } + ItemData[] bedrockItems = new ItemData[paddedSize]; + for (int i = 0; i < bedrockItems.length; i++) { + if (i <= this.size) { + bedrockItems[i] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItems()[i]); + } else { + bedrockItems[i] = ItemData.AIR; + } + } + InventoryContentPacket contentPacket = new InventoryContentPacket(); + contentPacket.setContainerId(inventory.getId()); + contentPacket.setContents(bedrockItems); + session.getUpstream().sendPacket(contentPacket); + + Inventory playerInventory = session.getInventory(); + for (int i = 0; i < 36; i++) { + playerInventory.getItems()[i + 9] = inventory.getItems()[i + this.size]; + } + TranslatorsInit.getInventoryTranslators().get(playerInventory.getWindowType()).updateInventory(session, playerInventory); + } + + @Override + public boolean isOutputSlot(InventoryAction action) { + return false; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DispenserInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DispenserInventoryTranslator.java new file mode 100644 index 00000000..6fe4f102 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DispenserInventoryTranslator.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.inventory; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; +import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.protocol.bedrock.data.ContainerType; +import com.nukkitx.protocol.bedrock.data.InventoryAction; +import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket; +import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; +import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.block.BlockEntry; +import org.geysermc.connector.world.GlobalBlockPalette; + +public class DispenserInventoryTranslator extends InventoryTranslator { + public DispenserInventoryTranslator() { + super(9); + } + + @Override + public void prepareInventory(GeyserSession session, Inventory inventory) { + Vector3i position = session.getPlayerEntity().getPosition().toInt(); + position = position.add(Vector3i.UP); + UpdateBlockPacket blockPacket = new UpdateBlockPacket(); + blockPacket.setDataLayer(0); + blockPacket.setBlockPosition(position); + blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(23 << 4)); //dispenser + blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); + session.getUpstream().sendPacket(blockPacket); + inventory.setHolderPosition(position); + } + + @Override + public void openInventory(GeyserSession session, Inventory inventory) { + ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket(); + containerOpenPacket.setWindowId((byte) inventory.getId()); + containerOpenPacket.setType((byte) ContainerType.DISPENSER.id()); + containerOpenPacket.setBlockPosition(inventory.getHolderPosition()); + containerOpenPacket.setUniqueEntityId(inventory.getHolderId()); + session.getUpstream().sendPacket(containerOpenPacket); + } + + @Override + public void closeInventory(GeyserSession session, Inventory inventory) { + Vector3i holderPos = inventory.getHolderPosition(); + Position pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ()); + BlockEntry realBlock = session.getChunkCache().getBlockAt(pos); + UpdateBlockPacket blockPacket = new UpdateBlockPacket(); + blockPacket.setDataLayer(0); + blockPacket.setBlockPosition(holderPos); + blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(realBlock.getBedrockId() << 4 | realBlock.getBedrockData())); + session.getUpstream().sendPacket(blockPacket); + } + + @Override + public void updateProperty(GeyserSession session, Inventory inventory, int key, int value) { + } + + @Override + public boolean isOutputSlot(InventoryAction action) { + return false; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java new file mode 100644 index 00000000..d46bcde0 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.inventory; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; +import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.nbt.tag.CompoundTag; +import com.nukkitx.protocol.bedrock.data.ContainerId; +import com.nukkitx.protocol.bedrock.data.ContainerType; +import com.nukkitx.protocol.bedrock.data.InventoryAction; +import com.nukkitx.protocol.bedrock.data.ItemData; +import com.nukkitx.protocol.bedrock.packet.*; +import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.block.BlockEntry; +import org.geysermc.connector.world.GlobalBlockPalette; + +public class FurnaceInventoryTranslator extends InventoryTranslator { + public FurnaceInventoryTranslator() { + super(3); + } + + @Override + public void prepareInventory(GeyserSession session, Inventory inventory) { + Vector3i position = session.getPlayerEntity().getPosition().toInt(); + position = position.add(Vector3i.UP); + UpdateBlockPacket blockPacket = new UpdateBlockPacket(); + blockPacket.setDataLayer(0); + blockPacket.setBlockPosition(position); + blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(61 << 4)); //furnace + blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); + session.getUpstream().sendPacket(blockPacket); + inventory.setHolderPosition(position); + } + + @Override + public void openInventory(GeyserSession session, Inventory inventory) { + ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket(); + containerOpenPacket.setWindowId((byte) inventory.getId()); + containerOpenPacket.setType((byte) ContainerType.FURNACE.id()); + containerOpenPacket.setBlockPosition(inventory.getHolderPosition()); + containerOpenPacket.setUniqueEntityId(inventory.getHolderId()); + session.getUpstream().sendPacket(containerOpenPacket); + } + + @Override + public void updateProperty(GeyserSession session, Inventory inventory, int key, int value) { + //bedrock protocol library is currently missing property mappings for windows. only the furnace arrow will update for now + ContainerSetDataPacket dataPacket = new ContainerSetDataPacket(); + dataPacket.setWindowId((byte) inventory.getId()); + switch (key) { + case 0: + dataPacket.setProperty(ContainerSetDataPacket.Property.FURNACE_LIT_TIME); + break; + case 1: + dataPacket.setProperty(ContainerSetDataPacket.Property.FURNACE_LIT_DURATION); + break; + case 2: + dataPacket.setProperty(ContainerSetDataPacket.Property.FURNACE_TICK_COUNT); + break; + default: + return; + } + dataPacket.setValue((short) value); + session.getUpstream().sendPacket(dataPacket); + } + + @Override + public void closeInventory(GeyserSession session, Inventory inventory) { + Vector3i holderPos = inventory.getHolderPosition(); + Position pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ()); + BlockEntry realBlock = session.getChunkCache().getBlockAt(pos); + UpdateBlockPacket blockPacket = new UpdateBlockPacket(); + blockPacket.setDataLayer(0); + blockPacket.setBlockPosition(holderPos); + blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(realBlock.getBedrockId() << 4 | realBlock.getBedrockData())); + session.getUpstream().sendPacket(blockPacket); + } + + @Override + public boolean isOutputSlot(InventoryAction action) { + return action.getSlot() == 2; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/GenericInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/GenericInventoryTranslator.java deleted file mode 100644 index 862117f9..00000000 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/GenericInventoryTranslator.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2019 GeyserMC. http://geysermc.org - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * @author GeyserMC - * @link https://github.com/GeyserMC/Geyser - */ - -package org.geysermc.connector.network.translators.inventory; - -import com.nukkitx.math.vector.Vector3i; -import com.nukkitx.protocol.bedrock.data.ItemData; -import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket; -import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket; -import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; -import org.geysermc.connector.inventory.Inventory; -import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.TranslatorsInit; - -public class GenericInventoryTranslator extends InventoryTranslator { - - @Override - public void prepareInventory(GeyserSession session, Inventory inventory) { - // TODO: Add code here - } - - @Override - public void openInventory(GeyserSession session, Inventory inventory) { - ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket(); - containerOpenPacket.setWindowId((byte) inventory.getId()); - containerOpenPacket.setType((byte) 0); - containerOpenPacket.setBlockPosition(Vector3i.ZERO); - session.getUpstream().sendPacket(containerOpenPacket); - } - - @Override - public void updateInventory(GeyserSession session, Inventory inventory) { - ItemData[] bedrockItems = new ItemData[inventory.getItems().length]; - for (int i = 0; i < bedrockItems.length; i++) { - bedrockItems[i] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItems()[i]); - } - - InventoryContentPacket contentPacket = new InventoryContentPacket(); - contentPacket.setContainerId(inventory.getId()); - contentPacket.setContents(bedrockItems); - session.getUpstream().sendPacket(contentPacket); - } - - @Override - public void updateSlot(GeyserSession session, Inventory inventory, int slot) { - InventorySlotPacket slotPacket = new InventorySlotPacket(); - slotPacket.setContainerId(inventory.getId()); - slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItems()[slot])); - slotPacket.setInventorySlot(slot); - session.getUpstream().sendPacket(slotPacket); - } -} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/HopperInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/HopperInventoryTranslator.java new file mode 100644 index 00000000..28203d35 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/HopperInventoryTranslator.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.inventory; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; +import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.protocol.bedrock.data.ContainerType; +import com.nukkitx.protocol.bedrock.data.InventoryAction; +import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket; +import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; +import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.block.BlockEntry; +import org.geysermc.connector.world.GlobalBlockPalette; + +public class HopperInventoryTranslator extends InventoryTranslator { + public HopperInventoryTranslator() { + super(5); + } + + @Override + public void prepareInventory(GeyserSession session, Inventory inventory) { + Vector3i position = session.getPlayerEntity().getPosition().toInt(); + position = position.add(Vector3i.UP); + UpdateBlockPacket blockPacket = new UpdateBlockPacket(); + blockPacket.setDataLayer(0); + blockPacket.setBlockPosition(position); + blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(154 << 4)); //hopper + blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); + session.getUpstream().sendPacket(blockPacket); + inventory.setHolderPosition(position); + } + + @Override + public void openInventory(GeyserSession session, Inventory inventory) { + ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket(); + containerOpenPacket.setWindowId((byte) inventory.getId()); + containerOpenPacket.setType((byte) ContainerType.HOPPER.id()); + containerOpenPacket.setBlockPosition(inventory.getHolderPosition()); + containerOpenPacket.setUniqueEntityId(inventory.getHolderId()); + session.getUpstream().sendPacket(containerOpenPacket); + } + + @Override + public void closeInventory(GeyserSession session, Inventory inventory) { + Vector3i holderPos = inventory.getHolderPosition(); + Position pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ()); + BlockEntry realBlock = session.getChunkCache().getBlockAt(pos); + UpdateBlockPacket blockPacket = new UpdateBlockPacket(); + blockPacket.setDataLayer(0); + blockPacket.setBlockPosition(holderPos); + blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(realBlock.getBedrockId() << 4 | realBlock.getBedrockData())); + session.getUpstream().sendPacket(blockPacket); + } + + @Override + public void updateProperty(GeyserSession session, Inventory inventory, int key, int value) { + } + + @Override + public boolean isOutputSlot(InventoryAction action) { + return false; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java index 0e244d3b..5a31a040 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java @@ -25,14 +25,72 @@ package org.geysermc.connector.network.translators.inventory; +import com.nukkitx.protocol.bedrock.data.ContainerId; +import com.nukkitx.protocol.bedrock.data.InventoryAction; +import com.nukkitx.protocol.bedrock.data.ItemData; +import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket; +import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.inventory.PlayerInventory; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.TranslatorsInit; public abstract class InventoryTranslator { + public final int size; + + InventoryTranslator(int size) { + this.size = size; + } public abstract void prepareInventory(GeyserSession session, Inventory inventory); public abstract void openInventory(GeyserSession session, Inventory inventory); - public abstract void updateInventory(GeyserSession session, Inventory inventory); - public abstract void updateSlot(GeyserSession session, Inventory inventory, int slot); + public abstract void closeInventory(GeyserSession session, Inventory inventory); + public abstract void updateProperty(GeyserSession session, Inventory inventory, int key, int value); + public void updateInventory(GeyserSession session, Inventory inventory) { + ItemData[] bedrockItems = new ItemData[this.size]; + for (int i = 0; i < bedrockItems.length; i++) { + bedrockItems[i] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItems()[i]); + } + InventoryContentPacket contentPacket = new InventoryContentPacket(); + contentPacket.setContainerId(inventory.getId()); + contentPacket.setContents(bedrockItems); + session.getUpstream().sendPacket(contentPacket); + + Inventory playerInventory = session.getInventory(); + for (int i = 0; i < 36; i++) { + playerInventory.getItems()[i + 9] = inventory.getItems()[i + this.size]; + } + TranslatorsInit.getInventoryTranslators().get(playerInventory.getWindowType()).updateInventory(session, playerInventory); + } + + public void updateSlot(GeyserSession session, Inventory inventory, int slot) { + if (slot >= this.size) { + Inventory playerInventory = session.getInventory(); + playerInventory.getItems()[(slot + 9) - this.size] = inventory.getItem(slot); + TranslatorsInit.getInventoryTranslators().get(playerInventory.getWindowType()).updateSlot(session, playerInventory, (slot + 9) - this.size); + } else { + InventorySlotPacket slotPacket = new InventorySlotPacket(); + slotPacket.setContainerId(inventory.getId()); + slotPacket.setInventorySlot(slot); + slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItems()[slot])); + session.getUpstream().sendPacket(slotPacket); + } + } + + public int bedrockSlotToJava(InventoryAction action) { + int slotnum = action.getSlot(); + if (action.getSource().getContainerId() == ContainerId.INVENTORY) { + //hotbar + if (slotnum >= 9) { + return slotnum + this.size - 9; + } else { + return slotnum + this.size + 27; + } + } else { + return slotnum; + } + } + + public abstract boolean isOutputSlot(InventoryAction action); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java new file mode 100644 index 00000000..153713d7 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.inventory; + +import com.nukkitx.protocol.bedrock.data.*; +import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket; +import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; +import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.TranslatorsInit; + +public class PlayerInventoryTranslator extends InventoryTranslator { + public PlayerInventoryTranslator() { + super(45); + } + + @Override + public void updateInventory(GeyserSession session, Inventory inventory) { + InventoryContentPacket inventoryContentPacket = new InventoryContentPacket(); + inventoryContentPacket.setContainerId(ContainerId.INVENTORY); + + ItemData[] contents = new ItemData[36]; + // Inventory + for (int i = 9; i < 36; i++) { + contents[i] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItems()[i]); + } + + // Hotbar + for (int i = 36; i < 45; i++) { + contents[i - 36] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItems()[i]); + } + + inventoryContentPacket.setContents(contents); + session.getUpstream().sendPacket(inventoryContentPacket); + + // Armor + InventoryContentPacket armorContentPacket = new InventoryContentPacket(); + armorContentPacket.setContainerId(ContainerId.ARMOR); + contents = new ItemData[4]; + for (int i = 5; i < 9; i++) { + contents[i - 5] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItems()[i]); + } + armorContentPacket.setContents(contents); + session.getUpstream().sendPacket(armorContentPacket); + } + + @Override + public void updateSlot(GeyserSession session, Inventory inventory, int slot) { + if (slot >= 5 && slot <= 44) { + InventorySlotPacket slotPacket = new InventorySlotPacket(); + if (slot >= 9) { + slotPacket.setContainerId(ContainerId.INVENTORY); + if (slot >= 36) { + slotPacket.setInventorySlot(slot - 36); + } else { + slotPacket.setInventorySlot(slot); + } + } else { + slotPacket.setContainerId(ContainerId.ARMOR); + slotPacket.setInventorySlot(slot - 5); + } + slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(slot))); + session.getUpstream().sendPacket(slotPacket); + } else if (slot == 0) { + //TODO: crafting output + } + } + + @Override + public int bedrockSlotToJava(InventoryAction action) { + int slotnum = action.getSlot(); + switch (action.getSource().getContainerId()) { + case ContainerId.INVENTORY: + // Inventory + if (slotnum >= 9 && slotnum <= 35) { + return slotnum; + } + // Hotbar + if (slotnum >= 0 && slotnum <= 8) { + return slotnum + 36; + } + break; + case ContainerId.ARMOR: + if (slotnum >= 0 && slotnum <= 3) { + return slotnum + 5; + } + break; + case ContainerId.CRAFTING_ADD_INGREDIENT: + case ContainerId.CRAFTING_REMOVE_INGREDIENT: + return slotnum + 1; + } + return slotnum; + } + + @Override + public boolean isOutputSlot(InventoryAction action) { + return false; + } + + @Override + public void prepareInventory(GeyserSession session, Inventory inventory) { + } + + @Override + public void openInventory(GeyserSession session, Inventory inventory) { + } + + @Override + public void closeInventory(GeyserSession session, Inventory inventory) { + } + + @Override + public void updateProperty(GeyserSession session, Inventory inventory, int key, int value) { + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java index b8d56ccf..f60b56f7 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java @@ -91,7 +91,6 @@ public class ItemTranslator { private CompoundTag translateToJavaNBT(com.nukkitx.nbt.tag.CompoundTag tag) { CompoundTag javaTag = new CompoundTag(tag.getName()); - Map javaValue = javaTag.getValue(); if (tag.getValue() != null && !tag.getValue().isEmpty()) { for (String str : tag.getValue().keySet()) { com.nukkitx.nbt.tag.Tag bedrockTag = tag.get(str); @@ -99,7 +98,7 @@ public class ItemTranslator { if (translatedTag == null) continue; - javaValue.put(str, translatedTag); + javaTag.getValue().put(str, translatedTag); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/inventory/OpenWindowPacketTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/inventory/OpenWindowPacketTranslator.java deleted file mode 100644 index 1b6ab8dc..00000000 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/inventory/OpenWindowPacketTranslator.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.geysermc.connector.network.translators.java.inventory; - -import com.github.steveice10.mc.protocol.packet.ingame.server.window.ServerOpenWindowPacket; -import com.nukkitx.protocol.bedrock.data.ContainerId; -import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket; -import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket; -import org.geysermc.connector.inventory.Inventory; -import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.PacketTranslator; -import org.geysermc.connector.network.translators.TranslatorsInit; -import org.geysermc.connector.network.translators.inventory.InventoryTranslator; - -public class OpenWindowPacketTranslator extends PacketTranslator { - @Override - public void translate(ServerOpenWindowPacket packet, GeyserSession session) { - System.out.println("debug: " + packet.getType()); - InventoryTranslator translator = TranslatorsInit.getInventoryTranslator(); - - translator.openInventory(session, new Inventory(packet.getName(), packet.getWindowId(), packet.getType(), 54)); - - } -} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaCloseWindowTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaCloseWindowTranslator.java new file mode 100644 index 00000000..dcb0c9fe --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaCloseWindowTranslator.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.java.window; + +import com.github.steveice10.mc.protocol.packet.ingame.server.window.ServerCloseWindowPacket; +import com.nukkitx.protocol.bedrock.packet.ContainerClosePacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.utils.InventoryUtils; + +public class JavaCloseWindowTranslator extends PacketTranslator { + + @Override + public void translate(ServerCloseWindowPacket packet, GeyserSession session) { + ContainerClosePacket closePacket = new ContainerClosePacket(); + closePacket.setWindowId((byte)packet.getWindowId()); + session.getUpstream().sendPacket(closePacket); + InventoryUtils.closeInventory(session, packet.getWindowId()); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaConfirmTransactionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaConfirmTransactionTranslator.java new file mode 100644 index 00000000..fc935662 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaConfirmTransactionTranslator.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.java.window; + +import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientConfirmTransactionPacket; +import com.github.steveice10.mc.protocol.packet.ingame.server.window.ServerConfirmTransactionPacket; +import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.network.translators.inventory.InventoryTranslator; +import org.geysermc.connector.utils.InventoryUtils; + +public class JavaConfirmTransactionTranslator extends PacketTranslator { + + @Override + public void translate(ServerConfirmTransactionPacket packet, GeyserSession session) { + System.out.println(packet); + if (!packet.isAccepted()) { + ClientConfirmTransactionPacket confirmPacket = new ClientConfirmTransactionPacket(packet.getWindowId(), packet.getActionId(), true); + session.getDownstream().getSession().send(confirmPacket); + } + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java index eca93a88..d67ad027 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java @@ -25,44 +25,57 @@ package org.geysermc.connector.network.translators.java.window; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.mc.protocol.packet.ingame.server.window.ServerSetSlotPacket; +import com.nukkitx.protocol.bedrock.data.ContainerId; +import com.nukkitx.protocol.bedrock.data.ItemData; +import com.nukkitx.protocol.bedrock.packet.ContainerClosePacket; +import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.session.cache.InventoryCache; import org.geysermc.connector.network.translators.PacketTranslator; -import org.geysermc.connector.utils.InventoryUtils; +import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.inventory.InventoryTranslator; + +import java.util.Objects; public class JavaSetSlotTranslator extends PacketTranslator { @Override public void translate(ServerSetSlotPacket packet, GeyserSession session) { - InventoryCache inventoryCache = session.getInventoryCache(); - if (!inventoryCache.getInventories().containsKey(packet.getWindowId())) { - inventoryCache.cachePacket(packet.getWindowId(), packet); + if (packet.getWindowId() == 255 && packet.getSlot() == -1) { //cursor + if (Objects.equals(session.getInventory().getCursor(), packet.getItem())) + return; + + //bedrock client is bugged when changing the cursor. reopen inventory after changing it + if (packet.getItem() == null && session.getInventory().getCursor() != null) { + InventorySlotPacket cursorPacket = new InventorySlotPacket(); + cursorPacket.setContainerId(ContainerId.CURSOR); + cursorPacket.setSlot(ItemData.AIR); + session.getUpstream().sendPacket(cursorPacket); + + Inventory inventory = session.getInventoryCache().getOpenInventory(); + if (inventory != null) { + session.setReopeningWindow(inventory.getId()); + } else { + inventory = session.getInventory(); + } + ContainerClosePacket closePacket = new ContainerClosePacket(); + closePacket.setWindowId((byte)inventory.getId()); + session.getUpstream().sendPacket(closePacket); + } + + session.getInventory().setCursor(packet.getItem()); return; } - Inventory inventory = inventoryCache.getInventories().get(packet.getWindowId()); - if (packet.getWindowId() != 0 && inventory.getWindowType() == null) + Inventory inventory = session.getInventoryCache().getInventories().get(packet.getWindowId()); + if (inventory == null || (packet.getWindowId() != 0 && inventory.getWindowType() == null)) return; - // Player inventory - if (packet.getWindowId() == 0) { - if (packet.getSlot() >= inventory.getItems().length) - return; // Most likely not a player inventory - - ItemStack[] items = inventory.getItems(); - items[packet.getSlot()] = packet.getItem(); - inventory.setItems(items); - - InventoryUtils.refreshPlayerInventory(session, inventory); - - if (inventory.isOpen()) { - InventoryUtils.updateSlot(session, packet); - } else { - inventoryCache.cachePacket(packet.getWindowId(), packet); - } + InventoryTranslator translator = TranslatorsInit.getInventoryTranslators().get(inventory.getWindowType()); + if (translator != null) { + inventory.getItems()[packet.getSlot()] = packet.getItem(); + translator.updateSlot(session, inventory, packet.getSlot()); } } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaWindowItemsTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaWindowItemsTranslator.java index 8f27e0ee..ce6b4f6c 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaWindowItemsTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaWindowItemsTranslator.java @@ -30,26 +30,22 @@ import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.cache.InventoryCache; import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.inventory.InventoryTranslator; import org.geysermc.connector.utils.InventoryUtils; public class JavaWindowItemsTranslator extends PacketTranslator { @Override public void translate(ServerWindowItemsPacket packet, GeyserSession session) { - InventoryCache inventoryCache = session.getInventoryCache(); - if (!inventoryCache.getInventories().containsKey(packet.getWindowId())) { - inventoryCache.cachePacket(packet.getWindowId(), packet); + Inventory inventory = session.getInventoryCache().getInventories().get(packet.getWindowId()); + if (inventory == null || (packet.getWindowId() != 0 && inventory.getWindowType() == null)) return; - } - Inventory inventory = inventoryCache.getInventories().get(packet.getWindowId()); - // Player inventory - if (packet.getWindowId() == 0) { - inventory.setItems(packet.getItems()); - InventoryUtils.refreshPlayerInventory(session, inventory); - return; + inventory.setItems(packet.getItems()); + InventoryTranslator translator = TranslatorsInit.getInventoryTranslators().get(inventory.getWindowType()); + if (translator != null) { + translator.updateInventory(session, inventory); } - - InventoryUtils.updateInventory(session, packet); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaWindowPropertyTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaWindowPropertyTranslator.java new file mode 100644 index 00000000..2127a94b --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaWindowPropertyTranslator.java @@ -0,0 +1,24 @@ +package org.geysermc.connector.network.translators.java.window; + +import com.github.steveice10.mc.protocol.packet.ingame.server.window.ServerWindowPropertyPacket; +import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.session.cache.InventoryCache; +import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.inventory.InventoryTranslator; + +public class JavaWindowPropertyTranslator extends PacketTranslator { + + @Override + public void translate(ServerWindowPropertyPacket packet, GeyserSession session) { + Inventory inventory = session.getInventoryCache().getInventories().get(packet.getWindowId()); + if (inventory == null || (packet.getWindowId() != 0 && inventory.getWindowType() == null)) + return; + + InventoryTranslator translator = TranslatorsInit.getInventoryTranslators().get(inventory.getWindowType()); + if (translator != null) { + translator.updateProperty(session, inventory, packet.getRawProperty(), packet.getValue()); + } + } +} diff --git a/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java b/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java index a56b6ed7..b979aadb 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java @@ -1,113 +1,63 @@ package org.geysermc.connector.utils; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; -import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientCloseWindowPacket; +import com.github.steveice10.mc.protocol.data.game.window.WindowType; 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 com.github.steveice10.packetlib.packet.Packet; -import com.nukkitx.protocol.bedrock.data.ContainerId; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.nukkitx.protocol.bedrock.data.ItemData; -import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket; import org.geysermc.api.Geyser; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.TranslatorsInit; import org.geysermc.connector.network.translators.inventory.InventoryTranslator; -import java.util.List; +import java.util.Objects; import java.util.concurrent.TimeUnit; public class InventoryUtils { - public static void refreshPlayerInventory(GeyserSession session, Inventory inventory) { - InventoryContentPacket inventoryContentPacket = new InventoryContentPacket(); - inventoryContentPacket.setContainerId(ContainerId.INVENTORY); - - ItemData[] contents = new ItemData[40]; - // Inventory - for (int i = 9; i < 36; i++) { - contents[i] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItems()[i]); - } - - // Hotbar - for (int i = 36; i < 45; i++) { - contents[i - 36] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItems()[i]); - } - - // Armor - for (int i = 5; i < 9; i++) { - contents[i + 31] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItems()[i]); - } - - inventoryContentPacket.setContents(contents); - session.getUpstream().sendPacket(inventoryContentPacket); - } - public static void openInventory(GeyserSession session, ServerOpenWindowPacket packet) { - Inventory inventory = new Inventory(packet.getWindowId(), packet.getType(), 45); // TODO: Find a way to set this value - session.getInventoryCache().getInventories().put(packet.getWindowId(), inventory); - session.getInventoryCache().setOpenInventory(inventory); - - InventoryTranslator translator = TranslatorsInit.getInventoryTranslator(); - translator.prepareInventory(session, inventory); - Geyser.getGeneralThreadPool().schedule(() -> { - List packets = session.getInventoryCache().getCachedPackets().get(inventory.getId()); - packets.forEach(itemPacket -> { - if (itemPacket != null) { - if (ServerWindowItemsPacket.class.isAssignableFrom(itemPacket.getClass())) { - updateInventory(session, (ServerWindowItemsPacket) itemPacket); - } - } - }); - }, 200, TimeUnit.MILLISECONDS); + Inventory inventory = new Inventory(packet.getWindowId(), packet.getType()); + InventoryTranslator translator = TranslatorsInit.getInventoryTranslators().get(inventory.getWindowType()); + if (translator != null) { + session.getInventoryCache().cacheInventory(inventory); + session.getInventoryCache().setOpenInventory(inventory); + translator.prepareInventory(session, inventory); + //TODO: find better way to handle double chest delay + if (inventory.getWindowType() == WindowType.GENERIC_9X4 || inventory.getWindowType() == WindowType.GENERIC_9X5 || inventory.getWindowType() == WindowType.GENERIC_9X6) { + Geyser.getGeneralThreadPool().schedule(() -> { + translator.openInventory(session, inventory); + translator.updateInventory(session, inventory); + }, 200, TimeUnit.MILLISECONDS); + } else { + translator.openInventory(session, inventory); + } + } } - public static void updateInventory(GeyserSession session, ServerWindowItemsPacket packet) { - if (packet.getWindowId() == 0) - return; - - if (session.getInventoryCache().getOpenInventory() == null || !session.getInventoryCache().getInventories().containsKey(packet.getWindowId())) - return; - - Inventory openInventory = session.getInventoryCache().getOpenInventory(); - if (packet.getWindowId() != openInventory.getId()) - return; - - InventoryTranslator translator = TranslatorsInit.getInventoryTranslator(); - if (translator == null) { - session.getDownstream().getSession().send(new ClientCloseWindowPacket(packet.getWindowId())); - return; + public static void closeInventory(GeyserSession session, int windowId) { + if (windowId != 0) { + Inventory inventory = session.getInventoryCache().getInventories().get(windowId); + if (inventory != null) { + InventoryTranslator translator = TranslatorsInit.getInventoryTranslators().get(inventory.getWindowType()); + translator.closeInventory(session, inventory); + session.getInventoryCache().uncacheInventory(windowId); + } + session.getInventoryCache().setOpenInventory(null); } - - openInventory.setItems(packet.getItems()); - translator.updateInventory(session, openInventory); } - public static void updateSlot(GeyserSession session, ServerSetSlotPacket packet) { - if (packet.getWindowId() == 0) - return; + //currently, ItemStack.equals() does not check the item id + public static boolean canCombine(ItemData stack1, ItemData stack2) { + if (stack1 == null || stack2 == null) + return false; + return stack1.getId() == stack2.getId() && stack1.equals(stack2, false, true, true); + } - if (session.getInventoryCache().getOpenInventory() == null || !session.getInventoryCache().getInventories().containsKey(packet.getWindowId())) - return; - - Inventory openInventory = session.getInventoryCache().getOpenInventory(); - if (packet.getWindowId() != openInventory.getId()) - return; - - InventoryTranslator translator = TranslatorsInit.getInventoryTranslator(); - if (translator == null) { - session.getDownstream().getSession().send(new ClientCloseWindowPacket(packet.getWindowId())); - return; - } - - if (packet.getSlot() >= openInventory.getSize()) { - session.getDownstream().getSession().send(new ClientCloseWindowPacket(packet.getWindowId())); - return; - } - - ItemStack[] items = openInventory.getItems(); - items[packet.getSlot()] = packet.getItem(); - translator.updateSlot(session, openInventory, packet.getSlot()); + //NPE if nbt tag is null + public static ItemStack fixNbt(ItemStack stack) { + if (stack == null) + return null; + return new ItemStack(stack.getId(), stack.getAmount(), stack.getNbt() == null ? new CompoundTag("") : stack.getNbt()); } } From 3812712a06faedca6e50117cb02d5a566c51030b Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Sun, 20 Oct 2019 13:29:21 -0800 Subject: [PATCH 003/109] Remove debug messages --- .../bedrock/BedrockInventoryTransactionTranslator.java | 4 ---- .../java/window/JavaConfirmTransactionTranslator.java | 1 - 2 files changed, 5 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java index e3301604..78509d12 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java @@ -140,7 +140,6 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator Date: Sun, 20 Oct 2019 13:52:21 -0800 Subject: [PATCH 004/109] Add delay when reopening inventory --- .../java/window/JavaSetSlotTranslator.java | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java index d67ad027..0392a52c 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java @@ -30,6 +30,7 @@ import com.nukkitx.protocol.bedrock.data.ContainerId; import com.nukkitx.protocol.bedrock.data.ItemData; import com.nukkitx.protocol.bedrock.packet.ContainerClosePacket; import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; +import org.geysermc.api.Geyser; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; @@ -37,6 +38,7 @@ import org.geysermc.connector.network.translators.TranslatorsInit; import org.geysermc.connector.network.translators.inventory.InventoryTranslator; import java.util.Objects; +import java.util.concurrent.TimeUnit; public class JavaSetSlotTranslator extends PacketTranslator { @@ -53,15 +55,17 @@ public class JavaSetSlotTranslator extends PacketTranslator cursorPacket.setSlot(ItemData.AIR); session.getUpstream().sendPacket(cursorPacket); - Inventory inventory = session.getInventoryCache().getOpenInventory(); - if (inventory != null) { - session.setReopeningWindow(inventory.getId()); - } else { - inventory = session.getInventory(); - } - ContainerClosePacket closePacket = new ContainerClosePacket(); - closePacket.setWindowId((byte)inventory.getId()); - session.getUpstream().sendPacket(closePacket); + Geyser.getGeneralThreadPool().schedule(() -> { + Inventory inventory = session.getInventoryCache().getOpenInventory(); + if (inventory != null) { + session.setReopeningWindow(inventory.getId()); + } else { + inventory = session.getInventory(); + } + ContainerClosePacket closePacket = new ContainerClosePacket(); + closePacket.setWindowId((byte) inventory.getId()); + session.getUpstream().sendPacket(closePacket); + }, 150, TimeUnit.MILLISECONDS); } session.getInventory().setCursor(packet.getItem()); From 06358b2449c11ec84761fd568fa7c4ccd7575d4b Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Sun, 20 Oct 2019 15:24:29 -0800 Subject: [PATCH 005/109] Update JavaSetSlotTranslator.java --- .../java/window/JavaSetSlotTranslator.java | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java index 0392a52c..562eb193 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java @@ -55,17 +55,15 @@ public class JavaSetSlotTranslator extends PacketTranslator cursorPacket.setSlot(ItemData.AIR); session.getUpstream().sendPacket(cursorPacket); - Geyser.getGeneralThreadPool().schedule(() -> { - Inventory inventory = session.getInventoryCache().getOpenInventory(); - if (inventory != null) { - session.setReopeningWindow(inventory.getId()); - } else { - inventory = session.getInventory(); - } - ContainerClosePacket closePacket = new ContainerClosePacket(); - closePacket.setWindowId((byte) inventory.getId()); - session.getUpstream().sendPacket(closePacket); - }, 150, TimeUnit.MILLISECONDS); + Inventory inventory = session.getInventoryCache().getOpenInventory(); + if (inventory != null) { + session.setReopeningWindow(inventory.getId()); + } else { + inventory = session.getInventory(); + } + ContainerClosePacket closePacket = new ContainerClosePacket(); + closePacket.setWindowId((byte) inventory.getId()); + Geyser.getGeneralThreadPool().schedule(() -> session.getUpstream().sendPacket(closePacket), 150, TimeUnit.MILLISECONDS); } session.getInventory().setCursor(packet.getItem()); From 4074582059be6d5ee40124e0cb2ee8b35570336c Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Sun, 20 Oct 2019 19:41:46 -0800 Subject: [PATCH 006/109] Close open inventory before opening a new one --- .../network/translators/TranslatorsInit.java | 12 +- .../DoubleChestInventoryTranslator.java | 157 ++++++++++++++++++ ...va => SingleChestInventoryTranslator.java} | 57 +------ .../java/window/JavaOpenWindowTranslator.java | 29 +++- .../connector/utils/InventoryUtils.java | 8 +- 5 files changed, 199 insertions(+), 64 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java rename connector/src/main/java/org/geysermc/connector/network/translators/inventory/{ChestInventoryTranslator.java => SingleChestInventoryTranslator.java} (66%) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java index 74c50dbf..09741a23 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java @@ -162,12 +162,12 @@ public class TranslatorsInit { private static void registerInventoryTranslators() { inventoryTranslators.put(null, new PlayerInventoryTranslator()); //player inventory - inventoryTranslators.put(WindowType.GENERIC_9X1, new ChestInventoryTranslator(9)); - inventoryTranslators.put(WindowType.GENERIC_9X2, new ChestInventoryTranslator(18)); - inventoryTranslators.put(WindowType.GENERIC_9X3, new ChestInventoryTranslator(27)); - inventoryTranslators.put(WindowType.GENERIC_9X4, new ChestInventoryTranslator(36)); - inventoryTranslators.put(WindowType.GENERIC_9X5, new ChestInventoryTranslator(45)); - inventoryTranslators.put(WindowType.GENERIC_9X6, new ChestInventoryTranslator(54)); + inventoryTranslators.put(WindowType.GENERIC_9X1, new SingleChestInventoryTranslator(9)); + inventoryTranslators.put(WindowType.GENERIC_9X2, new SingleChestInventoryTranslator(18)); + inventoryTranslators.put(WindowType.GENERIC_9X3, new SingleChestInventoryTranslator(27)); + inventoryTranslators.put(WindowType.GENERIC_9X4, new DoubleChestInventoryTranslator(36)); + inventoryTranslators.put(WindowType.GENERIC_9X5, new DoubleChestInventoryTranslator(45)); + inventoryTranslators.put(WindowType.GENERIC_9X6, new DoubleChestInventoryTranslator(54)); inventoryTranslators.put(WindowType.GENERIC_3X3, new DispenserInventoryTranslator()); inventoryTranslators.put(WindowType.HOPPER, new HopperInventoryTranslator()); inventoryTranslators.put(WindowType.FURNACE, new FurnaceInventoryTranslator()); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java new file mode 100644 index 00000000..027c59c6 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.inventory; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; +import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.nbt.tag.CompoundTag; +import com.nukkitx.protocol.bedrock.data.ContainerType; +import com.nukkitx.protocol.bedrock.data.InventoryAction; +import com.nukkitx.protocol.bedrock.data.ItemData; +import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; +import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket; +import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket; +import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; +import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.block.BlockEntry; +import org.geysermc.connector.world.GlobalBlockPalette; + +public class DoubleChestInventoryTranslator extends InventoryTranslator { + public DoubleChestInventoryTranslator(int size) { + super(size); + } + + @Override + public void prepareInventory(GeyserSession session, Inventory inventory) { + Vector3i position = session.getPlayerEntity().getPosition().toInt().add(Vector3i.UP); + Vector3i pairPosition = position.add(Vector3i.UNIT_X); + UpdateBlockPacket blockPacket = new UpdateBlockPacket(); + blockPacket.setDataLayer(0); + blockPacket.setBlockPosition(position); + blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(54 << 4)); //chest + blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); + session.getUpstream().sendPacket(blockPacket); + + CompoundTag tag = CompoundTag.EMPTY.toBuilder() + .stringTag("id", "Chest") + .intTag("x", position.getX()) + .intTag("y", position.getY()) + .intTag("z", position.getZ()) + .intTag("pairx", pairPosition.getX()) + .intTag("pairz", pairPosition.getZ()).buildRootTag(); + BlockEntityDataPacket dataPacket = new BlockEntityDataPacket(); + dataPacket.setData(tag); + dataPacket.setBlockPosition(position); + session.getUpstream().sendPacket(dataPacket); + + blockPacket = new UpdateBlockPacket(); + blockPacket.setDataLayer(0); + blockPacket.setBlockPosition(pairPosition); + blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(54 << 4)); + blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); + session.getUpstream().sendPacket(blockPacket); + + tag = CompoundTag.EMPTY.toBuilder() + .stringTag("id", "Chest") + .intTag("x", pairPosition.getX()) + .intTag("y", pairPosition.getY()) + .intTag("z", pairPosition.getZ()) + .intTag("pairx", position.getX()) + .intTag("pairz", position.getZ()).buildRootTag(); + dataPacket = new BlockEntityDataPacket(); + dataPacket.setData(tag); + dataPacket.setBlockPosition(pairPosition); + session.getUpstream().sendPacket(dataPacket); + + inventory.setHolderPosition(position); + } + + @Override + public void openInventory(GeyserSession session, Inventory inventory) { + ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket(); + containerOpenPacket.setWindowId((byte) inventory.getId()); + containerOpenPacket.setType((byte) ContainerType.CONTAINER.id()); + containerOpenPacket.setBlockPosition(inventory.getHolderPosition()); + containerOpenPacket.setUniqueEntityId(inventory.getHolderId()); + session.getUpstream().sendPacket(containerOpenPacket); + } + + @Override + public void closeInventory(GeyserSession session, Inventory inventory) { + Vector3i holderPos = inventory.getHolderPosition(); + Position pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ()); + BlockEntry realBlock = session.getChunkCache().getBlockAt(pos); + UpdateBlockPacket blockPacket = new UpdateBlockPacket(); + blockPacket.setDataLayer(0); + blockPacket.setBlockPosition(holderPos); + blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(realBlock.getBedrockId() << 4 | realBlock.getBedrockData())); + session.getUpstream().sendPacket(blockPacket); + + holderPos = holderPos.add(Vector3i.UNIT_X); + pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ()); + realBlock = session.getChunkCache().getBlockAt(pos); + blockPacket = new UpdateBlockPacket(); + blockPacket.setDataLayer(0); + blockPacket.setBlockPosition(holderPos); + blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(realBlock.getBedrockId() << 4 | realBlock.getBedrockData())); + session.getUpstream().sendPacket(blockPacket); + } + + @Override + public void updateProperty(GeyserSession session, Inventory inventory, int key, int value) { + } + + @Override + public void updateInventory(GeyserSession session, Inventory inventory) { + //need to pad empty slots for 4x9, and 5x9 + final int paddedSize = 54; + ItemData[] bedrockItems = new ItemData[paddedSize]; + for (int i = 0; i < bedrockItems.length; i++) { + if (i <= this.size) { + bedrockItems[i] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItems()[i]); + } else { + bedrockItems[i] = ItemData.AIR; + } + } + InventoryContentPacket contentPacket = new InventoryContentPacket(); + contentPacket.setContainerId(inventory.getId()); + contentPacket.setContents(bedrockItems); + session.getUpstream().sendPacket(contentPacket); + + Inventory playerInventory = session.getInventory(); + for (int i = 0; i < 36; i++) { + playerInventory.getItems()[i + 9] = inventory.getItems()[i + this.size]; + } + TranslatorsInit.getInventoryTranslators().get(playerInventory.getWindowType()).updateInventory(session, playerInventory); + } + + @Override + public boolean isOutputSlot(InventoryAction action) { + return false; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/ChestInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java similarity index 66% rename from connector/src/main/java/org/geysermc/connector/network/translators/inventory/ChestInventoryTranslator.java rename to connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java index bd2aa581..fd58e7c6 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/ChestInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java @@ -39,8 +39,8 @@ import org.geysermc.connector.network.translators.TranslatorsInit; import org.geysermc.connector.network.translators.block.BlockEntry; import org.geysermc.connector.world.GlobalBlockPalette; -public class ChestInventoryTranslator extends InventoryTranslator { - public ChestInventoryTranslator(int size) { +public class SingleChestInventoryTranslator extends InventoryTranslator { + public SingleChestInventoryTranslator(int size) { super(size); } @@ -54,39 +54,6 @@ public class ChestInventoryTranslator extends InventoryTranslator { blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(54 << 4)); //chest blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); session.getUpstream().sendPacket(blockPacket); - if (size > 27) { - Vector3i pairPosition = position.add(Vector3i.UNIT_X); - blockPacket = new UpdateBlockPacket(); - blockPacket.setDataLayer(0); - blockPacket.setBlockPosition(pairPosition); - blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(54 << 4)); - blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); - session.getUpstream().sendPacket(blockPacket); - - CompoundTag tag = CompoundTag.EMPTY.toBuilder() - .stringTag("id", "Chest") - .intTag("x", position.getX()) - .intTag("y", position.getY()) - .intTag("z", position.getZ()) - .intTag("pairx", pairPosition.getX()) - .intTag("pairz", pairPosition.getZ()).buildRootTag(); - BlockEntityDataPacket dataPacket = new BlockEntityDataPacket(); - dataPacket.setData(tag); - dataPacket.setBlockPosition(position); - session.getUpstream().sendPacket(dataPacket); - - tag = CompoundTag.EMPTY.toBuilder() - .stringTag("id", "Chest") - .intTag("x", pairPosition.getX()) - .intTag("y", pairPosition.getY()) - .intTag("z", pairPosition.getZ()) - .intTag("pairx", position.getX()) - .intTag("pairz", position.getZ()).buildRootTag(); - dataPacket = new BlockEntityDataPacket(); - dataPacket.setData(tag); - dataPacket.setBlockPosition(pairPosition); - session.getUpstream().sendPacket(dataPacket); - } inventory.setHolderPosition(position); } @@ -110,17 +77,6 @@ public class ChestInventoryTranslator extends InventoryTranslator { blockPacket.setBlockPosition(holderPos); blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(realBlock.getBedrockId() << 4 | realBlock.getBedrockData())); session.getUpstream().sendPacket(blockPacket); - - if (this.size > 27) { - holderPos = holderPos.add(Vector3i.UNIT_X); - pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ()); - realBlock = session.getChunkCache().getBlockAt(pos); - blockPacket = new UpdateBlockPacket(); - blockPacket.setDataLayer(0); - blockPacket.setBlockPosition(holderPos); - blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(realBlock.getBedrockId() << 4 | realBlock.getBedrockData())); - session.getUpstream().sendPacket(blockPacket); - } } @Override @@ -129,13 +85,8 @@ public class ChestInventoryTranslator extends InventoryTranslator { @Override public void updateInventory(GeyserSession session, Inventory inventory) { - //need to pad empty slots for 1x9, 2x9, 4x9, and 5x9 - int paddedSize; - if (this.size > 27) { - paddedSize = 54; - } else { - paddedSize = 27; - } + //need to pad empty slots for 1x9 and 2x9 + final int paddedSize = 27; ItemData[] bedrockItems = new ItemData[paddedSize]; for (int i = 0; i < bedrockItems.length; i++) { if (i <= this.size) { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaOpenWindowTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaOpenWindowTranslator.java index b5e0447c..95aa618c 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaOpenWindowTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaOpenWindowTranslator.java @@ -25,15 +25,42 @@ package org.geysermc.connector.network.translators.java.window; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientCloseWindowPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.window.ServerOpenWindowPacket; +import org.geysermc.api.Geyser; +import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.inventory.InventoryTranslator; import org.geysermc.connector.utils.InventoryUtils; +import java.util.concurrent.TimeUnit; + public class JavaOpenWindowTranslator extends PacketTranslator { @Override public void translate(ServerOpenWindowPacket packet, GeyserSession session) { - InventoryUtils.openInventory(session, packet); + InventoryTranslator newTranslator = TranslatorsInit.getInventoryTranslators().get(packet.getType()); + if (newTranslator == null) { + ClientCloseWindowPacket closeWindowPacket = new ClientCloseWindowPacket(packet.getWindowId()); + session.getDownstream().getSession().send(closeWindowPacket); + return; + } + Inventory openInventory = session.getInventoryCache().getOpenInventory(); + Inventory newInventory = new Inventory(packet.getWindowId(), packet.getType()); + newInventory.setItems(new ItemStack[newTranslator.size + 36]); + session.getInventoryCache().cacheInventory(newInventory); + if (openInventory != null) { + InventoryTranslator openTranslator = TranslatorsInit.getInventoryTranslators().get(openInventory.getWindowType()); + if (!openTranslator.getClass().equals(newTranslator.getClass())) { + InventoryUtils.closeInventory(session, openInventory.getId()); + Geyser.getGeneralThreadPool().schedule(() -> InventoryUtils.openInventory(session, newInventory), 350, TimeUnit.MILLISECONDS); + return; + } + } + + InventoryUtils.openInventory(session, newInventory); } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java b/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java index b979aadb..2663ab37 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java @@ -9,6 +9,7 @@ import org.geysermc.api.Geyser; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.inventory.DoubleChestInventoryTranslator; import org.geysermc.connector.network.translators.inventory.InventoryTranslator; import java.util.Objects; @@ -16,21 +17,20 @@ import java.util.concurrent.TimeUnit; public class InventoryUtils { - public static void openInventory(GeyserSession session, ServerOpenWindowPacket packet) { - Inventory inventory = new Inventory(packet.getWindowId(), packet.getType()); + public static void openInventory(GeyserSession session, Inventory inventory) { InventoryTranslator translator = TranslatorsInit.getInventoryTranslators().get(inventory.getWindowType()); if (translator != null) { - session.getInventoryCache().cacheInventory(inventory); session.getInventoryCache().setOpenInventory(inventory); translator.prepareInventory(session, inventory); //TODO: find better way to handle double chest delay - if (inventory.getWindowType() == WindowType.GENERIC_9X4 || inventory.getWindowType() == WindowType.GENERIC_9X5 || inventory.getWindowType() == WindowType.GENERIC_9X6) { + if (translator instanceof DoubleChestInventoryTranslator) { Geyser.getGeneralThreadPool().schedule(() -> { translator.openInventory(session, inventory); translator.updateInventory(session, inventory); }, 200, TimeUnit.MILLISECONDS); } else { translator.openInventory(session, inventory); + translator.updateInventory(session, inventory); } } } From 08357ed8b2ae7836f26b6dcd63b82277675a7607 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Mon, 21 Oct 2019 00:12:27 -0800 Subject: [PATCH 007/109] Uncache chunks --- .../network/translators/TranslatorsInit.java | 1 + .../java/JavaRespawnTranslator.java | 1 + .../java/world/JavaUnloadChunkTranslator.java | 39 +++++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUnloadChunkTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java index 09741a23..46c13d3d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java @@ -135,6 +135,7 @@ public class TranslatorsInit { Registry.registerJava(ServerTeamPacket.class, new JavaTeamTranslator()); Registry.registerJava(ServerBlockChangePacket.class, new JavaBlockChangeTranslator()); Registry.registerJava(ServerMultiBlockChangePacket.class, new JavaMultiBlockChangeTranslator()); + Registry.registerJava(ServerUnloadChunkPacket.class, new JavaUnloadChunkTranslator()); Registry.registerJava(ServerWindowItemsPacket.class, new JavaWindowItemsTranslator()); Registry.registerJava(ServerOpenWindowPacket.class, new JavaOpenWindowTranslator()); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaRespawnTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaRespawnTranslator.java index f5f86e19..4661b1cf 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaRespawnTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaRespawnTranslator.java @@ -44,6 +44,7 @@ public class JavaRespawnTranslator extends PacketTranslator if (entity.getDimension() == getDimension(packet.getDimension())) return; + session.getChunkCache().getChunks().clear(); entity.setDimension(getDimension(packet.getDimension())); ChangeDimensionPacket changeDimensionPacket = new ChangeDimensionPacket(); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUnloadChunkTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUnloadChunkTranslator.java new file mode 100644 index 00000000..b727f440 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUnloadChunkTranslator.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.java.world; + +import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerUnloadChunkPacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.world.chunk.ChunkPosition; + +public class JavaUnloadChunkTranslator extends PacketTranslator { + + @Override + public void translate(ServerUnloadChunkPacket packet, GeyserSession session) { + session.getChunkCache().removeChunk(new ChunkPosition(packet.getX(), packet.getZ())); + } +} From 12c049709a8274c17705f9a7a0d1e99a293bb250 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Mon, 21 Oct 2019 03:16:02 -0800 Subject: [PATCH 008/109] Fix item nbt translator Mineplex server seemed to be sensitive about quotes in string tags --- .../connector/network/translators/item/ItemTranslator.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java index f60b56f7..071ab75d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java @@ -91,6 +91,7 @@ public class ItemTranslator { private CompoundTag translateToJavaNBT(com.nukkitx.nbt.tag.CompoundTag tag) { CompoundTag javaTag = new CompoundTag(tag.getName()); + Map javaValue = javaTag.getValue(); if (tag.getValue() != null && !tag.getValue().isEmpty()) { for (String str : tag.getValue().keySet()) { com.nukkitx.nbt.tag.Tag bedrockTag = tag.get(str); @@ -98,10 +99,11 @@ public class ItemTranslator { if (translatedTag == null) continue; - javaTag.getValue().put(str, translatedTag); + javaValue.put(str, translatedTag); } } + javaTag.setValue(javaValue); return javaTag; } @@ -153,7 +155,7 @@ public class ItemTranslator { if (tag instanceof com.nukkitx.nbt.tag.StringTag) { com.nukkitx.nbt.tag.StringTag stringTag = (com.nukkitx.nbt.tag.StringTag) tag; - return new StringTag(stringTag.getName(), stringTag.getValue()); + return new StringTag(stringTag.getName(), '"' + stringTag.getValue() + '"'); } if (tag instanceof com.nukkitx.nbt.tag.ListTag) { From 38fd5376e7364c9d4105f6969a5a79aaa62d66cf Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Mon, 21 Oct 2019 16:07:07 -0800 Subject: [PATCH 009/109] Revert storing chunks in chunk cache --- .../java/entity/player/JavaPlayerActionAckTranslator.java | 1 - .../translators/java/world/JavaBlockChangeTranslator.java | 2 -- .../network/translators/java/world/JavaChunkDataTranslator.java | 1 - .../translators/java/world/JavaMultiBlockChangeTranslator.java | 1 - 4 files changed, 5 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java index cf5c26bc..3213a2fd 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java @@ -40,7 +40,6 @@ public class JavaPlayerActionAckTranslator extends PacketTranslator { Vector2i chunkPos = session.getLastChunkPosition(); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaMultiBlockChangeTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaMultiBlockChangeTranslator.java index b78e366c..14864b8c 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaMultiBlockChangeTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaMultiBlockChangeTranslator.java @@ -40,7 +40,6 @@ public class JavaMultiBlockChangeTranslator extends PacketTranslator Date: Tue, 22 Oct 2019 15:31:03 -0800 Subject: [PATCH 010/109] Various fixes Fix offhand, use AtomicInteger for transaction id, send null stack instead of air, and clear open inventory on dimension change --- .../connector/inventory/Inventory.java | 20 ++++++---- .../connector/inventory/PlayerInventory.java | 4 +- ...BedrockInventoryTransactionTranslator.java | 37 +++++++++---------- .../inventory/PlayerInventoryTranslator.java | 15 +++++++- .../java/JavaRespawnTranslator.java | 1 + .../java/window/JavaOpenWindowTranslator.java | 15 ++++++-- .../window/JavaWindowItemsTranslator.java | 11 ++++-- .../connector/utils/InventoryUtils.java | 6 +-- 8 files changed, 69 insertions(+), 40 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java b/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java index 215ac597..2147b070 100644 --- a/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java +++ b/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java @@ -31,6 +31,8 @@ import com.nukkitx.math.vector.Vector3i; import lombok.Getter; import lombok.Setter; +import java.util.concurrent.atomic.AtomicInteger; + public class Inventory { @Getter @@ -43,6 +45,9 @@ public class Inventory { @Getter protected WindowType windowType; + @Getter + protected final int size; + @Getter @Setter protected String title; @@ -59,23 +64,22 @@ public class Inventory { @Setter protected long holderId = -1; - protected short transactionId = 1; + @Getter + protected AtomicInteger transactionId = new AtomicInteger(1); - public Inventory(int id, WindowType windowType) { - this("Inventory", id, windowType); + public Inventory(int id, WindowType windowType, int size) { + this("Inventory", id, windowType, size); } - public Inventory(String title, int id, WindowType windowType) { + public Inventory(String title, int id, WindowType windowType, int size) { this.title = title; this.id = id; this.windowType = windowType; + this.size = size; + this.items = new ItemStack[size]; } public ItemStack getItem(int slot) { return items[slot]; } - - public short getNextTransactionId() { - return transactionId++; - } } diff --git a/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java b/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java index 44ad3cb6..4fd3bcd8 100644 --- a/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java +++ b/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java @@ -39,9 +39,7 @@ public class PlayerInventory extends Inventory { private ItemStack cursor; public PlayerInventory() { - super(0, null); - - items = new ItemStack[45]; + super(0, null, 46); heldItemSlot = 0; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java index 78509d12..c0b805aa 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java @@ -45,7 +45,6 @@ import com.nukkitx.protocol.bedrock.data.ItemData; import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import com.nukkitx.protocol.bedrock.packet.InventoryTransactionPacket; import org.geysermc.connector.entity.Entity; -import org.geysermc.connector.entity.PlayerEntity; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; @@ -110,13 +109,13 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator cursorAction.getFromItem().getCount()) { //fill stack int javaSlot = session.getLastClickedSlot(); - ClientWindowActionPacket fillStackPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getNextTransactionId(), + ClientWindowActionPacket fillStackPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getTransactionId().getAndIncrement(), javaSlot, null, WindowAction.FILL_STACK, FillStackParam.FILL); session.getDownstream().getSession().send(fillStackPacket); translator.updateInventory(session, inventory); //bedrock fill stack can sometimes differ from java version, refresh and let server change slots @@ -153,8 +152,8 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator if (entity.getDimension() == getDimension(packet.getDimension())) return; + session.getInventoryCache().setOpenInventory(null); session.getChunkCache().getChunks().clear(); entity.setDimension(getDimension(packet.getDimension())); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaOpenWindowTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaOpenWindowTranslator.java index 95aa618c..9e336ebd 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaOpenWindowTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaOpenWindowTranslator.java @@ -28,6 +28,7 @@ package org.geysermc.connector.network.translators.java.window; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientCloseWindowPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.window.ServerOpenWindowPacket; +import com.nukkitx.protocol.bedrock.packet.ContainerClosePacket; import org.geysermc.api.Geyser; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; @@ -42,15 +43,23 @@ public class JavaOpenWindowTranslator extends PacketTranslator { @@ -42,7 +42,12 @@ public class JavaWindowItemsTranslator extends PacketTranslator Date: Fri, 1 Nov 2019 01:07:13 -0800 Subject: [PATCH 011/109] Add inventory names Some translation identifiers such as "container.blast_furnace" are not being translated yet --- .../DispenserInventoryTranslator.java | 12 ++++++++++++ .../DoubleChestInventoryTranslator.java | 6 ++++-- .../inventory/FurnaceInventoryTranslator.java | 10 ++++++++++ .../inventory/HopperInventoryTranslator.java | 12 ++++++++++++ .../SingleChestInventoryTranslator.java | 10 ++++++++++ .../java/window/JavaOpenWindowTranslator.java | 19 +++++++++++++++++-- 6 files changed, 65 insertions(+), 4 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DispenserInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DispenserInventoryTranslator.java index 6fe4f102..9f361f39 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DispenserInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DispenserInventoryTranslator.java @@ -27,8 +27,10 @@ package org.geysermc.connector.network.translators.inventory; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.nbt.tag.CompoundTag; import com.nukkitx.protocol.bedrock.data.ContainerType; import com.nukkitx.protocol.bedrock.data.InventoryAction; +import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.connector.inventory.Inventory; @@ -52,6 +54,16 @@ public class DispenserInventoryTranslator extends InventoryTranslator { blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); session.getUpstream().sendPacket(blockPacket); inventory.setHolderPosition(position); + + CompoundTag tag = CompoundTag.EMPTY.toBuilder() + .intTag("x", position.getX()) + .intTag("y", position.getY()) + .intTag("z", position.getZ()) + .stringTag("CustomName", inventory.getTitle()).buildRootTag(); + BlockEntityDataPacket dataPacket = new BlockEntityDataPacket(); + dataPacket.setData(tag); + dataPacket.setBlockPosition(position); + session.getUpstream().sendPacket(dataPacket); } @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java index 027c59c6..d52e9447 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java @@ -63,7 +63,8 @@ public class DoubleChestInventoryTranslator extends InventoryTranslator { .intTag("y", position.getY()) .intTag("z", position.getZ()) .intTag("pairx", pairPosition.getX()) - .intTag("pairz", pairPosition.getZ()).buildRootTag(); + .intTag("pairz", pairPosition.getZ()) + .stringTag("CustomName", inventory.getTitle()).buildRootTag(); BlockEntityDataPacket dataPacket = new BlockEntityDataPacket(); dataPacket.setData(tag); dataPacket.setBlockPosition(position); @@ -82,7 +83,8 @@ public class DoubleChestInventoryTranslator extends InventoryTranslator { .intTag("y", pairPosition.getY()) .intTag("z", pairPosition.getZ()) .intTag("pairx", position.getX()) - .intTag("pairz", position.getZ()).buildRootTag(); + .intTag("pairz", position.getZ()) + .stringTag("CustomName", inventory.getTitle()).buildRootTag(); dataPacket = new BlockEntityDataPacket(); dataPacket.setData(tag); dataPacket.setBlockPosition(pairPosition); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java index d46bcde0..c65fca02 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java @@ -55,6 +55,16 @@ public class FurnaceInventoryTranslator extends InventoryTranslator { blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); session.getUpstream().sendPacket(blockPacket); inventory.setHolderPosition(position); + + CompoundTag tag = CompoundTag.EMPTY.toBuilder() + .intTag("x", position.getX()) + .intTag("y", position.getY()) + .intTag("z", position.getZ()) + .stringTag("CustomName", inventory.getTitle()).buildRootTag(); + BlockEntityDataPacket dataPacket = new BlockEntityDataPacket(); + dataPacket.setData(tag); + dataPacket.setBlockPosition(position); + session.getUpstream().sendPacket(dataPacket); } @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/HopperInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/HopperInventoryTranslator.java index 28203d35..cf877d0f 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/HopperInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/HopperInventoryTranslator.java @@ -27,8 +27,10 @@ package org.geysermc.connector.network.translators.inventory; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.nbt.tag.CompoundTag; import com.nukkitx.protocol.bedrock.data.ContainerType; import com.nukkitx.protocol.bedrock.data.InventoryAction; +import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.connector.inventory.Inventory; @@ -52,6 +54,16 @@ public class HopperInventoryTranslator extends InventoryTranslator { blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); session.getUpstream().sendPacket(blockPacket); inventory.setHolderPosition(position); + + CompoundTag tag = CompoundTag.EMPTY.toBuilder() + .intTag("x", position.getX()) + .intTag("y", position.getY()) + .intTag("z", position.getZ()) + .stringTag("CustomName", inventory.getTitle()).buildRootTag(); + BlockEntityDataPacket dataPacket = new BlockEntityDataPacket(); + dataPacket.setData(tag); + dataPacket.setBlockPosition(position); + session.getUpstream().sendPacket(dataPacket); } @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java index fd58e7c6..ef8f97cc 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java @@ -55,6 +55,16 @@ public class SingleChestInventoryTranslator extends InventoryTranslator { blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); session.getUpstream().sendPacket(blockPacket); inventory.setHolderPosition(position); + + CompoundTag tag = CompoundTag.EMPTY.toBuilder() + .intTag("x", position.getX()) + .intTag("y", position.getY()) + .intTag("z", position.getZ()) + .stringTag("CustomName", inventory.getTitle()).buildRootTag(); + BlockEntityDataPacket dataPacket = new BlockEntityDataPacket(); + dataPacket.setData(tag); + dataPacket.setBlockPosition(position); + session.getUpstream().sendPacket(dataPacket); } @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaOpenWindowTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaOpenWindowTranslator.java index 9e336ebd..eab7bee2 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaOpenWindowTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaOpenWindowTranslator.java @@ -25,9 +25,10 @@ package org.geysermc.connector.network.translators.java.window; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientCloseWindowPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.window.ServerOpenWindowPacket; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; import com.nukkitx.protocol.bedrock.packet.ContainerClosePacket; import org.geysermc.api.Geyser; import org.geysermc.connector.inventory.Inventory; @@ -59,7 +60,21 @@ public class JavaOpenWindowTranslator extends PacketTranslator Date: Tue, 5 Nov 2019 14:17:22 -0900 Subject: [PATCH 012/109] Implement some more windows anvil, brewing stand, crafting table (still no crafting yet), shulker box --- .../network/translators/TranslatorsInit.java | 20 +++- .../BedrockContainerCloseTranslator.java | 11 +- ...BedrockInventoryTransactionTranslator.java | 93 ++++++++++------ .../inventory/AnvilInventoryTranslator.java | 60 ++++++++++ ...tor.java => BlockInventoryTranslator.java} | 25 ++--- .../BrewingStandInventoryTranslator.java | 100 +++++++++++++++++ .../ContainerInventoryTranslator.java | 103 ++++++++++++++++++ .../DispenserInventoryTranslator.java | 99 ----------------- .../DoubleChestInventoryTranslator.java | 34 +----- .../EnchantmentInventoryTranslator.java | 41 +++++++ .../inventory/FurnaceInventoryTranslator.java | 59 +--------- .../inventory/InventoryTranslator.java | 56 +--------- .../inventory/PlayerInventoryTranslator.java | 5 + .../SingleChestInventoryTranslator.java | 68 +----------- 14 files changed, 421 insertions(+), 353 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java rename connector/src/main/java/org/geysermc/connector/network/translators/inventory/{HopperInventoryTranslator.java => BlockInventoryTranslator.java} (89%) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingStandInventoryTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/ContainerInventoryTranslator.java delete mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/DispenserInventoryTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/EnchantmentInventoryTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java index 46c13d3d..3e5af466 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java @@ -43,6 +43,7 @@ import com.nukkitx.nbt.CompoundTagBuilder; import com.nukkitx.nbt.NbtUtils; import com.nukkitx.nbt.stream.NBTOutputStream; import com.nukkitx.nbt.tag.CompoundTag; +import com.nukkitx.protocol.bedrock.data.ContainerType; import com.nukkitx.protocol.bedrock.packet.*; import lombok.Getter; import org.geysermc.connector.network.translators.bedrock.*; @@ -169,10 +170,19 @@ public class TranslatorsInit { inventoryTranslators.put(WindowType.GENERIC_9X4, new DoubleChestInventoryTranslator(36)); inventoryTranslators.put(WindowType.GENERIC_9X5, new DoubleChestInventoryTranslator(45)); inventoryTranslators.put(WindowType.GENERIC_9X6, new DoubleChestInventoryTranslator(54)); - inventoryTranslators.put(WindowType.GENERIC_3X3, new DispenserInventoryTranslator()); - inventoryTranslators.put(WindowType.HOPPER, new HopperInventoryTranslator()); - inventoryTranslators.put(WindowType.FURNACE, new FurnaceInventoryTranslator()); - inventoryTranslators.put(WindowType.BLAST_FURNACE, new FurnaceInventoryTranslator()); - inventoryTranslators.put(WindowType.SMOKER, new FurnaceInventoryTranslator()); + inventoryTranslators.put(WindowType.BREWING_STAND, new BrewingStandInventoryTranslator()); + inventoryTranslators.put(WindowType.ANVIL, new AnvilInventoryTranslator()); + //inventoryTranslators.put(WindowType.ENCHANTMENT, new EnchantmentInventoryTranslator()); //TODO + + InventoryTranslator furnace = new FurnaceInventoryTranslator(); + inventoryTranslators.put(WindowType.FURNACE, furnace); + inventoryTranslators.put(WindowType.BLAST_FURNACE, furnace); + inventoryTranslators.put(WindowType.SMOKER, furnace); + + inventoryTranslators.put(WindowType.GENERIC_3X3, new BlockInventoryTranslator(9, 23 << 4, ContainerType.DISPENSER)); + inventoryTranslators.put(WindowType.HOPPER, new BlockInventoryTranslator(5, 154 << 4, ContainerType.HOPPER)); + inventoryTranslators.put(WindowType.SHULKER_BOX, new BlockInventoryTranslator(36, 205 << 4, ContainerType.CONTAINER)); + inventoryTranslators.put(WindowType.CRAFTING, new BlockInventoryTranslator(10, 58 << 4, ContainerType.WORKBENCH)); + //inventoryTranslators.put(WindowType.BEACON, new BlockInventoryTranslator(1, 138 << 4, ContainerType.BEACON)); //TODO } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockContainerCloseTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockContainerCloseTranslator.java index de6a9d8c..71cc9f0d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockContainerCloseTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockContainerCloseTranslator.java @@ -38,7 +38,16 @@ public class BedrockContainerCloseTranslator extends PacketTranslator actions = packet.getActions(); + if (inventory.getWindowType() == WindowType.ANVIL) { + InventoryAction anvilResult = null; + InventoryAction anvilInput = null; + for (InventoryAction action : packet.getActions()) { + if (action.getSource().getContainerId() == ContainerId.ANVIL_RESULT) { + anvilResult = action; + } else if (action.getSource().getContainerId() == ContainerId.CONTAINER_INPUT) { + anvilInput = action; + } + } + ItemData itemName = null; + if (anvilResult != null) { + itemName = anvilResult.getFromItem(); + actions = new ArrayList<>(2); + for (InventoryAction action : packet.getActions()) { //packet sent by client when grabbing anvil output needs useless actions stripped + if (!(action.getSource().getContainerId() == ContainerId.CONTAINER_INPUT || action.getSource().getContainerId() == ContainerId.ANVIL_MATERIAL)) { + actions.add(action); + } + } + } else if (anvilInput != null) { + itemName = anvilInput.getToItem(); + } + if (itemName != null) { + String rename; + com.nukkitx.nbt.tag.CompoundTag tag = itemName.getTag(); + if (tag != null) { + rename = tag.getAsCompound("display").getAsString("Name"); + } else { + rename = ""; + } + ClientRenameItemPacket renameItemPacket = new ClientRenameItemPacket(rename); + session.getDownstream().getSession().send(renameItemPacket); + } + } + + if (actions.size() == 2) { if (worldAction != null && worldAction.getSource().getFlag() == InventorySource.Flag.DROP_ITEM) { //find container action InventoryAction containerAction = null; - for (InventoryAction action : packet.getActions()) { - if (action.getSource().getType() == InventorySource.Type.CONTAINER || action.getSource().getType() == InventorySource.Type.UNTRACKED_INTERACTION_UI) { + for (InventoryAction action : actions) { + if (action != worldAction) { containerAction = action; break; } @@ -125,8 +154,8 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator p.getSource().getType() == InventorySource.Type.CONTAINER || p.getSource().getType() == InventorySource.Type.UNTRACKED_INTERACTION_UI)) { + } else { //either moving 1 item or swapping 2 slots (touchscreen or one slot shift click) InventoryAction fromAction; InventoryAction toAction; //find source slot - if (packet.getActions().get(0).getFromItem().getCount() > packet.getActions().get(0).getToItem().getCount()) { - fromAction = packet.getActions().get(0); - toAction = packet.getActions().get(1); + if (actions.get(0).getFromItem().getCount() > actions.get(0).getToItem().getCount()) { + fromAction = actions.get(0); + toAction = actions.get(1); } else { - fromAction = packet.getActions().get(1); - toAction = packet.getActions().get(0); + fromAction = actions.get(1); + toAction = actions.get(0); } int fromSlot = translator.bedrockSlotToJava(fromAction); int toSlot = translator.bedrockSlotToJava(toAction); @@ -211,18 +240,18 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator 2) { + } else if (actions.size() > 2) { //shift click or fill stack? ItemData firstItem; - if (packet.getActions().get(0).getFromItem().getId() != 0) { - firstItem = packet.getActions().get(0).getFromItem(); + if (actions.get(0).getFromItem().getId() != 0) { + firstItem = actions.get(0).getFromItem(); } else { - firstItem = packet.getActions().get(0).getToItem(); + firstItem = actions.get(0).getToItem(); } - List sourceActions = new ArrayList<>(packet.getActions().size()); - List destActions = new ArrayList<>(packet.getActions().size()); + List sourceActions = new ArrayList<>(actions.size()); + List destActions = new ArrayList<>(actions.size()); boolean sameItems = true; - for (InventoryAction action : packet.getActions()) { + for (InventoryAction action : actions) { if (action.getFromItem().getCount() > action.getToItem().getCount()) { if (!InventoryUtils.canCombine(action.getFromItem(), firstItem)) sameItems = false; @@ -238,7 +267,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator= 9 && action.getSlot() >= 9)) { //shift click not compatible with java edition. refresh inventory and abort diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java new file mode 100644 index 00000000..9c027dc2 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.inventory; + +import com.nukkitx.protocol.bedrock.data.ContainerId; +import com.nukkitx.protocol.bedrock.data.ContainerType; +import com.nukkitx.protocol.bedrock.data.InventoryAction; + +public class AnvilInventoryTranslator extends BlockInventoryTranslator { + public AnvilInventoryTranslator() { + super(3, 145 << 4, ContainerType.ANVIL); + } + + @Override + public int bedrockSlotToJava(InventoryAction action) { + int slotnum = action.getSlot(); + if (action.getSource().getContainerId() == ContainerId.INVENTORY) { + //hotbar + if (slotnum >= 9) { + return slotnum + this.size - 9; + } else { + return slotnum + this.size + 27; + } + } else { + if (action.getSource().getContainerId() == ContainerId.ANVIL_RESULT) { + return 2; + } else { + return slotnum; + } + } + } + + @Override + public boolean isOutputSlot(InventoryAction action) { + return action.getSource().getContainerId() == ContainerId.ANVIL_RESULT; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/HopperInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BlockInventoryTranslator.java similarity index 89% rename from connector/src/main/java/org/geysermc/connector/network/translators/inventory/HopperInventoryTranslator.java rename to connector/src/main/java/org/geysermc/connector/network/translators/inventory/BlockInventoryTranslator.java index cf877d0f..065d63dc 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/HopperInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BlockInventoryTranslator.java @@ -29,7 +29,6 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.nukkitx.math.vector.Vector3i; import com.nukkitx.nbt.tag.CompoundTag; import com.nukkitx.protocol.bedrock.data.ContainerType; -import com.nukkitx.protocol.bedrock.data.InventoryAction; import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; @@ -38,9 +37,14 @@ import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.block.BlockEntry; import org.geysermc.connector.world.GlobalBlockPalette; -public class HopperInventoryTranslator extends InventoryTranslator { - public HopperInventoryTranslator() { - super(5); +public class BlockInventoryTranslator extends ContainerInventoryTranslator { + protected final int blockId; + protected final ContainerType containerType; + + public BlockInventoryTranslator(int size, int blockId, ContainerType containerType) { + super(size); + this.blockId = blockId; + this.containerType = containerType; } @Override @@ -50,7 +54,7 @@ public class HopperInventoryTranslator extends InventoryTranslator { UpdateBlockPacket blockPacket = new UpdateBlockPacket(); blockPacket.setDataLayer(0); blockPacket.setBlockPosition(position); - blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(154 << 4)); //hopper + blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(blockId)); blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); session.getUpstream().sendPacket(blockPacket); inventory.setHolderPosition(position); @@ -70,7 +74,7 @@ public class HopperInventoryTranslator extends InventoryTranslator { public void openInventory(GeyserSession session, Inventory inventory) { ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket(); containerOpenPacket.setWindowId((byte) inventory.getId()); - containerOpenPacket.setType((byte) ContainerType.HOPPER.id()); + containerOpenPacket.setType((byte) containerType.id()); containerOpenPacket.setBlockPosition(inventory.getHolderPosition()); containerOpenPacket.setUniqueEntityId(inventory.getHolderId()); session.getUpstream().sendPacket(containerOpenPacket); @@ -87,13 +91,4 @@ public class HopperInventoryTranslator extends InventoryTranslator { blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(realBlock.getBedrockId() << 4 | realBlock.getBedrockData())); session.getUpstream().sendPacket(blockPacket); } - - @Override - public void updateProperty(GeyserSession session, Inventory inventory, int key, int value) { - } - - @Override - public boolean isOutputSlot(InventoryAction action) { - return false; - } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingStandInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingStandInventoryTranslator.java new file mode 100644 index 00000000..92eb4bc8 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingStandInventoryTranslator.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.inventory; + +import com.nukkitx.protocol.bedrock.data.ContainerId; +import com.nukkitx.protocol.bedrock.data.ContainerType; +import com.nukkitx.protocol.bedrock.data.InventoryAction; +import com.nukkitx.protocol.bedrock.packet.ContainerSetDataPacket; +import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.network.session.GeyserSession; + +public class BrewingStandInventoryTranslator extends BlockInventoryTranslator { + public BrewingStandInventoryTranslator() { + super(5, 117 << 4, ContainerType.BREWING_STAND); + } + + @Override + public void updateProperty(GeyserSession session, Inventory inventory, int key, int value) { + //bedrock protocol library is currently missing property mappings for windows. + ContainerSetDataPacket dataPacket = new ContainerSetDataPacket(); + dataPacket.setWindowId((byte) inventory.getId()); + switch (key) { + case 0: + dataPacket.setProperty(ContainerSetDataPacket.Property.BREWING_STAND_BREW_TIME); + break; + case 1: + dataPacket.setProperty(ContainerSetDataPacket.Property.BREWING_STAND_FUEL_AMOUNT); + break; + default: + return; + } + dataPacket.setValue((short) value); + session.getUpstream().sendPacket(dataPacket); + } + + @Override + public int bedrockSlotToJava(InventoryAction action) { + int slotnum = action.getSlot(); + if (action.getSource().getContainerId() == ContainerId.INVENTORY) { + //hotbar + if (slotnum >= 9) { + return slotnum + this.size - 9; + } else { + return slotnum + this.size + 27; + } + } else { + switch (slotnum) { + case 0: + return 3; + case 1: + return 0; + case 2: + return 1; + case 3: + return 2; + default: + return slotnum; + } + } + } + + @Override + public int javaSlotToBedrock(int slotnum) { + switch (slotnum) { + case 0: + return 1; + case 1: + return 2; + case 2: + return 3; + case 3: + return 0; + default: + return slotnum; + } + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/ContainerInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/ContainerInventoryTranslator.java new file mode 100644 index 00000000..5c3ae3c8 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/ContainerInventoryTranslator.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.inventory; + +import com.nukkitx.protocol.bedrock.data.ContainerId; +import com.nukkitx.protocol.bedrock.data.InventoryAction; +import com.nukkitx.protocol.bedrock.data.ItemData; +import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket; +import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; +import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.TranslatorsInit; + +public abstract class ContainerInventoryTranslator extends InventoryTranslator { + public ContainerInventoryTranslator(int size) { + super(size); + } + + @Override + public void updateInventory(GeyserSession session, Inventory inventory) { + ItemData[] bedrockItems = new ItemData[this.size]; + for (int i = 0; i < bedrockItems.length; i++) { + bedrockItems[javaSlotToBedrock(i)] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItems()[i]); + } + InventoryContentPacket contentPacket = new InventoryContentPacket(); + contentPacket.setContainerId(inventory.getId()); + contentPacket.setContents(bedrockItems); + session.getUpstream().sendPacket(contentPacket); + + Inventory playerInventory = session.getInventory(); + for (int i = 0; i < 36; i++) { + playerInventory.getItems()[i + 9] = inventory.getItems()[i + this.size]; + } + TranslatorsInit.getInventoryTranslators().get(playerInventory.getWindowType()).updateInventory(session, playerInventory); + } + + @Override + public void updateSlot(GeyserSession session, Inventory inventory, int slot) { + if (slot >= this.size) { + Inventory playerInventory = session.getInventory(); + playerInventory.getItems()[(slot + 9) - this.size] = inventory.getItem(slot); + TranslatorsInit.getInventoryTranslators().get(playerInventory.getWindowType()).updateSlot(session, playerInventory, (slot + 9) - this.size); + } else { + InventorySlotPacket slotPacket = new InventorySlotPacket(); + slotPacket.setContainerId(inventory.getId()); + slotPacket.setInventorySlot(javaSlotToBedrock(slot)); + slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItems()[slot])); + session.getUpstream().sendPacket(slotPacket); + } + } + + @Override + public void updateProperty(GeyserSession session, Inventory inventory, int key, int value) { + } + + @Override + public int bedrockSlotToJava(InventoryAction action) { + int slotnum = action.getSlot(); + if (action.getSource().getContainerId() == ContainerId.INVENTORY) { + //hotbar + if (slotnum >= 9) { + return slotnum + this.size - 9; + } else { + return slotnum + this.size + 27; + } + } else { + return slotnum; + } + } + + @Override + public int javaSlotToBedrock(int slot) { + return slot; + } + + @Override + public boolean isOutputSlot(InventoryAction action) { + return false; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DispenserInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DispenserInventoryTranslator.java deleted file mode 100644 index 9f361f39..00000000 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DispenserInventoryTranslator.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2019 GeyserMC. http://geysermc.org - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * @author GeyserMC - * @link https://github.com/GeyserMC/Geyser - */ - -package org.geysermc.connector.network.translators.inventory; - -import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; -import com.nukkitx.math.vector.Vector3i; -import com.nukkitx.nbt.tag.CompoundTag; -import com.nukkitx.protocol.bedrock.data.ContainerType; -import com.nukkitx.protocol.bedrock.data.InventoryAction; -import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; -import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket; -import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; -import org.geysermc.connector.inventory.Inventory; -import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.block.BlockEntry; -import org.geysermc.connector.world.GlobalBlockPalette; - -public class DispenserInventoryTranslator extends InventoryTranslator { - public DispenserInventoryTranslator() { - super(9); - } - - @Override - public void prepareInventory(GeyserSession session, Inventory inventory) { - Vector3i position = session.getPlayerEntity().getPosition().toInt(); - position = position.add(Vector3i.UP); - UpdateBlockPacket blockPacket = new UpdateBlockPacket(); - blockPacket.setDataLayer(0); - blockPacket.setBlockPosition(position); - blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(23 << 4)); //dispenser - blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); - session.getUpstream().sendPacket(blockPacket); - inventory.setHolderPosition(position); - - CompoundTag tag = CompoundTag.EMPTY.toBuilder() - .intTag("x", position.getX()) - .intTag("y", position.getY()) - .intTag("z", position.getZ()) - .stringTag("CustomName", inventory.getTitle()).buildRootTag(); - BlockEntityDataPacket dataPacket = new BlockEntityDataPacket(); - dataPacket.setData(tag); - dataPacket.setBlockPosition(position); - session.getUpstream().sendPacket(dataPacket); - } - - @Override - public void openInventory(GeyserSession session, Inventory inventory) { - ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket(); - containerOpenPacket.setWindowId((byte) inventory.getId()); - containerOpenPacket.setType((byte) ContainerType.DISPENSER.id()); - containerOpenPacket.setBlockPosition(inventory.getHolderPosition()); - containerOpenPacket.setUniqueEntityId(inventory.getHolderId()); - session.getUpstream().sendPacket(containerOpenPacket); - } - - @Override - public void closeInventory(GeyserSession session, Inventory inventory) { - Vector3i holderPos = inventory.getHolderPosition(); - Position pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ()); - BlockEntry realBlock = session.getChunkCache().getBlockAt(pos); - UpdateBlockPacket blockPacket = new UpdateBlockPacket(); - blockPacket.setDataLayer(0); - blockPacket.setBlockPosition(holderPos); - blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(realBlock.getBedrockId() << 4 | realBlock.getBedrockData())); - session.getUpstream().sendPacket(blockPacket); - } - - @Override - public void updateProperty(GeyserSession session, Inventory inventory, int key, int value) { - } - - @Override - public boolean isOutputSlot(InventoryAction action) { - return false; - } -} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java index d52e9447..4b90ba07 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java @@ -29,10 +29,8 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.nukkitx.math.vector.Vector3i; import com.nukkitx.nbt.tag.CompoundTag; import com.nukkitx.protocol.bedrock.data.ContainerType; -import com.nukkitx.protocol.bedrock.data.InventoryAction; import com.nukkitx.protocol.bedrock.data.ItemData; import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; -import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket; import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.connector.inventory.Inventory; @@ -41,9 +39,9 @@ import org.geysermc.connector.network.translators.TranslatorsInit; import org.geysermc.connector.network.translators.block.BlockEntry; import org.geysermc.connector.world.GlobalBlockPalette; -public class DoubleChestInventoryTranslator extends InventoryTranslator { +public class DoubleChestInventoryTranslator extends BlockInventoryTranslator { public DoubleChestInventoryTranslator(int size) { - super(size); + super(size, 54 << 4, ContainerType.CONTAINER); } @Override @@ -53,7 +51,7 @@ public class DoubleChestInventoryTranslator extends InventoryTranslator { UpdateBlockPacket blockPacket = new UpdateBlockPacket(); blockPacket.setDataLayer(0); blockPacket.setBlockPosition(position); - blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(54 << 4)); //chest + blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(blockId)); blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); session.getUpstream().sendPacket(blockPacket); @@ -73,7 +71,7 @@ public class DoubleChestInventoryTranslator extends InventoryTranslator { blockPacket = new UpdateBlockPacket(); blockPacket.setDataLayer(0); blockPacket.setBlockPosition(pairPosition); - blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(54 << 4)); + blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(blockId)); blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); session.getUpstream().sendPacket(blockPacket); @@ -93,16 +91,6 @@ public class DoubleChestInventoryTranslator extends InventoryTranslator { inventory.setHolderPosition(position); } - @Override - public void openInventory(GeyserSession session, Inventory inventory) { - ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket(); - containerOpenPacket.setWindowId((byte) inventory.getId()); - containerOpenPacket.setType((byte) ContainerType.CONTAINER.id()); - containerOpenPacket.setBlockPosition(inventory.getHolderPosition()); - containerOpenPacket.setUniqueEntityId(inventory.getHolderId()); - session.getUpstream().sendPacket(containerOpenPacket); - } - @Override public void closeInventory(GeyserSession session, Inventory inventory) { Vector3i holderPos = inventory.getHolderPosition(); @@ -124,15 +112,10 @@ public class DoubleChestInventoryTranslator extends InventoryTranslator { session.getUpstream().sendPacket(blockPacket); } - @Override - public void updateProperty(GeyserSession session, Inventory inventory, int key, int value) { - } - @Override public void updateInventory(GeyserSession session, Inventory inventory) { - //need to pad empty slots for 4x9, and 5x9 - final int paddedSize = 54; - ItemData[] bedrockItems = new ItemData[paddedSize]; + //need to pad empty slots for 4x9 and 5x9 + ItemData[] bedrockItems = new ItemData[54]; for (int i = 0; i < bedrockItems.length; i++) { if (i <= this.size) { bedrockItems[i] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItems()[i]); @@ -151,9 +134,4 @@ public class DoubleChestInventoryTranslator extends InventoryTranslator { } TranslatorsInit.getInventoryTranslators().get(playerInventory.getWindowType()).updateInventory(session, playerInventory); } - - @Override - public boolean isOutputSlot(InventoryAction action) { - return false; - } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/EnchantmentInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/EnchantmentInventoryTranslator.java new file mode 100644 index 00000000..410bdc6a --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/EnchantmentInventoryTranslator.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.inventory; + +import com.nukkitx.protocol.bedrock.data.ContainerType; +import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.network.session.GeyserSession; + +public class EnchantmentInventoryTranslator extends BlockInventoryTranslator { + public EnchantmentInventoryTranslator() { + super(2, 116 << 4, ContainerType.ENCHANTMENT); + } + + @Override + public void updateProperty(GeyserSession session, Inventory inventory, int key, int value) { + + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java index c65fca02..c5296d37 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java @@ -25,56 +25,15 @@ package org.geysermc.connector.network.translators.inventory; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; -import com.nukkitx.math.vector.Vector3i; -import com.nukkitx.nbt.tag.CompoundTag; -import com.nukkitx.protocol.bedrock.data.ContainerId; import com.nukkitx.protocol.bedrock.data.ContainerType; import com.nukkitx.protocol.bedrock.data.InventoryAction; -import com.nukkitx.protocol.bedrock.data.ItemData; -import com.nukkitx.protocol.bedrock.packet.*; +import com.nukkitx.protocol.bedrock.packet.ContainerSetDataPacket; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.TranslatorsInit; -import org.geysermc.connector.network.translators.block.BlockEntry; -import org.geysermc.connector.world.GlobalBlockPalette; -public class FurnaceInventoryTranslator extends InventoryTranslator { +public class FurnaceInventoryTranslator extends BlockInventoryTranslator { public FurnaceInventoryTranslator() { - super(3); - } - - @Override - public void prepareInventory(GeyserSession session, Inventory inventory) { - Vector3i position = session.getPlayerEntity().getPosition().toInt(); - position = position.add(Vector3i.UP); - UpdateBlockPacket blockPacket = new UpdateBlockPacket(); - blockPacket.setDataLayer(0); - blockPacket.setBlockPosition(position); - blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(61 << 4)); //furnace - blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); - session.getUpstream().sendPacket(blockPacket); - inventory.setHolderPosition(position); - - CompoundTag tag = CompoundTag.EMPTY.toBuilder() - .intTag("x", position.getX()) - .intTag("y", position.getY()) - .intTag("z", position.getZ()) - .stringTag("CustomName", inventory.getTitle()).buildRootTag(); - BlockEntityDataPacket dataPacket = new BlockEntityDataPacket(); - dataPacket.setData(tag); - dataPacket.setBlockPosition(position); - session.getUpstream().sendPacket(dataPacket); - } - - @Override - public void openInventory(GeyserSession session, Inventory inventory) { - ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket(); - containerOpenPacket.setWindowId((byte) inventory.getId()); - containerOpenPacket.setType((byte) ContainerType.FURNACE.id()); - containerOpenPacket.setBlockPosition(inventory.getHolderPosition()); - containerOpenPacket.setUniqueEntityId(inventory.getHolderId()); - session.getUpstream().sendPacket(containerOpenPacket); + super(3, 61 << 4, ContainerType.FURNACE); } @Override @@ -99,18 +58,6 @@ public class FurnaceInventoryTranslator extends InventoryTranslator { session.getUpstream().sendPacket(dataPacket); } - @Override - public void closeInventory(GeyserSession session, Inventory inventory) { - Vector3i holderPos = inventory.getHolderPosition(); - Position pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ()); - BlockEntry realBlock = session.getChunkCache().getBlockAt(pos); - UpdateBlockPacket blockPacket = new UpdateBlockPacket(); - blockPacket.setDataLayer(0); - blockPacket.setBlockPosition(holderPos); - blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(realBlock.getBedrockId() << 4 | realBlock.getBedrockData())); - session.getUpstream().sendPacket(blockPacket); - } - @Override public boolean isOutputSlot(InventoryAction action) { return action.getSlot() == 2; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java index 5a31a040..7181a345 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java @@ -25,15 +25,9 @@ package org.geysermc.connector.network.translators.inventory; -import com.nukkitx.protocol.bedrock.data.ContainerId; import com.nukkitx.protocol.bedrock.data.InventoryAction; -import com.nukkitx.protocol.bedrock.data.ItemData; -import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket; -import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import org.geysermc.connector.inventory.Inventory; -import org.geysermc.connector.inventory.PlayerInventory; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.TranslatorsInit; public abstract class InventoryTranslator { public final int size; @@ -46,51 +40,9 @@ public abstract class InventoryTranslator { public abstract void openInventory(GeyserSession session, Inventory inventory); public abstract void closeInventory(GeyserSession session, Inventory inventory); public abstract void updateProperty(GeyserSession session, Inventory inventory, int key, int value); - - public void updateInventory(GeyserSession session, Inventory inventory) { - ItemData[] bedrockItems = new ItemData[this.size]; - for (int i = 0; i < bedrockItems.length; i++) { - bedrockItems[i] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItems()[i]); - } - InventoryContentPacket contentPacket = new InventoryContentPacket(); - contentPacket.setContainerId(inventory.getId()); - contentPacket.setContents(bedrockItems); - session.getUpstream().sendPacket(contentPacket); - - Inventory playerInventory = session.getInventory(); - for (int i = 0; i < 36; i++) { - playerInventory.getItems()[i + 9] = inventory.getItems()[i + this.size]; - } - TranslatorsInit.getInventoryTranslators().get(playerInventory.getWindowType()).updateInventory(session, playerInventory); - } - - public void updateSlot(GeyserSession session, Inventory inventory, int slot) { - if (slot >= this.size) { - Inventory playerInventory = session.getInventory(); - playerInventory.getItems()[(slot + 9) - this.size] = inventory.getItem(slot); - TranslatorsInit.getInventoryTranslators().get(playerInventory.getWindowType()).updateSlot(session, playerInventory, (slot + 9) - this.size); - } else { - InventorySlotPacket slotPacket = new InventorySlotPacket(); - slotPacket.setContainerId(inventory.getId()); - slotPacket.setInventorySlot(slot); - slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItems()[slot])); - session.getUpstream().sendPacket(slotPacket); - } - } - - public int bedrockSlotToJava(InventoryAction action) { - int slotnum = action.getSlot(); - if (action.getSource().getContainerId() == ContainerId.INVENTORY) { - //hotbar - if (slotnum >= 9) { - return slotnum + this.size - 9; - } else { - return slotnum + this.size + 27; - } - } else { - return slotnum; - } - } - + public abstract void updateInventory(GeyserSession session, Inventory inventory); + public abstract void updateSlot(GeyserSession session, Inventory inventory, int slot); + public abstract int bedrockSlotToJava(InventoryAction action); + public abstract int javaSlotToBedrock(int slot); public abstract boolean isOutputSlot(InventoryAction action); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java index 53244a9f..cfd92699 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java @@ -128,6 +128,11 @@ public class PlayerInventoryTranslator extends InventoryTranslator { return slotnum; } + @Override + public int javaSlotToBedrock(int slot) { + return slot; + } + @Override public boolean isOutputSlot(InventoryAction action) { return false; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java index ef8f97cc..43ceb283 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java @@ -25,79 +25,22 @@ package org.geysermc.connector.network.translators.inventory; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; -import com.nukkitx.math.vector.Vector3i; -import com.nukkitx.nbt.tag.CompoundTag; -import com.nukkitx.protocol.bedrock.data.ContainerId; import com.nukkitx.protocol.bedrock.data.ContainerType; -import com.nukkitx.protocol.bedrock.data.InventoryAction; import com.nukkitx.protocol.bedrock.data.ItemData; import com.nukkitx.protocol.bedrock.packet.*; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.TranslatorsInit; -import org.geysermc.connector.network.translators.block.BlockEntry; -import org.geysermc.connector.world.GlobalBlockPalette; -public class SingleChestInventoryTranslator extends InventoryTranslator { +public class SingleChestInventoryTranslator extends BlockInventoryTranslator { public SingleChestInventoryTranslator(int size) { - super(size); - } - - @Override - public void prepareInventory(GeyserSession session, Inventory inventory) { - Vector3i position = session.getPlayerEntity().getPosition().toInt(); - position = position.add(Vector3i.UP); - UpdateBlockPacket blockPacket = new UpdateBlockPacket(); - blockPacket.setDataLayer(0); - blockPacket.setBlockPosition(position); - blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(54 << 4)); //chest - blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); - session.getUpstream().sendPacket(blockPacket); - inventory.setHolderPosition(position); - - CompoundTag tag = CompoundTag.EMPTY.toBuilder() - .intTag("x", position.getX()) - .intTag("y", position.getY()) - .intTag("z", position.getZ()) - .stringTag("CustomName", inventory.getTitle()).buildRootTag(); - BlockEntityDataPacket dataPacket = new BlockEntityDataPacket(); - dataPacket.setData(tag); - dataPacket.setBlockPosition(position); - session.getUpstream().sendPacket(dataPacket); - } - - @Override - public void openInventory(GeyserSession session, Inventory inventory) { - ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket(); - containerOpenPacket.setWindowId((byte) inventory.getId()); - containerOpenPacket.setType((byte) ContainerType.CONTAINER.id()); - containerOpenPacket.setBlockPosition(inventory.getHolderPosition()); - containerOpenPacket.setUniqueEntityId(inventory.getHolderId()); - session.getUpstream().sendPacket(containerOpenPacket); - } - - @Override - public void closeInventory(GeyserSession session, Inventory inventory) { - Vector3i holderPos = inventory.getHolderPosition(); - Position pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ()); - BlockEntry realBlock = session.getChunkCache().getBlockAt(pos); - UpdateBlockPacket blockPacket = new UpdateBlockPacket(); - blockPacket.setDataLayer(0); - blockPacket.setBlockPosition(holderPos); - blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(realBlock.getBedrockId() << 4 | realBlock.getBedrockData())); - session.getUpstream().sendPacket(blockPacket); - } - - @Override - public void updateProperty(GeyserSession session, Inventory inventory, int key, int value) { + super(size, 54 << 4, ContainerType.CONTAINER); } @Override public void updateInventory(GeyserSession session, Inventory inventory) { //need to pad empty slots for 1x9 and 2x9 - final int paddedSize = 27; - ItemData[] bedrockItems = new ItemData[paddedSize]; + ItemData[] bedrockItems = new ItemData[27]; for (int i = 0; i < bedrockItems.length; i++) { if (i <= this.size) { bedrockItems[i] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItems()[i]); @@ -116,9 +59,4 @@ public class SingleChestInventoryTranslator extends InventoryTranslator { } TranslatorsInit.getInventoryTranslators().get(playerInventory.getWindowType()).updateInventory(session, playerInventory); } - - @Override - public boolean isOutputSlot(InventoryAction action) { - return false; - } } From 2d36a8b43bf285374f03b4382431c67cf7631cfa Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Sat, 9 Nov 2019 17:20:47 -0900 Subject: [PATCH 013/109] Begin adding support for creative Still need to complete item mappings --- .../network/session/GeyserSession.java | 8 +++- .../network/translators/TranslatorsInit.java | 2 +- ...BedrockInventoryTransactionTranslator.java | 37 ++++++++++++++++++ .../CraftingTableInventoryTranslator.java | 33 ++++++++++++++++ .../org/geysermc/connector/utils/Toolbox.java | 38 ++++++++++++++++++- 5 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingTableInventoryTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index 63b8a7e9..da98c62a 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -29,7 +29,6 @@ import com.github.steveice10.mc.auth.data.GameProfile; import com.github.steveice10.mc.auth.exception.request.RequestException; import com.github.steveice10.mc.protocol.MinecraftProtocol; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockFace; import com.github.steveice10.packetlib.Client; import com.github.steveice10.packetlib.event.session.ConnectedEvent; import com.github.steveice10.packetlib.event.session.DisconnectedEvent; @@ -42,8 +41,10 @@ import com.nukkitx.math.vector.Vector2i; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3i; import com.nukkitx.protocol.bedrock.BedrockServerSession; +import com.nukkitx.protocol.bedrock.data.ContainerId; import com.nukkitx.protocol.bedrock.data.GamePublishSetting; import com.nukkitx.protocol.bedrock.data.GameRule; +import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket; import com.nukkitx.protocol.bedrock.packet.PlayStatusPacket; import com.nukkitx.protocol.bedrock.packet.StartGamePacket; import com.nukkitx.protocol.bedrock.packet.TextPacket; @@ -311,5 +312,10 @@ public class GeyserSession implements Player { PlayStatusPacket playStatusPacket = new PlayStatusPacket(); playStatusPacket.setStatus(PlayStatusPacket.Status.PLAYER_SPAWN); upstream.sendPacket(playStatusPacket); + + InventoryContentPacket creativePacket = new InventoryContentPacket(); + creativePacket.setContainerId(ContainerId.CREATIVE); + creativePacket.setContents(Toolbox.CREATIVE_ITEMS); + upstream.sendPacket(creativePacket); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java index 3e5af466..7a07d4bc 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java @@ -172,6 +172,7 @@ public class TranslatorsInit { inventoryTranslators.put(WindowType.GENERIC_9X6, new DoubleChestInventoryTranslator(54)); inventoryTranslators.put(WindowType.BREWING_STAND, new BrewingStandInventoryTranslator()); inventoryTranslators.put(WindowType.ANVIL, new AnvilInventoryTranslator()); + inventoryTranslators.put(WindowType.CRAFTING, new CraftingTableInventoryTranslator()); //inventoryTranslators.put(WindowType.ENCHANTMENT, new EnchantmentInventoryTranslator()); //TODO InventoryTranslator furnace = new FurnaceInventoryTranslator(); @@ -182,7 +183,6 @@ public class TranslatorsInit { inventoryTranslators.put(WindowType.GENERIC_3X3, new BlockInventoryTranslator(9, 23 << 4, ContainerType.DISPENSER)); inventoryTranslators.put(WindowType.HOPPER, new BlockInventoryTranslator(5, 154 << 4, ContainerType.HOPPER)); inventoryTranslators.put(WindowType.SHULKER_BOX, new BlockInventoryTranslator(36, 205 << 4, ContainerType.CONTAINER)); - inventoryTranslators.put(WindowType.CRAFTING, new BlockInventoryTranslator(10, 58 << 4, ContainerType.WORKBENCH)); //inventoryTranslators.put(WindowType.BEACON, new BlockInventoryTranslator(1, 138 << 4, ContainerType.BEACON)); //TODO } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java index bf2dd7bc..d2f94164 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java @@ -26,6 +26,7 @@ package org.geysermc.connector.network.translators.bedrock; import com.github.steveice10.mc.protocol.data.game.window.*; +import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientCreativeInventoryActionPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientRenameItemPacket; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.nukkitx.math.vector.Vector3f; @@ -69,6 +70,42 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator ITEMS; public static final ByteBuf CACHED_PALLETE; + public static final ItemData[] CREATIVE_ITEMS; public static final TIntObjectMap ITEM_ENTRIES; public static final TIntObjectMap BLOCK_ENTRIES; @@ -116,5 +120,37 @@ public class Toolbox { } BLOCK_ENTRIES = blockEntries; + + InputStream creativeItemStream = Toolbox.class.getClassLoader().getResourceAsStream("bedrock/creative_items.json"); + ObjectMapper creativeItemMapper = new ObjectMapper(); + List> creativeItemEntries = new ArrayList<>(); + + try { + creativeItemEntries = creativeItemMapper.readValue(creativeItemStream, ArrayList.class); + } catch (Exception e) { + e.printStackTrace(); + } + + List creativeItems = new ArrayList<>(); + for (Map map : creativeItemEntries) { + short damage = 0; + if (map.containsKey("damage")) { + damage = (short)(int) map.get("damage"); + } + if (map.containsKey("nbt_b64")) { + byte[] bytes = DatatypeConverter.parseBase64Binary((String) map.get("nbt_b64")); + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + try { + com.nukkitx.nbt.tag.CompoundTag tag = (com.nukkitx.nbt.tag.CompoundTag) NbtUtils.createReaderLE(bais).readTag(); + creativeItems.add(ItemData.of((int) map.get("id"), damage, 1, tag)); + } catch (IOException e) { + e.printStackTrace(); + } + } else { + creativeItems.add(ItemData.of((int) map.get("id"), damage, 1)); + } + } + + CREATIVE_ITEMS = creativeItems.toArray(new ItemData[0]); } } \ No newline at end of file From ce68e1442a4f233dd0287084d2b1bb2051af97ac Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Wed, 27 Nov 2019 18:14:38 -0600 Subject: [PATCH 014/109] Start work on block entities (partially-functioning) Most block entities should now *show up*. Some like signs will not as of yet, however when another player places one, they will display. Block entities are not yet fully functional and may only just be visible for the time being. --- .../network/translators/TranslatorsInit.java | 15 ++++ .../block/entity/BlockEntityTranslator.java | 73 ++++++++++++++++++ .../entity/EmptyBlockEntityTranslator.java | 50 ++++++++++++ .../entity/SignBlockEntityTranslator.java | 77 +++++++++++++++++++ .../java/world/JavaChunkDataTranslator.java | 12 +++ .../world/JavaUpdateTileEntityTranslator.java | 51 ++++++++++++ .../connector/utils/BlockEntityUtils.java | 32 ++++++++ .../geysermc/connector/utils/ChunkUtils.java | 34 +++++++- 8 files changed, 343 insertions(+), 1 deletion(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java index 6539fb05..8e3728e6 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java @@ -48,6 +48,9 @@ import com.nukkitx.protocol.bedrock.packet.*; import lombok.Getter; import org.geysermc.connector.network.translators.bedrock.*; import org.geysermc.connector.network.translators.block.BlockTranslator; +import org.geysermc.connector.network.translators.block.entity.BlockEntityTranslator; +import org.geysermc.connector.network.translators.block.entity.EmptyBlockEntityTranslator; +import org.geysermc.connector.network.translators.block.entity.SignBlockEntityTranslator; import org.geysermc.connector.network.translators.inventory.GenericInventoryTranslator; import org.geysermc.connector.network.translators.inventory.InventoryTranslator; import org.geysermc.connector.network.translators.item.ItemTranslator; @@ -67,6 +70,8 @@ import org.geysermc.connector.network.translators.java.world.*; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.util.HashMap; +import java.util.Map; public class TranslatorsInit { @@ -79,6 +84,9 @@ public class TranslatorsInit { @Getter private static InventoryTranslator inventoryTranslator = new GenericInventoryTranslator(); + @Getter + private static Map blockEntityTranslators = new HashMap<>(); + private static final CompoundTag EMPTY_TAG = CompoundTagBuilder.builder().buildRootTag(); public static final byte[] EMPTY_LEVEL_CHUNK_DATA; @@ -143,6 +151,7 @@ public class TranslatorsInit { Registry.registerJava(ServerBlockChangePacket.class, new JavaBlockChangeTranslator()); Registry.registerJava(ServerMultiBlockChangePacket.class, new JavaMultiBlockChangeTranslator()); Registry.registerJava(ServerUnloadChunkPacket.class, new JavaUnloadChunkTranslator()); + Registry.registerJava(ServerUpdateTileEntityPacket.class, new JavaUpdateTileEntityTranslator()); Registry.registerJava(ServerOpenWindowPacket.class, new OpenWindowPacketTranslator()); @@ -159,9 +168,15 @@ public class TranslatorsInit { itemTranslator = new ItemTranslator(); blockTranslator = new BlockTranslator(); + registerBlockEntityTranslators(); registerInventoryTranslators(); } + private static void registerBlockEntityTranslators() { + blockEntityTranslators.put("Empty", new EmptyBlockEntityTranslator()); + blockEntityTranslators.put("Sign", new SignBlockEntityTranslator()); + } + private static void registerInventoryTranslators() { /*inventoryTranslators.put(WindowType.GENERIC_9X1, new GenericInventoryTranslator()); inventoryTranslators.put(WindowType.GENERIC_9X2, new GenericInventoryTranslator()); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java new file mode 100644 index 00000000..4913a300 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.block.entity; + +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.IntTag; +import com.github.steveice10.opennbt.tag.builtin.StringTag; +import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.tag.Tag; +import org.geysermc.connector.utils.BlockEntityUtils; + +import java.util.List; + +public abstract class BlockEntityTranslator { + + public abstract List> translateTag(CompoundTag tag); + + public abstract CompoundTag getDefaultJavaTag(int x, int y, int z); + + public abstract com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(int x, int y, int z); + + public com.nukkitx.nbt.tag.CompoundTag getBlockEntityTag(CompoundTag tag) { + String id = BlockEntityUtils.getBedrockBlockEntityId((String) tag.get("id").getValue()); + int x = Integer.parseInt(String.valueOf(tag.getValue().get("x").getValue())); + int y = Integer.parseInt(String.valueOf(tag.getValue().get("y").getValue())); + int z = Integer.parseInt(String.valueOf(tag.getValue().get("z").getValue())); + + CompoundTagBuilder tagBuilder = getConstantBedrockTag(id, x, y, z).toBuilder(); + translateTag(tag).forEach(tagBuilder::tag); + return tagBuilder.buildRootTag(); + } + + protected CompoundTag getConstantJavaTag(String id, int x, int y, int z) { + CompoundTag tag = new CompoundTag(""); + tag.put(new IntTag("x", x)); + tag.put(new IntTag("y", y)); + tag.put(new IntTag("z", z)); + tag.put(new StringTag("id", id)); + return tag; + } + + protected com.nukkitx.nbt.tag.CompoundTag getConstantBedrockTag(String id, int x, int y, int z) { + CompoundTagBuilder tagBuilder = CompoundTagBuilder.builder() + .intTag("x", x) + .intTag("y", y) + .intTag("z", z) + .stringTag("id", id); + return tagBuilder.buildRootTag(); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java new file mode 100644 index 00000000..927337bc --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.block.entity; + +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.nukkitx.nbt.tag.Tag; + +import java.util.ArrayList; +import java.util.List; + +public class EmptyBlockEntityTranslator extends BlockEntityTranslator { + + @Override + public List> translateTag(CompoundTag tag) { + return new ArrayList<>(); + } + + @Override + public CompoundTag getDefaultJavaTag(int x, int y, int z) { + return getConstantJavaTag("empty", x, y, z); + } + + @Override + public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(int x, int y, int z) { + return getConstantBedrockTag("Empty", x, y, z); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java new file mode 100644 index 00000000..414455c7 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.block.entity; + +import com.github.steveice10.mc.protocol.data.message.Message; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.tag.ByteTag; +import com.nukkitx.nbt.tag.StringTag; +import com.nukkitx.nbt.tag.Tag; +import org.geysermc.connector.utils.MessageUtils; + +import java.util.ArrayList; +import java.util.List; + +public class SignBlockEntityTranslator extends BlockEntityTranslator { + + @Override + public List> translateTag(CompoundTag tag) { + List> tags = new ArrayList<>(); + + String line1 = (String) tag.getValue().get("Text1").getValue(); + String line2 = (String) tag.getValue().get("Text2").getValue(); + String line3 = (String) tag.getValue().get("Text3").getValue(); + String line4 = (String) tag.getValue().get("Text4").getValue(); + + tags.add(new StringTag("Text", MessageUtils.getBedrockMessage(Message.fromString(line1)) + + "\n" + MessageUtils.getBedrockMessage(Message.fromString(line2)) + + "\n" + MessageUtils.getBedrockMessage(Message.fromString(line3)) + + "\n" + MessageUtils.getBedrockMessage(Message.fromString(line4)) + )); + + tags.add(new ByteTag("isMovable", (byte) 0)); + return tags; + } + + @Override + public CompoundTag getDefaultJavaTag(int x, int y, int z) { + CompoundTag tag = getConstantJavaTag("minecraft:sign", x, y, z); + tag.put(new com.github.steveice10.opennbt.tag.builtin.StringTag("Text1", "\"text\":\"\"")); + tag.put(new com.github.steveice10.opennbt.tag.builtin.StringTag("Text2", "\"text\":\"\"")); + tag.put(new com.github.steveice10.opennbt.tag.builtin.StringTag("Text3", "\"text\":\"\"")); + tag.put(new com.github.steveice10.opennbt.tag.builtin.StringTag("Text4", "\"text\":\"\"")); + return tag; + } + + @Override + public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(int x, int y, int z) { + CompoundTagBuilder tagBuilder = getConstantBedrockTag("Sign", x, y, z).toBuilder(); + tagBuilder.stringTag("Text", ""); + tagBuilder.byteTag("isMovable", (byte) 0); + return tagBuilder.buildRootTag(); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java index a620197e..1c83579a 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java @@ -3,10 +3,14 @@ package org.geysermc.connector.network.translators.java.world; import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerChunkDataPacket; import com.nukkitx.math.vector.Vector2i; import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.nbt.NbtUtils; +import com.nukkitx.nbt.stream.NBTOutputStream; +import com.nukkitx.nbt.tag.CompoundTag; import com.nukkitx.network.VarInts; import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket; import com.nukkitx.protocol.bedrock.packet.NetworkChunkPublisherUpdatePacket; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufOutputStream; import io.netty.buffer.Unpooled; import org.geysermc.api.Geyser; import org.geysermc.connector.network.session.GeyserSession; @@ -53,6 +57,14 @@ public class JavaChunkDataTranslator extends PacketTranslator { + + @Override + public void translate(ServerUpdateTileEntityPacket packet, GeyserSession session) { + BlockEntityDataPacket blockEntityPacket = new BlockEntityDataPacket(); + blockEntityPacket.setBlockPosition(Vector3i.from(packet.getPosition().getX(), + packet.getPosition().getY(), + packet.getPosition().getZ()) + ); + + String id = BlockEntityUtils.getBedrockBlockEntityId(packet.getType().name()); + BlockEntityTranslator translator = BlockEntityUtils.getBlockEntityTranslator(id); + blockEntityPacket.setData(translator.getBlockEntityTag(packet.getNbt())); + session.getUpstream().sendPacket(blockEntityPacket); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java new file mode 100644 index 00000000..6fb62b55 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java @@ -0,0 +1,32 @@ +package org.geysermc.connector.utils; + +import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.block.entity.BlockEntityTranslator; + +public class BlockEntityUtils { + + public static String getBedrockBlockEntityId(String id) { + // This is the only exception when it comes to block entity ids + if (id.contains("piston_head")) + return "PistonArm"; + + id = id.replace("minecraft:", ""); + id = id.replace("_", " "); + String[] words = id.split(" "); + for (int i = 0; i < words.length; i++) { + words[i] = words[i].substring(0, 1).toUpperCase() + words[i].substring(1).toLowerCase(); + } + + id = String.join(" ", words); + return id.replace(" ", ""); + } + + public static BlockEntityTranslator getBlockEntityTranslator(String name) { + BlockEntityTranslator blockEntityTranslator = TranslatorsInit.getBlockEntityTranslators().get(name); + if (blockEntityTranslator == null) { + return TranslatorsInit.getBlockEntityTranslators().get("Empty"); + } + + return blockEntityTranslator; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java index 6f2b6d3c..59a5fe84 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -3,10 +3,19 @@ package org.geysermc.connector.utils; import com.github.steveice10.mc.protocol.data.game.chunk.Chunk; import com.github.steveice10.mc.protocol.data.game.chunk.Column; import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.Tag; +import org.geysermc.connector.console.GeyserLogger; import org.geysermc.connector.network.translators.TranslatorsInit; import org.geysermc.connector.network.translators.block.BlockEntry; +import org.geysermc.connector.network.translators.block.entity.BlockEntityTranslator; +import org.geysermc.connector.network.translators.block.entity.SignBlockEntityTranslator; import org.geysermc.connector.world.chunk.ChunkSection; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + public class ChunkUtils { public static ChunkData translateToBedrock(Column column) { @@ -16,6 +25,7 @@ public class ChunkUtils { int chunkSectionCount = chunks.length; chunkData.sections = new ChunkSection[chunkSectionCount]; + List blockEntities = new ArrayList<>(Arrays.asList(column.getTileEntities())); for (int chunkY = 0; chunkY < chunkSectionCount; chunkY++) { chunkData.sections[chunkY] = new ChunkSection(); Chunk chunk = chunks[chunkY]; @@ -38,10 +48,32 @@ public class ChunkUtils { section.getBlockStorageArray()[1].setFullBlock(ChunkSection.blockPosition(x, y, z), 9 << 4); // water id } + + // Block entity data for signs is not sent in this packet, which is needed + // for bedrock, so we need to check the block itself + if (block.getJavaIdentifier().contains("sign")) { + SignBlockEntityTranslator sign = (SignBlockEntityTranslator) BlockEntityUtils.getBlockEntityTranslator("Sign"); + blockEntities.add(sign.getDefaultJavaTag(x, y, z)); + } } } } } + + List bedrockBlockEntities = new ArrayList<>(); + for (CompoundTag tag : blockEntities) { + Tag idTag = tag.get("id"); + if (idTag == null) { + GeyserLogger.DEFAULT.debug("Got tag with no id: " + tag.getValue()); + continue; + } + + String id = BlockEntityUtils.getBedrockBlockEntityId((String) tag.get("id").getValue()); + BlockEntityTranslator blockEntityTranslator = BlockEntityUtils.getBlockEntityTranslator(id); + bedrockBlockEntities.add(blockEntityTranslator.getBlockEntityTag(tag)); + } + + chunkData.blockEntities = bedrockBlockEntities; return chunkData; } @@ -49,6 +81,6 @@ public class ChunkUtils { public ChunkSection[] sections; public byte[] biomes = new byte[256]; - public byte[] blockEntities = new byte[0]; + public List blockEntities = new ArrayList<>(); } } From 489c39e900c9b5478325267c62c00ae5fdb45ff3 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Wed, 27 Nov 2019 18:55:58 -0900 Subject: [PATCH 015/109] Start adding support for crafting Expect bugs --- .../connector/inventory/Inventory.java | 7 +- .../connector/inventory/PlayerInventory.java | 2 +- .../network/session/GeyserSession.java | 4 +- .../network/translators/TranslatorsInit.java | 3 +- ...BedrockInventoryTransactionTranslator.java | 472 ++++++++++++------ .../inventory/AnvilInventoryTranslator.java | 4 +- .../ContainerInventoryTranslator.java | 10 +- .../CraftingTableInventoryTranslator.java | 22 + .../DoubleChestInventoryTranslator.java | 4 +- .../inventory/FurnaceInventoryTranslator.java | 4 +- .../inventory/InventoryTranslator.java | 2 +- .../inventory/PlayerInventoryTranslator.java | 14 +- .../SingleChestInventoryTranslator.java | 4 +- .../java/JavaDeclareRecipesTranslator.java | 149 ++++++ .../java/window/JavaSetSlotTranslator.java | 9 +- .../connector/utils/InventoryUtils.java | 13 +- 16 files changed, 541 insertions(+), 182 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java b/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java index 2147b070..24ec4a3c 100644 --- a/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java +++ b/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java @@ -52,7 +52,6 @@ public class Inventory { @Setter protected String title; - @Getter @Setter protected ItemStack[] items; @@ -82,4 +81,10 @@ public class Inventory { public ItemStack getItem(int slot) { return items[slot]; } + + public void setItem(int slot, ItemStack item) { + if (item != null && (item.getId() == 0 || item.getAmount() < 1)) + item = null; + items[slot] = item; + } } diff --git a/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java b/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java index 4fd3bcd8..a11ce856 100644 --- a/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java +++ b/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java @@ -44,7 +44,7 @@ public class PlayerInventory extends Inventory { } public void setCursor(ItemStack stack) { - if (stack != null && stack.getId() == 0) + if (stack != null && (stack.getId() == 0 || stack.getAmount() < 1)) stack = null; cursor = stack; } diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index da8aaa20..1e410134 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -105,11 +105,9 @@ public class GeyserSession implements Player { @Setter private GameMode gameMode = GameMode.SURVIVAL; - @Getter @Setter - private int lastClickedSlot; + private int craftSlot = 0; - @Getter @Setter private int reopeningWindow = -1; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java index 535faf5c..ba7e3a97 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java @@ -99,6 +99,7 @@ public class TranslatorsInit { Registry.registerJava(ServerRespawnPacket.class, new JavaRespawnTranslator()); Registry.registerJava(ServerSpawnPositionPacket.class, new JavaSpawnPositionTranslator()); Registry.registerJava(ServerDifficultyPacket.class, new JavaDifficultyTranslator()); + Registry.registerJava(ServerDeclareRecipesPacket.class, new JavaDeclareRecipesTranslator()); Registry.registerJava(ServerEntityAnimationPacket.class, new JavaEntityAnimationTranslator()); Registry.registerJava(ServerEntityPositionPacket.class, new JavaEntityPositionTranslator()); @@ -181,7 +182,7 @@ public class TranslatorsInit { inventoryTranslators.put(WindowType.GENERIC_3X3, new BlockInventoryTranslator(9, 23 << 4, ContainerType.DISPENSER)); inventoryTranslators.put(WindowType.HOPPER, new BlockInventoryTranslator(5, 154 << 4, ContainerType.HOPPER)); - inventoryTranslators.put(WindowType.SHULKER_BOX, new BlockInventoryTranslator(36, 205 << 4, ContainerType.CONTAINER)); + inventoryTranslators.put(WindowType.SHULKER_BOX, new BlockInventoryTranslator(27, 205 << 4, ContainerType.CONTAINER)); //inventoryTranslators.put(WindowType.BEACON, new BlockInventoryTranslator(1, 138 << 4, ContainerType.BEACON)); //TODO } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java index d2f94164..27dd19ca 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java @@ -26,6 +26,7 @@ package org.geysermc.connector.network.translators.bedrock; import com.github.steveice10.mc.protocol.data.game.window.*; +import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientConfirmTransactionPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientCreativeInventoryActionPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientRenameItemPacket; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; @@ -49,27 +50,36 @@ import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import com.nukkitx.protocol.bedrock.packet.InventoryTransactionPacket; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.inventory.PlayerInventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.TranslatorsInit; import org.geysermc.connector.network.translators.inventory.InventoryTranslator; -import org.geysermc.connector.utils.InventoryUtils; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; +import java.util.*; public class BedrockInventoryTransactionTranslator extends PacketTranslator { + private final ItemStack refreshItem = new ItemStack(1, 127, new CompoundTag("")); @Override public void translate(InventoryTransactionPacket packet, GeyserSession session) { switch (packet.getTransactionType()) { case NORMAL: + for (InventoryAction action : packet.getActions()) { + if (action.getSource().getContainerId() == ContainerId.CRAFTING_USE_INGREDIENT || + action.getSource().getContainerId() == ContainerId.CRAFTING_RESULT) { + return; + } + } + Inventory inventory = session.getInventoryCache().getOpenInventory(); if (inventory == null) inventory = session.getInventory(); InventoryTranslator translator = TranslatorsInit.getInventoryTranslators().get(inventory.getWindowType()); + int craftSlot = session.getCraftSlot(); + session.setCraftSlot(0); + if (session.getGameMode() == GameMode.CREATIVE && inventory.getId() == 0) { ItemStack javaItem; for (InventoryAction action : packet.getActions()) { @@ -87,17 +97,18 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator actions = packet.getActions(); if (inventory.getWindowType() == WindowType.ANVIL) { InventoryAction anvilResult = null; @@ -132,7 +142,8 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator(2); for (InventoryAction action : packet.getActions()) { //packet sent by client when grabbing anvil output needs useless actions stripped - if (!(action.getSource().getContainerId() == ContainerId.CONTAINER_INPUT || action.getSource().getContainerId() == ContainerId.ANVIL_MATERIAL)) { + if (!(action.getSource().getContainerId() == ContainerId.CONTAINER_INPUT || + action.getSource().getContainerId() == ContainerId.ANVIL_MATERIAL)) { actions.add(action); } } @@ -153,7 +164,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator 1 ? ClickItemParam.LEFT_CLICK : ClickItemParam.RIGHT_CLICK); session.getDownstream().getSession().send(dropPacket); + ItemStack cursor = session.getInventory().getCursor(); + if (cursor != null) { + session.getInventory().setCursor(new ItemStack(cursor.getId(), dropAmount > 1 ? 0 : cursor.getAmount() - 1, cursor.getNbt())); + } return; } } @@ -199,43 +234,81 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator cursorAction.getFromItem().getCount()) { //fill stack - int javaSlot = session.getLastClickedSlot(); - ClientWindowActionPacket fillStackPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getTransactionId().getAndIncrement(), - javaSlot, null, WindowAction.FILL_STACK, FillStackParam.FILL); - session.getDownstream().getSession().send(fillStackPacket); - translator.updateInventory(session, inventory); //bedrock fill stack can sometimes differ from java version, refresh and let server change slots - return; - } else { - //left/right click - int javaSlot = translator.bedrockSlotToJava(containerAction); - boolean rightClick; - if (cursorAction.getFromItem().getCount() == 0) { //picking up item - rightClick = containerAction.getToItem().getCount() != 0; - } else { //releasing item - rightClick = cursorAction.getToItem().getCount() != 0 && cursorAction.getFromItem().getCount() - cursorAction.getToItem().getCount() == 1; + //left/right click + List plan = new ArrayList<>(); + ItemStack translatedCursor = TranslatorsInit.getItemTranslator().translateToJava(cursorAction.getFromItem()); + boolean refresh = !Objects.equals(session.getInventory().getCursor(), translatedCursor.getId() == 0 ? null : translatedCursor); //refresh slot if there is a cursor mismatch + int javaSlot = translator.bedrockSlotToJava(containerAction); + if (cursorAction.getFromItem().equals(containerAction.getToItem()) && + containerAction.getFromItem().equals(cursorAction.getToItem()) && + !canStack(cursorAction.getFromItem(), containerAction.getFromItem())) { //simple swap + Click.LEFT.onSlot(javaSlot, plan); + } else if (cursorAction.getFromItem().getCount() > cursorAction.getToItem().getCount()) { //release + if (cursorAction.getToItem().getCount() == 0) { + Click.LEFT.onSlot(javaSlot, plan); + } else { + int difference = cursorAction.getFromItem().getCount() - cursorAction.getToItem().getCount(); + for (int i = 0; i < difference; i++) { + Click.RIGHT.onSlot(javaSlot, plan); + } + } + } else { //pickup + if (cursorAction.getFromItem().getCount() == 0) { + if (containerAction.getToItem().getCount() == 0) { //pickup all + Click.LEFT.onSlot(javaSlot, plan); + } else { //pickup some + if (translator.isOutputSlot(javaSlot) || + containerAction.getToItem().getCount() == containerAction.getFromItem().getCount() / 2) { //right click + Click.RIGHT.onSlot(javaSlot, plan); + } else { + Click.LEFT.onSlot(javaSlot, plan); + int difference = containerAction.getFromItem().getCount() - cursorAction.getToItem().getCount(); + for (int i = 0; i < difference; i++) { + Click.RIGHT.onSlot(javaSlot, plan); + } + } + } + } else { //pickup into non-empty cursor + if (translator.isOutputSlot(javaSlot)) { + if (containerAction.getToItem().getCount() == 0) { + Click.LEFT.onSlot(javaSlot, plan); + } else { + ClientWindowActionPacket shiftClickPacket = new ClientWindowActionPacket(inventory.getId(), + inventory.getTransactionId().getAndIncrement(), + javaSlot, refreshItem, WindowAction.SHIFT_CLICK_ITEM, + ShiftClickItemParam.LEFT_CLICK); + session.getDownstream().getSession().send(shiftClickPacket); + translator.updateInventory(session, inventory); + return; + } + } else if ((inventory.getId() == 0 || inventory.getWindowType() == WindowType.CRAFTING) && javaSlot == 0) { //crafting output + Click.LEFT.onSlot(javaSlot, plan); + } else { + int cursorSlot = findTempSlot(inventory, session.getInventory().getCursor(), Collections.singletonList(javaSlot)); + if (cursorSlot != -1) { + Click.LEFT.onSlot(cursorSlot, plan); + } else { + translator.updateInventory(session, inventory); + return; + } + Click.LEFT.onSlot(javaSlot, plan); + int difference = cursorAction.getToItem().getCount() - cursorAction.getFromItem().getCount(); + for (int i = 0; i < difference; i++) { + Click.RIGHT.onSlot(cursorSlot, plan); + } + Click.LEFT.onSlot(javaSlot, plan); + Click.LEFT.onSlot(cursorSlot, plan); + } } - ItemStack translatedCursor = TranslatorsInit.getItemTranslator().translateToJava(cursorAction.getFromItem()); - boolean refresh = !Objects.equals(session.getInventory().getCursor(), translatedCursor.getId() == 0 ? null : translatedCursor); //refresh slot if there is a cursor mismatch - ClientWindowActionPacket clickPacket = new ClientWindowActionPacket(inventory.getId(), - inventory.getTransactionId().getAndIncrement(), javaSlot, - refresh ? new ItemStack(1, 127, new CompoundTag("")) : InventoryUtils.fixStack(TranslatorsInit.getItemTranslator().translateToJava(containerAction.getFromItem())), //send invalid item stack to refresh slot - WindowAction.CLICK_ITEM, rightClick ? ClickItemParam.RIGHT_CLICK : ClickItemParam.LEFT_CLICK); - session.getDownstream().getSession().send(clickPacket); - inventory.getItems()[javaSlot] = TranslatorsInit.getItemTranslator().translateToJava(containerAction.getToItem()); - translator.updateSlot(session, inventory, javaSlot); - session.getInventory().setCursor(TranslatorsInit.getItemTranslator().translateToJava(cursorAction.getToItem())); - session.setLastClickedSlot(javaSlot); - return; } + executePlan(session, inventory, translator, plan, refresh); + return; } } else { - //either moving 1 item or swapping 2 slots (touchscreen or one slot shift click) + List plan = new ArrayList<>(); InventoryAction fromAction; InventoryAction toAction; - //find source slot - if (actions.get(0).getFromItem().getCount() > actions.get(0).getToItem().getCount()) { + if (actions.get(0).getFromItem().getCount() >= actions.get(0).getToItem().getCount()) { fromAction = actions.get(0); toAction = actions.get(1); } else { @@ -245,120 +318,93 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator 2) { - //shift click or fill stack? - ItemData firstItem; - if (actions.get(0).getFromItem().getId() != 0) { - firstItem = actions.get(0).getFromItem(); - } else { - firstItem = actions.get(0).getToItem(); - } - List sourceActions = new ArrayList<>(actions.size()); - List destActions = new ArrayList<>(actions.size()); - boolean sameItems = true; - for (InventoryAction action : actions) { - if (action.getFromItem().getCount() > action.getToItem().getCount()) { - if (!InventoryUtils.canCombine(action.getFromItem(), firstItem)) - sameItems = false; - sourceActions.add(action); - } else { - if (!InventoryUtils.canCombine(action.getToItem(), firstItem)) - sameItems = false; - destActions.add(action); - } - } - if (sameItems) { - if (sourceActions.size() == 1) { //shift click - InventoryAction sourceAction = sourceActions.get(0); - //in java edition, shift clicked item must move across hotbar and main inventory - if (sourceAction.getSource().getContainerId() == ContainerId.INVENTORY) { - for (InventoryAction action : actions) { - if (action != sourceAction && action.getSource().getContainerId() == ContainerId.INVENTORY) { - if ((sourceAction.getSlot() < 9 && action.getSlot() < 9) || (sourceAction.getSlot() >= 9 && action.getSlot() >= 9)) { - //shift click not compatible with java edition. refresh inventory and abort - translator.updateInventory(session, inventory); - return; - } + if ((inventory.getId() == 0 || inventory.getWindowType() == WindowType.CRAFTING) && fromSlot == 0) { + if ((craftSlot != 0 && craftSlot != -2) && (inventory.getItem(toSlot) == null || + canStack(session.getInventory().getCursor(), inventory.getItem(toSlot)))) { + boolean refresh = false; + if (fromAction.getToItem().getCount() == 0) { + refresh = true; + Click.LEFT.onSlot(toSlot, plan); + if (craftSlot != -1) { + Click.LEFT.onSlot(craftSlot, plan); } + } else { + int difference = toAction.getToItem().getCount() - toAction.getFromItem().getCount(); + for (int i = 0; i < difference; i++) { + Click.RIGHT.onSlot(toSlot, plan); + } + session.setCraftSlot(craftSlot); } - } - int javaSlot = translator.bedrockSlotToJava(sourceAction); - ClientWindowActionPacket shiftClickPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getTransactionId().getAndIncrement(), - javaSlot, InventoryUtils.fixStack(inventory.getItem(javaSlot)), WindowAction.SHIFT_CLICK_ITEM, ShiftClickItemParam.LEFT_CLICK); - session.getDownstream().getSession().send(shiftClickPacket); - return; - } else if (destActions.size() == 1) { //fill stack - InventoryAction destAction = destActions.get(0); - int javaSlot; - if (destAction != cursorAction) { //if touchscreen - javaSlot = translator.bedrockSlotToJava(destAction); - ClientWindowActionPacket leftClickPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getTransactionId().getAndIncrement(), - javaSlot, InventoryUtils.fixStack(inventory.getItem(javaSlot)), WindowAction.CLICK_ITEM, ClickItemParam.LEFT_CLICK); - session.getDownstream().getSession().send(leftClickPacket); + executePlan(session, inventory, translator, plan, refresh); + return; } else { - javaSlot = session.getLastClickedSlot(); + session.setCraftSlot(-2); } - ClientWindowActionPacket fillStackPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getTransactionId().getAndIncrement(), - javaSlot, null, WindowAction.FILL_STACK, FillStackParam.FILL); - session.getDownstream().getSession().send(fillStackPacket); - if (destAction != cursorAction) { //if touchscreen - ClientWindowActionPacket leftClickPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getTransactionId().getAndIncrement(), - javaSlot, null, WindowAction.CLICK_ITEM, ClickItemParam.LEFT_CLICK); - session.getDownstream().getSession().send(leftClickPacket); - inventory.getItems()[javaSlot] = TranslatorsInit.getItemTranslator().translateToJava(destAction.getToItem()); - } - translator.updateInventory(session, inventory); - return; } + + int cursorSlot = -1; + if (session.getInventory().getCursor() != null) { //move cursor contents to a temporary slot + cursorSlot = findTempSlot(inventory, session.getInventory().getCursor(), Arrays.asList(fromSlot, toSlot)); + if (cursorSlot != -1) { + Click.LEFT.onSlot(cursorSlot, plan); + } else { + translator.updateInventory(session, inventory); + return; + } + } + if ((fromAction.getFromItem().equals(toAction.getToItem()) && !canStack(fromAction.getFromItem(), toAction.getFromItem())) || fromAction.getToItem().getId() == 0) { //slot swap + Click.LEFT.onSlot(fromSlot, plan); + Click.LEFT.onSlot(toSlot, plan); + if (fromAction.getToItem().getId() != 0) { + Click.LEFT.onSlot(fromSlot, plan); + } + } else if (canStack(fromAction.getFromItem(), toAction.getToItem())) { //partial item move + if (translator.isOutputSlot(fromSlot)) { + ClientWindowActionPacket shiftClickPacket = new ClientWindowActionPacket(inventory.getId(), + inventory.getTransactionId().getAndIncrement(), + fromSlot, refreshItem, WindowAction.SHIFT_CLICK_ITEM, + ShiftClickItemParam.LEFT_CLICK); + session.getDownstream().getSession().send(shiftClickPacket); + translator.updateInventory(session, inventory); + return; + } else if ((inventory.getId() == 0 || inventory.getWindowType() == WindowType.CRAFTING) && fromSlot == 0) { + session.setCraftSlot(cursorSlot); + Click.LEFT.onSlot(fromSlot, plan); + int difference = toAction.getToItem().getCount() - toAction.getFromItem().getCount(); + for (int i = 0; i < difference; i++) { + Click.RIGHT.onSlot(toSlot, plan); + } + //client will send additional packets later to finish transferring crafting output + //translator will know how to handle this using the craftSlot variable + } else { + Click.LEFT.onSlot(fromSlot, plan); + int difference = toAction.getToItem().getCount() - toAction.getFromItem().getCount(); + for (int i = 0; i < difference; i++) { + Click.RIGHT.onSlot(toSlot, plan); + } + Click.LEFT.onSlot(fromSlot, plan); + } + } + if (cursorSlot != -1) { + Click.LEFT.onSlot(cursorSlot, plan); + } + executePlan(session, inventory, translator, plan, false); + return; } } - - //refresh inventory, transaction was not translated translator.updateInventory(session, inventory); break; case INVENTORY_MISMATCH: InventorySlotPacket cursorPacket = new InventorySlotPacket(); cursorPacket.setContainerId(ContainerId.CURSOR); cursorPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(session.getInventory().getCursor())); - session.getUpstream().sendPacket(cursorPacket); + //session.getUpstream().sendPacket(cursorPacket); Inventory inv = session.getInventoryCache().getOpenInventory(); if (inv == null) inv = session.getInventory(); TranslatorsInit.getInventoryTranslators().get(inv.getWindowType()).updateInventory(session, inv); + break; case ITEM_USE: if (packet.getActionType() == 1) { ClientPlayerUseItemPacket useItemPacket = new ClientPlayerUseItemPacket(Hand.MAIN_HAND); @@ -389,4 +435,134 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator slotBlacklist) { + /*try and find a slot that can temporarily store the given item + only look in the main inventory and hotbar + only slots that are empty or contain a different type of item are valid*/ + int offset = inventory.getId() == 0 ? 1 : 0; //offhand is not a viable slot (some servers disable it) + List itemBlacklist = new ArrayList<>(slotBlacklist.size() + 1); + itemBlacklist.add(item); + for (int slot : slotBlacklist) { + ItemStack blacklistItem = inventory.getItem(slot); + if (blacklistItem != null) + itemBlacklist.add(blacklistItem); + } + for (int i = inventory.getSize() - (36 + offset); i < inventory.getSize() - offset; i++) { + ItemStack testItem = inventory.getItem(i); + boolean acceptable = true; + if (testItem != null) { + for (ItemStack blacklistItem : itemBlacklist) { + if (canStack(testItem, blacklistItem)) { + acceptable = false; + break; + } + } + } + if (acceptable && !slotBlacklist.contains(i)) + return i; + } + //could not find a viable temp slot + return -1; + } + + //NPE if compound tag is null + private ItemStack fixStack(ItemStack stack) { + if (stack == null || stack.getId() == 0) + return null; + return new ItemStack(stack.getId(), stack.getAmount(), stack.getNbt() == null ? new CompoundTag("") : stack.getNbt()); + } + + private boolean canStack(ItemStack item1, ItemStack item2) { + if (item1 == null || item2 == null) + return false; + return item1.getId() == item2.getId() && item1.getNbt() == item2.getNbt(); + } + + private boolean canStack(ItemData item1, ItemData item2) { + if (item1 == null || item2 == null) + return false; + return item1.equals(item2, false, true, true); + } + + private void executePlan(GeyserSession session, Inventory inventory, InventoryTranslator translator, List plan, boolean refresh) { + PlayerInventory playerInventory = session.getInventory(); + ListIterator planIter = plan.listIterator(); + while (planIter.hasNext()) { + ClickAction action = planIter.next(); + ItemStack cursorItem = playerInventory.getCursor(); + ItemStack clickedItem = inventory.getItem(action.slot); + short actionId = (short) inventory.getTransactionId().getAndIncrement(); + boolean craftingOutput = (inventory.getId() == 0 || inventory.getWindowType() == WindowType.CRAFTING) && action.slot == 0; + if (craftingOutput) + refresh = true; + ClientWindowActionPacket clickPacket = new ClientWindowActionPacket(inventory.getId(), + actionId, action.slot, !planIter.hasNext() && refresh ? refreshItem : fixStack(clickedItem), + WindowAction.CLICK_ITEM, action.click.actionParam); + if (craftingOutput) { //crafting output + if (cursorItem == null && clickedItem != null) { + playerInventory.setCursor(clickedItem); + } else if (canStack(cursorItem, clickedItem)) { + playerInventory.setCursor(new ItemStack(cursorItem.getId(), + cursorItem.getAmount() + clickedItem.getAmount(), cursorItem.getNbt())); + } + } else { + switch (action.click) { + case LEFT: + if (!canStack(cursorItem, clickedItem)) { + playerInventory.setCursor(clickedItem); + inventory.setItem(action.slot, cursorItem); + } else { + playerInventory.setCursor(null); + inventory.setItem(action.slot, new ItemStack(clickedItem.getId(), + clickedItem.getAmount() + cursorItem.getAmount(), clickedItem.getNbt())); + } + break; + case RIGHT: + if (cursorItem == null && clickedItem != null) { + ItemStack halfItem = new ItemStack(clickedItem.getId(), + clickedItem.getAmount() / 2, clickedItem.getNbt()); + inventory.setItem(action.slot, halfItem); + playerInventory.setCursor(new ItemStack(clickedItem.getId(), + clickedItem.getAmount() - halfItem.getAmount(), clickedItem.getNbt())); + } else if (cursorItem != null && clickedItem == null) { + playerInventory.setCursor(new ItemStack(cursorItem.getId(), + cursorItem.getAmount() - 1, cursorItem.getNbt())); + inventory.setItem(action.slot, new ItemStack(cursorItem.getId(), + 1, cursorItem.getNbt())); + } else if (canStack(cursorItem, clickedItem)) { + playerInventory.setCursor(new ItemStack(cursorItem.getId(), + cursorItem.getAmount() - 1, cursorItem.getNbt())); + inventory.setItem(action.slot, new ItemStack(clickedItem.getId(), + clickedItem.getAmount() + 1, clickedItem.getNbt())); + } + break; + } + } + session.getDownstream().getSession().send(clickPacket); + session.getDownstream().getSession().send(new ClientConfirmTransactionPacket(inventory.getId(), actionId, true)); + } + } + + private enum Click { + LEFT(ClickItemParam.LEFT_CLICK), + RIGHT(ClickItemParam.RIGHT_CLICK); + + final WindowActionParam actionParam; + Click(WindowActionParam actionParam) { + this.actionParam = actionParam; + } + void onSlot(int slot, List plan) { + plan.add(new ClickAction(slot, this)); + } + } + + private static class ClickAction { + final int slot; + final Click click; + ClickAction(int slot, Click click) { + this.slot = slot; + this.click = click; + } + } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java index 9c027dc2..53750130 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java @@ -54,7 +54,7 @@ public class AnvilInventoryTranslator extends BlockInventoryTranslator { } @Override - public boolean isOutputSlot(InventoryAction action) { - return action.getSource().getContainerId() == ContainerId.ANVIL_RESULT; + public boolean isOutputSlot(int slot) { + return slot == 2; } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/ContainerInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/ContainerInventoryTranslator.java index 5c3ae3c8..22d73b9b 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/ContainerInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/ContainerInventoryTranslator.java @@ -43,7 +43,7 @@ public abstract class ContainerInventoryTranslator extends InventoryTranslator { public void updateInventory(GeyserSession session, Inventory inventory) { ItemData[] bedrockItems = new ItemData[this.size]; for (int i = 0; i < bedrockItems.length; i++) { - bedrockItems[javaSlotToBedrock(i)] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItems()[i]); + bedrockItems[javaSlotToBedrock(i)] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i)); } InventoryContentPacket contentPacket = new InventoryContentPacket(); contentPacket.setContainerId(inventory.getId()); @@ -52,7 +52,7 @@ public abstract class ContainerInventoryTranslator extends InventoryTranslator { Inventory playerInventory = session.getInventory(); for (int i = 0; i < 36; i++) { - playerInventory.getItems()[i + 9] = inventory.getItems()[i + this.size]; + playerInventory.setItem(i + 9, inventory.getItem(i + this.size)); } TranslatorsInit.getInventoryTranslators().get(playerInventory.getWindowType()).updateInventory(session, playerInventory); } @@ -61,13 +61,13 @@ public abstract class ContainerInventoryTranslator extends InventoryTranslator { public void updateSlot(GeyserSession session, Inventory inventory, int slot) { if (slot >= this.size) { Inventory playerInventory = session.getInventory(); - playerInventory.getItems()[(slot + 9) - this.size] = inventory.getItem(slot); + playerInventory.setItem((slot + 9) - this.size, inventory.getItem(slot)); TranslatorsInit.getInventoryTranslators().get(playerInventory.getWindowType()).updateSlot(session, playerInventory, (slot + 9) - this.size); } else { InventorySlotPacket slotPacket = new InventorySlotPacket(); slotPacket.setContainerId(inventory.getId()); slotPacket.setInventorySlot(javaSlotToBedrock(slot)); - slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItems()[slot])); + slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(slot))); session.getUpstream().sendPacket(slotPacket); } } @@ -97,7 +97,7 @@ public abstract class ContainerInventoryTranslator extends InventoryTranslator { } @Override - public boolean isOutputSlot(InventoryAction action) { + public boolean isOutputSlot(int slot) { return false; } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingTableInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingTableInventoryTranslator.java index e5f614f4..911fddc3 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingTableInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingTableInventoryTranslator.java @@ -1,7 +1,9 @@ package org.geysermc.connector.network.translators.inventory; import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.protocol.bedrock.data.ContainerId; import com.nukkitx.protocol.bedrock.data.ContainerType; +import com.nukkitx.protocol.bedrock.data.InventoryAction; import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; @@ -30,4 +32,24 @@ public class CraftingTableInventoryTranslator extends ContainerInventoryTranslat public void closeInventory(GeyserSession session, Inventory inventory) { } + + @Override + public int bedrockSlotToJava(InventoryAction action) { + int slotnum = action.getSlot(); + if (action.getSource().getContainerId() == ContainerId.INVENTORY) { + //hotbar + if (slotnum >= 9) { + return slotnum + this.size - 9; + } else { + return slotnum + this.size + 27; + } + } else { + if (slotnum >= 32 && 42 >= slotnum) { + return slotnum - 31; + } else if (slotnum == 50) { + return 0; + } + return slotnum; + } + } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java index 4b90ba07..6c5057bb 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java @@ -118,7 +118,7 @@ public class DoubleChestInventoryTranslator extends BlockInventoryTranslator { ItemData[] bedrockItems = new ItemData[54]; for (int i = 0; i < bedrockItems.length; i++) { if (i <= this.size) { - bedrockItems[i] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItems()[i]); + bedrockItems[i] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i)); } else { bedrockItems[i] = ItemData.AIR; } @@ -130,7 +130,7 @@ public class DoubleChestInventoryTranslator extends BlockInventoryTranslator { Inventory playerInventory = session.getInventory(); for (int i = 0; i < 36; i++) { - playerInventory.getItems()[i + 9] = inventory.getItems()[i + this.size]; + playerInventory.setItem(i + 9, inventory.getItem(i + this.size)); } TranslatorsInit.getInventoryTranslators().get(playerInventory.getWindowType()).updateInventory(session, playerInventory); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java index c5296d37..9c274c87 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java @@ -59,7 +59,7 @@ public class FurnaceInventoryTranslator extends BlockInventoryTranslator { } @Override - public boolean isOutputSlot(InventoryAction action) { - return action.getSlot() == 2; + public boolean isOutputSlot(int slot) { + return slot == 2; } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java index 7181a345..edc7f495 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java @@ -44,5 +44,5 @@ public abstract class InventoryTranslator { public abstract void updateSlot(GeyserSession session, Inventory inventory, int slot); public abstract int bedrockSlotToJava(InventoryAction action); public abstract int javaSlotToBedrock(int slot); - public abstract boolean isOutputSlot(InventoryAction action); + public abstract boolean isOutputSlot(int slot); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java index cfd92699..2608fd6c 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java @@ -45,12 +45,12 @@ public class PlayerInventoryTranslator extends InventoryTranslator { ItemData[] contents = new ItemData[36]; // Inventory for (int i = 9; i < 36; i++) { - contents[i] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItems()[i]); + contents[i] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i)); } // Hotbar for (int i = 36; i < 45; i++) { - contents[i - 36] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItems()[i]); + contents[i - 36] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i)); } inventoryContentPacket.setContents(contents); @@ -61,7 +61,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { armorContentPacket.setContainerId(ContainerId.ARMOR); contents = new ItemData[4]; for (int i = 5; i < 9; i++) { - contents[i - 5] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItems()[i]); + contents[i - 5] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i)); } armorContentPacket.setContents(contents); session.getUpstream().sendPacket(armorContentPacket); @@ -124,6 +124,12 @@ public class PlayerInventoryTranslator extends InventoryTranslator { case ContainerId.CRAFTING_ADD_INGREDIENT: case ContainerId.CRAFTING_REMOVE_INGREDIENT: return slotnum + 1; + case ContainerId.CURSOR: + if (slotnum >= 28 && 31 >= slotnum) { + return slotnum - 27; + } else if (slotnum == 50) { + return 0; + } } return slotnum; } @@ -134,7 +140,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { } @Override - public boolean isOutputSlot(InventoryAction action) { + public boolean isOutputSlot(int slot) { return false; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java index 43ceb283..3b2c70d9 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java @@ -43,7 +43,7 @@ public class SingleChestInventoryTranslator extends BlockInventoryTranslator { ItemData[] bedrockItems = new ItemData[27]; for (int i = 0; i < bedrockItems.length; i++) { if (i <= this.size) { - bedrockItems[i] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItems()[i]); + bedrockItems[i] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i)); } else { bedrockItems[i] = ItemData.AIR; } @@ -55,7 +55,7 @@ public class SingleChestInventoryTranslator extends BlockInventoryTranslator { Inventory playerInventory = session.getInventory(); for (int i = 0; i < 36; i++) { - playerInventory.getItems()[i + 9] = inventory.getItems()[i + this.size]; + playerInventory.setItem(i + 9, inventory.getItem(i + this.size)); } TranslatorsInit.getInventoryTranslators().get(playerInventory.getWindowType()).updateInventory(session, playerInventory); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java new file mode 100644 index 00000000..afa4836c --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.java; + +import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; +import com.github.steveice10.mc.protocol.data.game.recipe.Recipe; +import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapedRecipeData; +import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapelessRecipeData; +import com.github.steveice10.mc.protocol.packet.ingame.server.ServerDeclareRecipesPacket; +import com.nukkitx.nbt.tag.CompoundTag; +import com.nukkitx.protocol.bedrock.data.CraftingData; +import com.nukkitx.protocol.bedrock.data.ItemData; +import com.nukkitx.protocol.bedrock.packet.CraftingDataPacket; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.network.translators.TranslatorsInit; + +import java.util.*; +import java.util.stream.Collectors; + +public class JavaDeclareRecipesTranslator extends PacketTranslator { + + @Override + public void translate(ServerDeclareRecipesPacket packet, GeyserSession session) { + CraftingDataPacket craftingDataPacket = new CraftingDataPacket(); + craftingDataPacket.setCleanRecipes(true); + for (Recipe recipe : packet.getRecipes()) { + switch (recipe.getType()) { + case CRAFTING_SHAPELESS: { + ShapelessRecipeData shapelessRecipeData = (ShapelessRecipeData) recipe.getData(); + ItemData output = TranslatorsInit.getItemTranslator().translateToBedrock(shapelessRecipeData.getResult()); + List inputList = combinations(shapelessRecipeData.getIngredients()); + for (ItemData[] inputs : inputList) { + UUID uuid = UUID.randomUUID(); + craftingDataPacket.getCraftingData().add(CraftingData.fromShapeless(uuid.toString(), + inputs, new ItemData[]{output}, uuid, "crafting_table", 0)); + } + break; + } + case CRAFTING_SHAPED: { + ShapedRecipeData shapedRecipeData = (ShapedRecipeData) recipe.getData(); + ItemData output = TranslatorsInit.getItemTranslator().translateToBedrock(shapedRecipeData.getResult()); + List inputList = combinations(shapedRecipeData.getIngredients()); + for (ItemData[] inputs : inputList) { + UUID uuid = UUID.randomUUID(); + craftingDataPacket.getCraftingData().add(CraftingData.fromShaped(uuid.toString(), + shapedRecipeData.getWidth(), shapedRecipeData.getHeight(), inputs, + new ItemData[]{output}, uuid, "crafting_table", 0)); + } + break; + } + } + } + session.getUpstream().sendPacket(craftingDataPacket); + } + + private List combinations(Ingredient[] ingredients) { + ItemData[][] squashed = new ItemData[ingredients.length][]; + for (int i = 0; i < ingredients.length; i++) { + if (ingredients[i].getOptions().length == 0) { + squashed[i] = new ItemData[]{ItemData.AIR}; + continue; + } + Ingredient ingredient = ingredients[i]; + Map> groupedByIds = Arrays.stream(ingredient.getOptions()) + .map(item -> TranslatorsInit.getItemTranslator().translateToBedrock(item)) + .collect(Collectors.groupingBy(item -> new GroupedItem(item.getId(), item.getCount(), item.getTag()))); + squashed[i] = new ItemData[groupedByIds.size()]; + int index = 0; + for (Map.Entry> entry : groupedByIds.entrySet()) { + if (entry.getValue().size() > 1) { + GroupedItem groupedItem = entry.getKey(); + squashed[i][index++] = ItemData.of(groupedItem.id, (short) -1, groupedItem.count, groupedItem.tag); + } else { + ItemData item = entry.getValue().get(0); + squashed[i][index++] = item; + } + } + } + int[] sizeArray = new int[squashed.length]; + int[] counterArray = new int[squashed.length]; + int totalCombinationCount = 1; + for(int i = 0; i < squashed.length; i++) { + sizeArray[i] = squashed[i].length; + totalCombinationCount *= squashed[i].length; + } + if (totalCombinationCount > 10000) { + ItemData[] translatedItems = new ItemData[ingredients.length]; + for (int i = 0; i < ingredients.length; i++) { + if (ingredients[i].getOptions().length > 0) { + translatedItems[i] = TranslatorsInit.getItemTranslator().translateToBedrock(ingredients[i].getOptions()[0]); + } else { + translatedItems[i] = ItemData.AIR; + } + } + return Collections.singletonList(translatedItems); + } + List combinationList = new ArrayList<>(totalCombinationCount); + for (int countdown = totalCombinationCount; countdown > 0; --countdown) { + ItemData[] translatedItems = new ItemData[squashed.length]; + for(int i = 0; i < squashed.length; ++i) { + if (squashed[i].length > 0) + translatedItems[i] = squashed[i][counterArray[i]]; + } + combinationList.add(translatedItems); + for(int incIndex = squashed.length - 1; incIndex >= 0; --incIndex) { + if(counterArray[incIndex] + 1 < sizeArray[incIndex]) { + ++counterArray[incIndex]; + break; + } + counterArray[incIndex] = 0; + } + } + return combinationList; + } + + @EqualsAndHashCode + @AllArgsConstructor + private static class GroupedItem { + int id; + int count; + CompoundTag tag; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java index 562eb193..d658535f 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java @@ -47,9 +47,12 @@ public class JavaSetSlotTranslator extends PacketTranslator if (packet.getWindowId() == 255 && packet.getSlot() == -1) { //cursor if (Objects.equals(session.getInventory().getCursor(), packet.getItem())) return; + if (session.getCraftSlot() != 0) + return; //bedrock client is bugged when changing the cursor. reopen inventory after changing it - if (packet.getItem() == null && session.getInventory().getCursor() != null) { + //TODO: fix this. too buggy rn + /*if (packet.getItem() == null && session.getInventory().getCursor() != null) { InventorySlotPacket cursorPacket = new InventorySlotPacket(); cursorPacket.setContainerId(ContainerId.CURSOR); cursorPacket.setSlot(ItemData.AIR); @@ -64,7 +67,7 @@ public class JavaSetSlotTranslator extends PacketTranslator ContainerClosePacket closePacket = new ContainerClosePacket(); closePacket.setWindowId((byte) inventory.getId()); Geyser.getGeneralThreadPool().schedule(() -> session.getUpstream().sendPacket(closePacket), 150, TimeUnit.MILLISECONDS); - } + }*/ session.getInventory().setCursor(packet.getItem()); return; @@ -76,7 +79,7 @@ public class JavaSetSlotTranslator extends PacketTranslator InventoryTranslator translator = TranslatorsInit.getInventoryTranslators().get(inventory.getWindowType()); if (translator != null) { - inventory.getItems()[packet.getSlot()] = packet.getItem(); + inventory.setItem(packet.getSlot(), packet.getItem()); translator.updateSlot(session, inventory, packet.getSlot()); } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java b/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java index 86c38fe9..77c69eed 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java @@ -44,14 +44,13 @@ public class InventoryUtils { session.getInventoryCache().uncacheInventory(windowId); session.getInventoryCache().setOpenInventory(null); } + } else { + Inventory inventory = session.getInventory(); + InventoryTranslator translator = TranslatorsInit.getInventoryTranslators().get(inventory.getWindowType()); + translator.updateInventory(session, inventory); } - } - - //currently, ItemStack.equals() does not check the item id - public static boolean canCombine(ItemData stack1, ItemData stack2) { - if (stack1 == null || stack2 == null) - return false; - return stack1.getId() == stack2.getId() && stack1.equals(stack2, false, true, true); + session.setCraftSlot(0); + session.getInventory().setCursor(null); } //NPE if nbt tag is null From 8a589129f0912d456b97f897d0b3e6a4d71460cd Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Fri, 29 Nov 2019 02:16:52 -0900 Subject: [PATCH 016/109] Update crafting recipe combinations calculation --- .../java/JavaDeclareRecipesTranslator.java | 78 +++++++++++-------- 1 file changed, 45 insertions(+), 33 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java index afa4836c..cadafb01 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java @@ -39,6 +39,8 @@ import lombok.EqualsAndHashCode; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.item.ItemEntry; +import org.geysermc.connector.utils.Toolbox; import java.util.*; import java.util.stream.Collectors; @@ -54,8 +56,8 @@ public class JavaDeclareRecipesTranslator extends PacketTranslator inputList = combinations(shapelessRecipeData.getIngredients()); - for (ItemData[] inputs : inputList) { + ItemData[][] inputCombinations = combinations(shapelessRecipeData.getIngredients()); + for (ItemData[] inputs : inputCombinations) { UUID uuid = UUID.randomUUID(); craftingDataPacket.getCraftingData().add(CraftingData.fromShapeless(uuid.toString(), inputs, new ItemData[]{output}, uuid, "crafting_table", 0)); @@ -65,8 +67,8 @@ public class JavaDeclareRecipesTranslator extends PacketTranslator inputList = combinations(shapedRecipeData.getIngredients()); - for (ItemData[] inputs : inputList) { + ItemData[][] inputCombinations = combinations(shapedRecipeData.getIngredients()); + for (ItemData[] inputs : inputCombinations) { UUID uuid = UUID.randomUUID(); craftingDataPacket.getCraftingData().add(CraftingData.fromShaped(uuid.toString(), shapedRecipeData.getWidth(), shapedRecipeData.getHeight(), inputs, @@ -79,37 +81,45 @@ public class JavaDeclareRecipesTranslator extends PacketTranslator combinations(Ingredient[] ingredients) { - ItemData[][] squashed = new ItemData[ingredients.length][]; + private ItemData[][] combinations(Ingredient[] ingredients) { + Map, Set> squashedOptions = new HashMap<>(); for (int i = 0; i < ingredients.length; i++) { if (ingredients[i].getOptions().length == 0) { - squashed[i] = new ItemData[]{ItemData.AIR}; + squashedOptions.computeIfAbsent(Collections.singleton(ItemData.AIR), k -> new HashSet<>()).add(i); continue; } Ingredient ingredient = ingredients[i]; Map> groupedByIds = Arrays.stream(ingredient.getOptions()) .map(item -> TranslatorsInit.getItemTranslator().translateToBedrock(item)) .collect(Collectors.groupingBy(item -> new GroupedItem(item.getId(), item.getCount(), item.getTag()))); - squashed[i] = new ItemData[groupedByIds.size()]; - int index = 0; + Set optionSet = new HashSet<>(groupedByIds.size()); for (Map.Entry> entry : groupedByIds.entrySet()) { if (entry.getValue().size() > 1) { GroupedItem groupedItem = entry.getKey(); - squashed[i][index++] = ItemData.of(groupedItem.id, (short) -1, groupedItem.count, groupedItem.tag); + int idCount = 0; + //not optimal + for (ItemEntry itemEntry : Toolbox.ITEM_ENTRIES.valueCollection()) { + if (itemEntry.getBedrockId() == groupedItem.id) { + idCount++; + } + } + if (entry.getValue().size() < idCount) { + optionSet.addAll(entry.getValue()); + } else { + optionSet.add(ItemData.of(groupedItem.id, (short) -1, groupedItem.count, groupedItem.tag)); + } } else { ItemData item = entry.getValue().get(0); - squashed[i][index++] = item; + optionSet.add(item); } } + squashedOptions.computeIfAbsent(optionSet, k -> new HashSet<>()).add(i); } - int[] sizeArray = new int[squashed.length]; - int[] counterArray = new int[squashed.length]; - int totalCombinationCount = 1; - for(int i = 0; i < squashed.length; i++) { - sizeArray[i] = squashed[i].length; - totalCombinationCount *= squashed[i].length; + int totalCombinations = 1; + for (Set optionSet : squashedOptions.keySet()) { + totalCombinations *= optionSet.size(); } - if (totalCombinationCount > 10000) { + if (totalCombinations > 500) { ItemData[] translatedItems = new ItemData[ingredients.length]; for (int i = 0; i < ingredients.length; i++) { if (ingredients[i].getOptions().length > 0) { @@ -118,25 +128,27 @@ public class JavaDeclareRecipesTranslator extends PacketTranslator combinationList = new ArrayList<>(totalCombinationCount); - for (int countdown = totalCombinationCount; countdown > 0; --countdown) { - ItemData[] translatedItems = new ItemData[squashed.length]; - for(int i = 0; i < squashed.length; ++i) { - if (squashed[i].length > 0) - translatedItems[i] = squashed[i][counterArray[i]]; - } - combinationList.add(translatedItems); - for(int incIndex = squashed.length - 1; incIndex >= 0; --incIndex) { - if(counterArray[incIndex] + 1 < sizeArray[incIndex]) { - ++counterArray[incIndex]; - break; + List> sortedSets = new ArrayList<>(squashedOptions.keySet()); + sortedSets.sort(Comparator.comparing(Set::size, Comparator.reverseOrder())); + ItemData[][] combinations = new ItemData[totalCombinations][ingredients.length]; + int x = 1; + for (Set set : sortedSets) { + Set slotSet = squashedOptions.get(set); + int i = 0; + for (ItemData item : set) { + for (int j = 0; j < totalCombinations / set.size(); j++) { + final int comboIndex = (i * x) + (j % x) + ((j / x) * set.size() * x); + for (int slot : slotSet) { + combinations[comboIndex][slot] = item; + } } - counterArray[incIndex] = 0; + i++; } + x *= set.size(); } - return combinationList; + return combinations; } @EqualsAndHashCode From 24e5d34ce92a740b000bd4f7f91a374dc928c375 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Fri, 29 Nov 2019 15:49:29 -0900 Subject: [PATCH 017/109] Cleanup --- .../network/session/GeyserSession.java | 3 --- .../BedrockContainerCloseTranslator.java | 11 -------- .../CraftingTableInventoryTranslator.java | 26 +++++++++++++++++- .../inventory/PlayerInventoryTranslator.java | 2 -- .../translators/item/ItemTranslator.java | 2 +- .../java/window/JavaSetSlotTranslator.java | 27 +------------------ .../window/JavaWindowPropertyTranslator.java | 26 +++++++++++++++++- .../connector/utils/InventoryUtils.java | 13 --------- 8 files changed, 52 insertions(+), 58 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index 1e410134..71108d89 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -108,9 +108,6 @@ public class GeyserSession implements Player { @Setter private int craftSlot = 0; - @Setter - private int reopeningWindow = -1; - public GeyserSession(GeyserConnector connector, BedrockServerSession bedrockServerSession) { this.connector = connector; this.upstream = new UpstreamSession(bedrockServerSession); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockContainerCloseTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockContainerCloseTranslator.java index 71cc9f0d..01da6d5f 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockContainerCloseTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockContainerCloseTranslator.java @@ -47,17 +47,6 @@ public class BedrockContainerCloseTranslator extends PacketTranslator { @@ -49,26 +43,7 @@ public class JavaSetSlotTranslator extends PacketTranslator return; if (session.getCraftSlot() != 0) return; - - //bedrock client is bugged when changing the cursor. reopen inventory after changing it - //TODO: fix this. too buggy rn - /*if (packet.getItem() == null && session.getInventory().getCursor() != null) { - InventorySlotPacket cursorPacket = new InventorySlotPacket(); - cursorPacket.setContainerId(ContainerId.CURSOR); - cursorPacket.setSlot(ItemData.AIR); - session.getUpstream().sendPacket(cursorPacket); - - Inventory inventory = session.getInventoryCache().getOpenInventory(); - if (inventory != null) { - session.setReopeningWindow(inventory.getId()); - } else { - inventory = session.getInventory(); - } - ContainerClosePacket closePacket = new ContainerClosePacket(); - closePacket.setWindowId((byte) inventory.getId()); - Geyser.getGeneralThreadPool().schedule(() -> session.getUpstream().sendPacket(closePacket), 150, TimeUnit.MILLISECONDS); - }*/ - + //bedrock client is bugged when changing the cursor. do not send slot update packet session.getInventory().setCursor(packet.getItem()); return; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaWindowPropertyTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaWindowPropertyTranslator.java index 2127a94b..c8e04d37 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaWindowPropertyTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaWindowPropertyTranslator.java @@ -1,9 +1,33 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + package org.geysermc.connector.network.translators.java.window; import com.github.steveice10.mc.protocol.packet.ingame.server.window.ServerWindowPropertyPacket; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.session.cache.InventoryCache; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.TranslatorsInit; import org.geysermc.connector.network.translators.inventory.InventoryTranslator; diff --git a/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java b/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java index 77c69eed..c5823a40 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java @@ -1,10 +1,5 @@ package org.geysermc.connector.utils; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; -import com.github.steveice10.mc.protocol.data.game.window.WindowType; -import com.github.steveice10.mc.protocol.packet.ingame.server.window.ServerOpenWindowPacket; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.nukkitx.protocol.bedrock.data.ItemData; import org.geysermc.api.Geyser; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; @@ -12,7 +7,6 @@ import org.geysermc.connector.network.translators.TranslatorsInit; import org.geysermc.connector.network.translators.inventory.DoubleChestInventoryTranslator; import org.geysermc.connector.network.translators.inventory.InventoryTranslator; -import java.util.Objects; import java.util.concurrent.TimeUnit; public class InventoryUtils { @@ -52,11 +46,4 @@ public class InventoryUtils { session.setCraftSlot(0); session.getInventory().setCursor(null); } - - //NPE if nbt tag is null - public static ItemStack fixStack(ItemStack stack) { - if (stack == null || stack.getId() == 0) - return null; - return new ItemStack(stack.getId(), stack.getAmount(), stack.getNbt() == null ? new CompoundTag("") : stack.getNbt()); - } } From ebf6050d44f5ae1fcf03bb3fdd289ec02dfd4e81 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Wed, 27 Nov 2019 18:14:38 -0600 Subject: [PATCH 018/109] Start work on block entities (partially-functioning) Most block entities should now *show up*. Some like signs will not as of yet, however when another player places one, they will display. Block entities are not yet fully functional and may only just be visible for the time being. --- .../network/translators/TranslatorsInit.java | 15 ++++ .../block/entity/BlockEntityTranslator.java | 73 ++++++++++++++++++ .../entity/EmptyBlockEntityTranslator.java | 50 ++++++++++++ .../entity/SignBlockEntityTranslator.java | 77 +++++++++++++++++++ .../java/world/JavaChunkDataTranslator.java | 12 +++ .../world/JavaUpdateTileEntityTranslator.java | 51 ++++++++++++ .../connector/utils/BlockEntityUtils.java | 32 ++++++++ .../geysermc/connector/utils/ChunkUtils.java | 34 +++++++- 8 files changed, 343 insertions(+), 1 deletion(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java index a19de3f2..072b7aed 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java @@ -45,6 +45,9 @@ import com.nukkitx.protocol.bedrock.packet.*; import lombok.Getter; import org.geysermc.connector.network.translators.bedrock.*; import org.geysermc.connector.network.translators.block.BlockTranslator; +import org.geysermc.connector.network.translators.block.entity.BlockEntityTranslator; +import org.geysermc.connector.network.translators.block.entity.EmptyBlockEntityTranslator; +import org.geysermc.connector.network.translators.block.entity.SignBlockEntityTranslator; import org.geysermc.connector.network.translators.inventory.GenericInventoryTranslator; import org.geysermc.connector.network.translators.inventory.InventoryTranslator; import org.geysermc.connector.network.translators.item.ItemTranslator; @@ -64,6 +67,8 @@ import org.geysermc.connector.network.translators.java.world.*; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.util.HashMap; +import java.util.Map; public class TranslatorsInit { @@ -76,6 +81,9 @@ public class TranslatorsInit { @Getter private static InventoryTranslator inventoryTranslator = new GenericInventoryTranslator(); + @Getter + private static Map blockEntityTranslators = new HashMap<>(); + private static final CompoundTag EMPTY_TAG = CompoundTagBuilder.builder().buildRootTag(); public static final byte[] EMPTY_LEVEL_CHUNK_DATA; @@ -144,6 +152,7 @@ public class TranslatorsInit { Registry.registerJava(ServerBlockChangePacket.class, new JavaBlockChangeTranslator()); Registry.registerJava(ServerMultiBlockChangePacket.class, new JavaMultiBlockChangeTranslator()); Registry.registerJava(ServerUnloadChunkPacket.class, new JavaUnloadChunkTranslator()); + Registry.registerJava(ServerUpdateTileEntityPacket.class, new JavaUpdateTileEntityTranslator()); Registry.registerJava(ServerOpenWindowPacket.class, new OpenWindowPacketTranslator()); @@ -160,9 +169,15 @@ public class TranslatorsInit { itemTranslator = new ItemTranslator(); blockTranslator = new BlockTranslator(); + registerBlockEntityTranslators(); registerInventoryTranslators(); } + private static void registerBlockEntityTranslators() { + blockEntityTranslators.put("Empty", new EmptyBlockEntityTranslator()); + blockEntityTranslators.put("Sign", new SignBlockEntityTranslator()); + } + private static void registerInventoryTranslators() { /*inventoryTranslators.put(WindowType.GENERIC_9X1, new GenericInventoryTranslator()); inventoryTranslators.put(WindowType.GENERIC_9X2, new GenericInventoryTranslator()); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java new file mode 100644 index 00000000..4913a300 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.block.entity; + +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.IntTag; +import com.github.steveice10.opennbt.tag.builtin.StringTag; +import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.tag.Tag; +import org.geysermc.connector.utils.BlockEntityUtils; + +import java.util.List; + +public abstract class BlockEntityTranslator { + + public abstract List> translateTag(CompoundTag tag); + + public abstract CompoundTag getDefaultJavaTag(int x, int y, int z); + + public abstract com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(int x, int y, int z); + + public com.nukkitx.nbt.tag.CompoundTag getBlockEntityTag(CompoundTag tag) { + String id = BlockEntityUtils.getBedrockBlockEntityId((String) tag.get("id").getValue()); + int x = Integer.parseInt(String.valueOf(tag.getValue().get("x").getValue())); + int y = Integer.parseInt(String.valueOf(tag.getValue().get("y").getValue())); + int z = Integer.parseInt(String.valueOf(tag.getValue().get("z").getValue())); + + CompoundTagBuilder tagBuilder = getConstantBedrockTag(id, x, y, z).toBuilder(); + translateTag(tag).forEach(tagBuilder::tag); + return tagBuilder.buildRootTag(); + } + + protected CompoundTag getConstantJavaTag(String id, int x, int y, int z) { + CompoundTag tag = new CompoundTag(""); + tag.put(new IntTag("x", x)); + tag.put(new IntTag("y", y)); + tag.put(new IntTag("z", z)); + tag.put(new StringTag("id", id)); + return tag; + } + + protected com.nukkitx.nbt.tag.CompoundTag getConstantBedrockTag(String id, int x, int y, int z) { + CompoundTagBuilder tagBuilder = CompoundTagBuilder.builder() + .intTag("x", x) + .intTag("y", y) + .intTag("z", z) + .stringTag("id", id); + return tagBuilder.buildRootTag(); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java new file mode 100644 index 00000000..927337bc --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.block.entity; + +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.nukkitx.nbt.tag.Tag; + +import java.util.ArrayList; +import java.util.List; + +public class EmptyBlockEntityTranslator extends BlockEntityTranslator { + + @Override + public List> translateTag(CompoundTag tag) { + return new ArrayList<>(); + } + + @Override + public CompoundTag getDefaultJavaTag(int x, int y, int z) { + return getConstantJavaTag("empty", x, y, z); + } + + @Override + public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(int x, int y, int z) { + return getConstantBedrockTag("Empty", x, y, z); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java new file mode 100644 index 00000000..414455c7 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.block.entity; + +import com.github.steveice10.mc.protocol.data.message.Message; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.tag.ByteTag; +import com.nukkitx.nbt.tag.StringTag; +import com.nukkitx.nbt.tag.Tag; +import org.geysermc.connector.utils.MessageUtils; + +import java.util.ArrayList; +import java.util.List; + +public class SignBlockEntityTranslator extends BlockEntityTranslator { + + @Override + public List> translateTag(CompoundTag tag) { + List> tags = new ArrayList<>(); + + String line1 = (String) tag.getValue().get("Text1").getValue(); + String line2 = (String) tag.getValue().get("Text2").getValue(); + String line3 = (String) tag.getValue().get("Text3").getValue(); + String line4 = (String) tag.getValue().get("Text4").getValue(); + + tags.add(new StringTag("Text", MessageUtils.getBedrockMessage(Message.fromString(line1)) + + "\n" + MessageUtils.getBedrockMessage(Message.fromString(line2)) + + "\n" + MessageUtils.getBedrockMessage(Message.fromString(line3)) + + "\n" + MessageUtils.getBedrockMessage(Message.fromString(line4)) + )); + + tags.add(new ByteTag("isMovable", (byte) 0)); + return tags; + } + + @Override + public CompoundTag getDefaultJavaTag(int x, int y, int z) { + CompoundTag tag = getConstantJavaTag("minecraft:sign", x, y, z); + tag.put(new com.github.steveice10.opennbt.tag.builtin.StringTag("Text1", "\"text\":\"\"")); + tag.put(new com.github.steveice10.opennbt.tag.builtin.StringTag("Text2", "\"text\":\"\"")); + tag.put(new com.github.steveice10.opennbt.tag.builtin.StringTag("Text3", "\"text\":\"\"")); + tag.put(new com.github.steveice10.opennbt.tag.builtin.StringTag("Text4", "\"text\":\"\"")); + return tag; + } + + @Override + public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(int x, int y, int z) { + CompoundTagBuilder tagBuilder = getConstantBedrockTag("Sign", x, y, z).toBuilder(); + tagBuilder.stringTag("Text", ""); + tagBuilder.byteTag("isMovable", (byte) 0); + return tagBuilder.buildRootTag(); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java index a620197e..1c83579a 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java @@ -3,10 +3,14 @@ package org.geysermc.connector.network.translators.java.world; import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerChunkDataPacket; import com.nukkitx.math.vector.Vector2i; import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.nbt.NbtUtils; +import com.nukkitx.nbt.stream.NBTOutputStream; +import com.nukkitx.nbt.tag.CompoundTag; import com.nukkitx.network.VarInts; import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket; import com.nukkitx.protocol.bedrock.packet.NetworkChunkPublisherUpdatePacket; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufOutputStream; import io.netty.buffer.Unpooled; import org.geysermc.api.Geyser; import org.geysermc.connector.network.session.GeyserSession; @@ -53,6 +57,14 @@ public class JavaChunkDataTranslator extends PacketTranslator { + + @Override + public void translate(ServerUpdateTileEntityPacket packet, GeyserSession session) { + BlockEntityDataPacket blockEntityPacket = new BlockEntityDataPacket(); + blockEntityPacket.setBlockPosition(Vector3i.from(packet.getPosition().getX(), + packet.getPosition().getY(), + packet.getPosition().getZ()) + ); + + String id = BlockEntityUtils.getBedrockBlockEntityId(packet.getType().name()); + BlockEntityTranslator translator = BlockEntityUtils.getBlockEntityTranslator(id); + blockEntityPacket.setData(translator.getBlockEntityTag(packet.getNbt())); + session.getUpstream().sendPacket(blockEntityPacket); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java new file mode 100644 index 00000000..6fb62b55 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java @@ -0,0 +1,32 @@ +package org.geysermc.connector.utils; + +import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.block.entity.BlockEntityTranslator; + +public class BlockEntityUtils { + + public static String getBedrockBlockEntityId(String id) { + // This is the only exception when it comes to block entity ids + if (id.contains("piston_head")) + return "PistonArm"; + + id = id.replace("minecraft:", ""); + id = id.replace("_", " "); + String[] words = id.split(" "); + for (int i = 0; i < words.length; i++) { + words[i] = words[i].substring(0, 1).toUpperCase() + words[i].substring(1).toLowerCase(); + } + + id = String.join(" ", words); + return id.replace(" ", ""); + } + + public static BlockEntityTranslator getBlockEntityTranslator(String name) { + BlockEntityTranslator blockEntityTranslator = TranslatorsInit.getBlockEntityTranslators().get(name); + if (blockEntityTranslator == null) { + return TranslatorsInit.getBlockEntityTranslators().get("Empty"); + } + + return blockEntityTranslator; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java index 6f2b6d3c..59a5fe84 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -3,10 +3,19 @@ package org.geysermc.connector.utils; import com.github.steveice10.mc.protocol.data.game.chunk.Chunk; import com.github.steveice10.mc.protocol.data.game.chunk.Column; import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.Tag; +import org.geysermc.connector.console.GeyserLogger; import org.geysermc.connector.network.translators.TranslatorsInit; import org.geysermc.connector.network.translators.block.BlockEntry; +import org.geysermc.connector.network.translators.block.entity.BlockEntityTranslator; +import org.geysermc.connector.network.translators.block.entity.SignBlockEntityTranslator; import org.geysermc.connector.world.chunk.ChunkSection; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + public class ChunkUtils { public static ChunkData translateToBedrock(Column column) { @@ -16,6 +25,7 @@ public class ChunkUtils { int chunkSectionCount = chunks.length; chunkData.sections = new ChunkSection[chunkSectionCount]; + List blockEntities = new ArrayList<>(Arrays.asList(column.getTileEntities())); for (int chunkY = 0; chunkY < chunkSectionCount; chunkY++) { chunkData.sections[chunkY] = new ChunkSection(); Chunk chunk = chunks[chunkY]; @@ -38,10 +48,32 @@ public class ChunkUtils { section.getBlockStorageArray()[1].setFullBlock(ChunkSection.blockPosition(x, y, z), 9 << 4); // water id } + + // Block entity data for signs is not sent in this packet, which is needed + // for bedrock, so we need to check the block itself + if (block.getJavaIdentifier().contains("sign")) { + SignBlockEntityTranslator sign = (SignBlockEntityTranslator) BlockEntityUtils.getBlockEntityTranslator("Sign"); + blockEntities.add(sign.getDefaultJavaTag(x, y, z)); + } } } } } + + List bedrockBlockEntities = new ArrayList<>(); + for (CompoundTag tag : blockEntities) { + Tag idTag = tag.get("id"); + if (idTag == null) { + GeyserLogger.DEFAULT.debug("Got tag with no id: " + tag.getValue()); + continue; + } + + String id = BlockEntityUtils.getBedrockBlockEntityId((String) tag.get("id").getValue()); + BlockEntityTranslator blockEntityTranslator = BlockEntityUtils.getBlockEntityTranslator(id); + bedrockBlockEntities.add(blockEntityTranslator.getBlockEntityTag(tag)); + } + + chunkData.blockEntities = bedrockBlockEntities; return chunkData; } @@ -49,6 +81,6 @@ public class ChunkUtils { public ChunkSection[] sections; public byte[] biomes = new byte[256]; - public byte[] blockEntities = new byte[0]; + public List blockEntities = new ArrayList<>(); } } From 8c93ca65f5fdeea32f046469923e03e5f3fdd1f2 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Sat, 30 Nov 2019 15:24:01 -0900 Subject: [PATCH 019/109] Update JavaDeclareRecipesTranslator.java --- .../java/JavaDeclareRecipesTranslator.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java index cadafb01..5cc98c3f 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java @@ -34,6 +34,8 @@ import com.nukkitx.nbt.tag.CompoundTag; import com.nukkitx.protocol.bedrock.data.CraftingData; import com.nukkitx.protocol.bedrock.data.ItemData; import com.nukkitx.protocol.bedrock.packet.CraftingDataPacket; +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import org.geysermc.connector.network.session.GeyserSession; @@ -82,10 +84,10 @@ public class JavaDeclareRecipesTranslator extends PacketTranslator, Set> squashedOptions = new HashMap<>(); + Map, IntSet> squashedOptions = new HashMap<>(); for (int i = 0; i < ingredients.length; i++) { if (ingredients[i].getOptions().length == 0) { - squashedOptions.computeIfAbsent(Collections.singleton(ItemData.AIR), k -> new HashSet<>()).add(i); + squashedOptions.computeIfAbsent(Collections.singleton(ItemData.AIR), k -> new IntOpenHashSet()).add(i); continue; } Ingredient ingredient = ingredients[i]; @@ -98,7 +100,7 @@ public class JavaDeclareRecipesTranslator extends PacketTranslator new HashSet<>()).add(i); + squashedOptions.computeIfAbsent(optionSet, k -> new IntOpenHashSet()).add(i); } int totalCombinations = 1; for (Set optionSet : squashedOptions.keySet()) { @@ -135,7 +137,7 @@ public class JavaDeclareRecipesTranslator extends PacketTranslator set : sortedSets) { - Set slotSet = squashedOptions.get(set); + IntSet slotSet = squashedOptions.get(set); int i = 0; for (ItemData item : set) { for (int j = 0; j < totalCombinations / set.size(); j++) { From ba0b898da99da96dd5d086e0502883efbc5d64a0 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Sat, 30 Nov 2019 17:22:14 -0900 Subject: [PATCH 020/109] Fix anvils --- ...BedrockInventoryTransactionTranslator.java | 21 +++++++++--------- .../inventory/AnvilInventoryTranslator.java | 22 +++++++++++++++---- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java index 27dd19ca..06343110 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java @@ -131,22 +131,18 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator(2); - for (InventoryAction action : packet.getActions()) { //packet sent by client when grabbing anvil output needs useless actions stripped - if (!(action.getSource().getContainerId() == ContainerId.CONTAINER_INPUT || - action.getSource().getContainerId() == ContainerId.ANVIL_MATERIAL)) { - actions.add(action); - } - } } else if (anvilInput != null) { itemName = anvilInput.getToItem(); } @@ -161,6 +157,11 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator Date: Sun, 1 Dec 2019 00:26:11 -0900 Subject: [PATCH 021/109] Cleanup and fixes --- ...BedrockInventoryTransactionTranslator.java | 38 +++++++++++------ .../inventory/AnvilInventoryTranslator.java | 42 ++++++------------- .../inventory/BlockInventoryTranslator.java | 4 +- .../BrewingStandInventoryTranslator.java | 34 ++++++--------- .../ContainerInventoryTranslator.java | 6 +-- .../CraftingTableInventoryTranslator.java | 20 ++++----- .../inventory/FurnaceInventoryTranslator.java | 7 ++-- .../inventory/InventoryTranslator.java | 2 +- .../inventory/PlayerInventoryTranslator.java | 10 ++--- .../translators/inventory/SlotType.java | 32 ++++++++++++++ 10 files changed, 108 insertions(+), 87 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/SlotType.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java index 06343110..1fd0500c 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java @@ -55,6 +55,7 @@ import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.TranslatorsInit; import org.geysermc.connector.network.translators.inventory.InventoryTranslator; +import org.geysermc.connector.network.translators.inventory.SlotType; import java.util.*; @@ -237,8 +238,19 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator plan = new ArrayList<>(); - ItemStack translatedCursor = TranslatorsInit.getItemTranslator().translateToJava(cursorAction.getFromItem()); - boolean refresh = !Objects.equals(session.getInventory().getCursor(), translatedCursor.getId() == 0 ? null : translatedCursor); //refresh slot if there is a cursor mismatch + ItemStack translatedCursor = cursorAction.getFromItem().isValid() ? + TranslatorsInit.getItemTranslator().translateToJava(cursorAction.getFromItem()) : null; + ItemStack currentCursor = session.getInventory().getCursor(); + boolean refresh = false; + if (currentCursor != null) { + if (translatedCursor != null) { + refresh = !(currentCursor.getId() == translatedCursor.getId() && + currentCursor.getAmount() == translatedCursor.getAmount()); + } else { + refresh = true; + } + } + int javaSlot = translator.bedrockSlotToJava(containerAction); if (cursorAction.getFromItem().equals(containerAction.getToItem()) && containerAction.getFromItem().equals(cursorAction.getToItem()) && @@ -258,7 +270,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator= 9) { - return slotnum + this.size - 9; - } else { - return slotnum + this.size + 27; - } - } else { - if (action.getSource().getContainerId() == ContainerId.CURSOR) { - switch (slotnum) { - case 1: - return 0; - case 2: - return 1; - case 50: - return 2; - } + if (action.getSource().getContainerId() == ContainerId.CURSOR) { + switch (action.getSlot()) { + case 1: + return 0; + case 2: + return 1; + case 50: + return 2; } } - return slotnum; + return super.bedrockSlotToJava(action); } @Override - public boolean isOutputSlot(int slot) { - return slot == 2; + public SlotType getSlotType(int javaSlot) { + if (javaSlot == 2) + return SlotType.OUTPUT; + return SlotType.NORMAL; } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BlockInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BlockInventoryTranslator.java index 065d63dc..0112dc9e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BlockInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BlockInventoryTranslator.java @@ -38,8 +38,8 @@ import org.geysermc.connector.network.translators.block.BlockEntry; import org.geysermc.connector.world.GlobalBlockPalette; public class BlockInventoryTranslator extends ContainerInventoryTranslator { - protected final int blockId; - protected final ContainerType containerType; + final int blockId; + private final ContainerType containerType; public BlockInventoryTranslator(int size, int blockId, ContainerType containerType) { super(size); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingStandInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingStandInventoryTranslator.java index 92eb4bc8..e6089cb8 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingStandInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingStandInventoryTranslator.java @@ -25,7 +25,6 @@ package org.geysermc.connector.network.translators.inventory; -import com.nukkitx.protocol.bedrock.data.ContainerId; import com.nukkitx.protocol.bedrock.data.ContainerType; import com.nukkitx.protocol.bedrock.data.InventoryAction; import com.nukkitx.protocol.bedrock.packet.ContainerSetDataPacket; @@ -58,27 +57,18 @@ public class BrewingStandInventoryTranslator extends BlockInventoryTranslator { @Override public int bedrockSlotToJava(InventoryAction action) { - int slotnum = action.getSlot(); - if (action.getSource().getContainerId() == ContainerId.INVENTORY) { - //hotbar - if (slotnum >= 9) { - return slotnum + this.size - 9; - } else { - return slotnum + this.size + 27; - } - } else { - switch (slotnum) { - case 0: - return 3; - case 1: - return 0; - case 2: - return 1; - case 3: - return 2; - default: - return slotnum; - } + int slotnum = super.bedrockSlotToJava(action); + switch (slotnum) { + case 0: + return 3; + case 1: + return 0; + case 2: + return 1; + case 3: + return 2; + default: + return slotnum; } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/ContainerInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/ContainerInventoryTranslator.java index 22d73b9b..8f66675b 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/ContainerInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/ContainerInventoryTranslator.java @@ -35,7 +35,7 @@ import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.TranslatorsInit; public abstract class ContainerInventoryTranslator extends InventoryTranslator { - public ContainerInventoryTranslator(int size) { + ContainerInventoryTranslator(int size) { super(size); } @@ -97,7 +97,7 @@ public abstract class ContainerInventoryTranslator extends InventoryTranslator { } @Override - public boolean isOutputSlot(int slot) { - return false; + public SlotType getSlotType(int javaSlot) { + return SlotType.NORMAL; } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingTableInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingTableInventoryTranslator.java index 82b4f922..28ad0cb2 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingTableInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingTableInventoryTranslator.java @@ -59,21 +59,21 @@ public class CraftingTableInventoryTranslator extends ContainerInventoryTranslat @Override public int bedrockSlotToJava(InventoryAction action) { - int slotnum = action.getSlot(); - if (action.getSource().getContainerId() == ContainerId.INVENTORY) { - //hotbar - if (slotnum >= 9) { - return slotnum + this.size - 9; - } else { - return slotnum + this.size + 27; - } - } else { + if (action.getSource().getContainerId() == ContainerId.CURSOR) { + int slotnum = action.getSlot(); if (slotnum >= 32 && 42 >= slotnum) { return slotnum - 31; } else if (slotnum == 50) { return 0; } - return slotnum; } + return super.bedrockSlotToJava(action); + } + + @Override + public SlotType getSlotType(int javaSlot) { + if (javaSlot == 0) + return SlotType.OUTPUT; + return SlotType.NORMAL; } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java index 9c274c87..95d78562 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java @@ -26,7 +26,6 @@ package org.geysermc.connector.network.translators.inventory; import com.nukkitx.protocol.bedrock.data.ContainerType; -import com.nukkitx.protocol.bedrock.data.InventoryAction; import com.nukkitx.protocol.bedrock.packet.ContainerSetDataPacket; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; @@ -59,7 +58,9 @@ public class FurnaceInventoryTranslator extends BlockInventoryTranslator { } @Override - public boolean isOutputSlot(int slot) { - return slot == 2; + public SlotType getSlotType(int javaSlot) { + if (javaSlot == 2) + return SlotType.FURNACE_OUTPUT; + return SlotType.NORMAL; } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java index edc7f495..0aa4df0a 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java @@ -44,5 +44,5 @@ public abstract class InventoryTranslator { public abstract void updateSlot(GeyserSession session, Inventory inventory, int slot); public abstract int bedrockSlotToJava(InventoryAction action); public abstract int javaSlotToBedrock(int slot); - public abstract boolean isOutputSlot(int slot); + public abstract SlotType getSlotType(int javaSlot); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java index 773c4dca..6ba25bc5 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java @@ -119,15 +119,13 @@ public class PlayerInventoryTranslator extends InventoryTranslator { break; case ContainerId.OFFHAND: return 45; - case ContainerId.CRAFTING_ADD_INGREDIENT: - case ContainerId.CRAFTING_REMOVE_INGREDIENT: - return slotnum + 1; case ContainerId.CURSOR: if (slotnum >= 28 && 31 >= slotnum) { return slotnum - 27; } else if (slotnum == 50) { return 0; } + break; } return slotnum; } @@ -138,8 +136,10 @@ public class PlayerInventoryTranslator extends InventoryTranslator { } @Override - public boolean isOutputSlot(int slot) { - return false; + public SlotType getSlotType(int javaSlot) { + if (javaSlot == 0) + return SlotType.OUTPUT; + return SlotType.NORMAL; } @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SlotType.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SlotType.java new file mode 100644 index 00000000..b5657af4 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SlotType.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.inventory; + +public enum SlotType { + NORMAL, + OUTPUT, + FURNACE_OUTPUT +} From 4eeadc6d21233baaffabd5194566b4522f181339 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Mon, 2 Dec 2019 00:48:27 -0900 Subject: [PATCH 022/109] Start working on translating enchantments and potions Translation is only (java -> bedrock) for now. Only regular potions will translate correctly. More work will be needed to translate custom potions. --- .../network/translators/item/Enchantment.java | 85 +++++++++++++++ .../translators/item/ItemTranslator.java | 40 ++++++- .../network/translators/item/Potion.java | 102 ++++++++++++++++++ 3 files changed, 225 insertions(+), 2 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/item/Enchantment.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/item/Potion.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/Enchantment.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/Enchantment.java new file mode 100644 index 00000000..79b8514a --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/Enchantment.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.item; + +import lombok.Getter; + +import java.util.Locale; + +@Getter +enum Enchantment { + PROTECTION, + FIRE_PROTECTION, + FEATHER_FALLING, + BLAST_PROTECTION, + PROJECTILE_PROTECTION, + THORNS, + RESPIRATION, + DEPTH_STRIDER, + AQUA_AFFINITY, + SHARPNESS, + SMITE, + BANE_OF_ARTHROPODS, + KNOCKBACK, + FIRE_ASPECT, + LOOTING, + EFFICIENCY, + SILK_TOUCH, + UNBREAKING, + FORTUNE, + POWER, + PUNCH, + FLAME, + INFINITY, + LUCK_OF_THE_SEA, + LURE, + FROST_WALKER, + MENDING, + BINDING_CURSE, + VANISHING_CURSE, + IMPALING, + RIPTIDE, + LOYALTY, + CHANNELING, + MULTISHOT, + PIERCING, + QUICK_CHARGE; + + private final String javaIdentifier; + + Enchantment() { + this.javaIdentifier = "minecraft:" + this.name().toLowerCase(Locale.ENGLISH); + } + + public static Enchantment getByJavaIdentifier(String javaIdentifier) { + for (Enchantment enchantment : Enchantment.values()) { + if (enchantment.javaIdentifier.equals(javaIdentifier)) { + return enchantment; + } + } + return null; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java index 472287b7..5478a278 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java @@ -41,6 +41,7 @@ import com.github.steveice10.opennbt.tag.builtin.ShortTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import com.nukkitx.protocol.bedrock.data.ItemData; +import org.geysermc.api.Geyser; import org.geysermc.connector.console.GeyserLogger; import org.geysermc.connector.utils.MessageUtils; import org.geysermc.connector.utils.Toolbox; @@ -70,6 +71,15 @@ public class ItemTranslator { ItemEntry bedrockItem = getItem(stack); if (stack.getNbt() == null) { return ItemData.of(bedrockItem.getBedrockId(), (short) bedrockItem.getBedrockData(), stack.getAmount()); + } else if (bedrockItem.getJavaIdentifier().endsWith("potion")) { + Tag potionTag = stack.getNbt().get("Potion"); + if (potionTag instanceof StringTag) { + Potion potion = Potion.getByJavaIdentifier(((StringTag) potionTag).getValue()); + if (potion != null) { + return ItemData.of(bedrockItem.getBedrockId(), potion.getBedrockId(), stack.getAmount(), translateToBedrockNBT(stack.getNbt())); + } + Geyser.getLogger().debug("Unknown java potion: " + potionTag.getValue()); + } } return ItemData.of(bedrockItem.getBedrockId(), (short) bedrockItem.getBedrockData(), stack.getAmount(), translateToBedrockNBT(stack.getNbt())); } @@ -80,7 +90,7 @@ public class ItemTranslator { public ItemEntry getItem(ItemData data) { for (ItemEntry itemEntry : Toolbox.ITEM_ENTRIES.values()) { - if (itemEntry.getBedrockId() == data.getId() && itemEntry.getBedrockData() == data.getDamage()) { + if (itemEntry.getBedrockId() == data.getId() && (itemEntry.getBedrockData() == data.getDamage() || itemEntry.getJavaIdentifier().endsWith("potion"))) { return itemEntry; } } @@ -251,7 +261,33 @@ public class ItemTranslator { if (tag instanceof ListTag) { ListTag listTag = (ListTag) tag; - if (listTag.getName().equalsIgnoreCase("Lore")) { + if (listTag.getName().equalsIgnoreCase("Enchantments") || listTag.getName().equalsIgnoreCase("StoredEnchantments")) { + List tags = new ArrayList<>(); + for (Object value : listTag.getValue()) { + if (!(value instanceof CompoundTag)) + continue; + + Tag javaEnchLvl = ((CompoundTag) value).get("lvl"); + if (!(javaEnchLvl instanceof ShortTag)) + continue; + + Tag javaEnchId = ((CompoundTag) value).get("id"); + if (!(javaEnchId instanceof StringTag)) + continue; + + Enchantment enchantment = Enchantment.getByJavaIdentifier(((StringTag) javaEnchId).getValue()); + if (enchantment == null) { + Geyser.getLogger().debug("Unknown java enchantment: " + javaEnchId.getValue()); + continue; + } + + com.nukkitx.nbt.CompoundTagBuilder builder = com.nukkitx.nbt.tag.CompoundTag.EMPTY.toBuilder(); + builder.shortTag("lvl", ((ShortTag) javaEnchLvl).getValue()); + builder.shortTag("id", (short) enchantment.ordinal()); + tags.add(builder.buildRootTag()); + } + return new com.nukkitx.nbt.tag.ListTag<>("ench", com.nukkitx.nbt.tag.CompoundTag.class, tags); + } else if (listTag.getName().equalsIgnoreCase("Lore")) { List tags = new ArrayList<>(); for (Object value : listTag.getValue()) { if (!(value instanceof Tag)) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/Potion.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/Potion.java new file mode 100644 index 00000000..ca5cd5c0 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/Potion.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.item; + +import lombok.Getter; + +import java.util.Locale; + +@Getter +enum Potion { + WATER(0), + MUNDANE(1), + THICK(3), + AWKWARD(4), + NIGHT_VISION(5), + LONG_NIGHT_VISION(6), + INVISIBILITY(7), + LONG_INVISIBILITY(8), + LEAPING(9), + STRONG_LEAPING(11), + LONG_LEAPING(10), + FIRE_RESISTANCE(12), + LONG_FIRE_RESISTANCE(13), + SWIFTNESS(14), + STRONG_SWIFTNESS(16), + LONG_SWIFTNESS(15), + SLOWNESS(17), + STRONG_SLOWNESS(18), //does not exist + LONG_SLOWNESS(18), + WATER_BREATHING(19), + LONG_WATER_BREATHING(20), + HEALING(21), + STRONG_HEALING(22), + HARMING(23), + STRONG_HARMING(24), + POISON(25), + STRONG_POISON(27), + LONG_POISON(26), + REGENERATION(28), + STRONG_REGENERATION(30), + LONG_REGENERATION(29), + STRENGTH(31), + STRONG_STRENGTH(33), + LONG_STRENGTH(32), + WEAKNESS(34), + LONG_WEAKNESS(35), + LUCK(2), //does not exist + TURTLE_MASTER(37), + STRONG_TURTLE_MASTER(39), + LONG_TURTLE_MASTER(38), + SLOW_FALLING(40), + LONG_SLOW_FALLING(41); + + private final String javaIdentifier; + private final short bedrockId; + + Potion(int bedrockId) { + this.javaIdentifier = "minecraft:" + this.name().toLowerCase(Locale.ENGLISH); + this.bedrockId = (short) bedrockId; + } + + public static Potion getByJavaIdentifier(String javaIdentifier) { + for (Potion potion : Potion.values()) { + if (potion.javaIdentifier.equals(javaIdentifier)) { + return potion; + } + } + return null; + } + + public static Potion getByBedrockId(short bedrockId) { + for (Potion potion : Potion.values()) { + if (potion.bedrockId == bedrockId) { + return potion; + } + } + return null; + } +} From 7a588408215e63171011a3c07b15974757d5694e Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Mon, 2 Dec 2019 14:22:13 -0900 Subject: [PATCH 023/109] Fix NoClassDefFoundError in Java 9+ --- .../src/main/java/org/geysermc/connector/utils/Toolbox.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java index 806f5e17..3b0d02a2 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java +++ b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java @@ -16,7 +16,6 @@ import org.geysermc.connector.network.translators.block.BlockEntry; import org.geysermc.connector.network.translators.item.ItemEntry; import org.geysermc.connector.world.GlobalBlockPalette; -import javax.xml.bind.DatatypeConverter; import java.io.*; import java.util.*; @@ -129,7 +128,7 @@ public class Toolbox { damage = (short)(int) map.get("damage"); } if (map.containsKey("nbt_b64")) { - byte[] bytes = DatatypeConverter.parseBase64Binary((String) map.get("nbt_b64")); + byte[] bytes = Base64.getDecoder().decode((String) map.get("nbt_b64")); ByteArrayInputStream bais = new ByteArrayInputStream(bytes); try { com.nukkitx.nbt.tag.CompoundTag tag = (com.nukkitx.nbt.tag.CompoundTag) NbtUtils.createReaderLE(bais).readTag(); From 1b37a192808d501f429970fc824dafb779e291ec Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Mon, 2 Dec 2019 15:53:46 -0900 Subject: [PATCH 024/109] Translate bedrock enchantments to java --- .../network/translators/item/Enchantment.java | 7 ++++ .../translators/item/ItemTranslator.java | 38 ++++++++++++++++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/Enchantment.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/Enchantment.java index 79b8514a..596ef215 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/Enchantment.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/Enchantment.java @@ -82,4 +82,11 @@ enum Enchantment { } return null; } + + public static Enchantment getByBedrockId(int bedrockId) { + if (bedrockId >= 0 && bedrockId < Enchantment.values().length) { + return Enchantment.values()[bedrockId]; + } + return null; + } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java index 5478a278..438b2061 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java @@ -58,6 +58,17 @@ public class ItemTranslator { if (data.getTag() == null) { return new ItemStack(javaItem.getJavaId(), data.getCount()); + } else if (javaItem.getJavaIdentifier().equals("minecraft:enchanted_book")) { + CompoundTag javaTag = translateToJavaNBT(data.getTag()); + Map javaValue = javaTag.getValue(); + Tag enchTag = javaValue.get("Enchantments"); + if (enchTag instanceof ListTag) { + enchTag = new ListTag("StoredEnchantments", ((ListTag) enchTag).getValue()); + javaValue.remove("Enchantments"); + javaValue.put("StoredEnchantments", enchTag); + javaTag.setValue(javaValue); + } + return new ItemStack(javaItem.getJavaId(), data.getCount(), javaTag); } return new ItemStack(javaItem.getJavaId(), data.getCount(), translateToJavaNBT(data.getTag())); } @@ -109,7 +120,7 @@ public class ItemTranslator { if (translatedTag == null) continue; - javaValue.put(str, translatedTag); + javaValue.put(translatedTag.getName(), translatedTag); } } @@ -172,6 +183,29 @@ public class ItemTranslator { com.nukkitx.nbt.tag.ListTag listTag = (com.nukkitx.nbt.tag.ListTag) tag; List tags = new ArrayList<>(); + + if (tag.getName().equals("ench")) { + for (Object value : listTag.getValue()) { + if (!(value instanceof com.nukkitx.nbt.tag.CompoundTag)) + continue; + + com.nukkitx.nbt.tag.CompoundTag tagValue = (com.nukkitx.nbt.tag.CompoundTag) value; + int bedrockId = tagValue.getAsShort("id", (short) -1); + Enchantment enchantment = Enchantment.getByBedrockId(bedrockId); + if (enchantment != null) { + CompoundTag javaTag = new CompoundTag(""); + Map javaValue = javaTag.getValue(); + javaValue.put("id", new StringTag("id", enchantment.getJavaIdentifier())); + javaValue.put("lvl", new IntTag("lvl", tagValue.getAsShort("lvl"))); + javaTag.setValue(javaValue); + tags.add(javaTag); + } else { + Geyser.getLogger().debug("Unknown bedrock enchantment: " + bedrockId); + } + } + return new ListTag("Enchantments", tags); + } + for (Object value : listTag.getValue()) { if (!(value instanceof com.nukkitx.nbt.tag.Tag)) continue; @@ -200,7 +234,7 @@ public class ItemTranslator { if (translatedTag == null) continue; - javaValue.put(str, translatedTag); + javaValue.put(translatedTag.getName(), translatedTag); } } From 0720e18015f295cd4c652f992cee4c8f380767b2 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Mon, 2 Dec 2019 16:07:44 -0900 Subject: [PATCH 025/109] Default bedrock enchantment level to 1 --- .../connector/network/translators/item/ItemTranslator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java index 438b2061..6b78f0d6 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java @@ -196,7 +196,7 @@ public class ItemTranslator { CompoundTag javaTag = new CompoundTag(""); Map javaValue = javaTag.getValue(); javaValue.put("id", new StringTag("id", enchantment.getJavaIdentifier())); - javaValue.put("lvl", new IntTag("lvl", tagValue.getAsShort("lvl"))); + javaValue.put("lvl", new IntTag("lvl", tagValue.getAsShort("lvl", (short) 1))); javaTag.setValue(javaValue); tags.add(javaTag); } else { From cdab1ce5ec32d69c29f5119cb1cc7703177ac21f Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Sat, 7 Dec 2019 14:56:00 -0900 Subject: [PATCH 026/109] Translate window properties Furnace and brewing stand --- .../BrewingStandInventoryTranslator.java | 17 +++++++++++++---- .../inventory/FurnaceInventoryTranslator.java | 13 ++++++++----- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingStandInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingStandInventoryTranslator.java index e6089cb8..91f9d327 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingStandInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingStandInventoryTranslator.java @@ -36,22 +36,31 @@ public class BrewingStandInventoryTranslator extends BlockInventoryTranslator { super(5, 117 << 4, ContainerType.BREWING_STAND); } + @Override + public void openInventory(GeyserSession session, Inventory inventory) { + super.openInventory(session, inventory); + ContainerSetDataPacket dataPacket = new ContainerSetDataPacket(); + dataPacket.setWindowId((byte) inventory.getId()); + dataPacket.setProperty(ContainerSetDataPacket.BREWING_STAND_FUEL_TOTAL); + dataPacket.setValue(20); + session.getUpstream().sendPacket(dataPacket); + } + @Override public void updateProperty(GeyserSession session, Inventory inventory, int key, int value) { - //bedrock protocol library is currently missing property mappings for windows. ContainerSetDataPacket dataPacket = new ContainerSetDataPacket(); dataPacket.setWindowId((byte) inventory.getId()); switch (key) { case 0: - dataPacket.setProperty(ContainerSetDataPacket.Property.BREWING_STAND_BREW_TIME); + dataPacket.setProperty(ContainerSetDataPacket.BREWING_STAND_BREW_TIME); break; case 1: - dataPacket.setProperty(ContainerSetDataPacket.Property.BREWING_STAND_FUEL_AMOUNT); + dataPacket.setProperty(ContainerSetDataPacket.BREWING_STAND_FUEL_AMOUNT); break; default: return; } - dataPacket.setValue((short) value); + dataPacket.setValue(value); session.getUpstream().sendPacket(dataPacket); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java index 95d78562..12a634ff 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java @@ -25,6 +25,7 @@ package org.geysermc.connector.network.translators.inventory; +import com.github.steveice10.mc.protocol.data.game.window.WindowType; import com.nukkitx.protocol.bedrock.data.ContainerType; import com.nukkitx.protocol.bedrock.packet.ContainerSetDataPacket; import org.geysermc.connector.inventory.Inventory; @@ -37,23 +38,25 @@ public class FurnaceInventoryTranslator extends BlockInventoryTranslator { @Override public void updateProperty(GeyserSession session, Inventory inventory, int key, int value) { - //bedrock protocol library is currently missing property mappings for windows. only the furnace arrow will update for now ContainerSetDataPacket dataPacket = new ContainerSetDataPacket(); dataPacket.setWindowId((byte) inventory.getId()); switch (key) { case 0: - dataPacket.setProperty(ContainerSetDataPacket.Property.FURNACE_LIT_TIME); + dataPacket.setProperty(ContainerSetDataPacket.FURNACE_LIT_TIME); break; case 1: - dataPacket.setProperty(ContainerSetDataPacket.Property.FURNACE_LIT_DURATION); + dataPacket.setProperty(ContainerSetDataPacket.FURNACE_LIT_DURATION); break; case 2: - dataPacket.setProperty(ContainerSetDataPacket.Property.FURNACE_TICK_COUNT); + dataPacket.setProperty(ContainerSetDataPacket.FURNACE_TICK_COUNT); + if (inventory.getWindowType() == WindowType.BLAST_FURNACE || inventory.getWindowType() == WindowType.SMOKER) { + value *= 2; + } break; default: return; } - dataPacket.setValue((short) value); + dataPacket.setValue(value); session.getUpstream().sendPacket(dataPacket); } From f524407c1d47ef160c737467e02a475aefbcc625 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Sat, 7 Dec 2019 15:06:56 -0900 Subject: [PATCH 027/109] Fix brewing --- .../translators/java/JavaDeclareRecipesTranslator.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java index 5cc98c3f..9015fc28 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java @@ -33,6 +33,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.server.ServerDeclareRecip import com.nukkitx.nbt.tag.CompoundTag; import com.nukkitx.protocol.bedrock.data.CraftingData; import com.nukkitx.protocol.bedrock.data.ItemData; +import com.nukkitx.protocol.bedrock.data.PotionMixData; import com.nukkitx.protocol.bedrock.packet.CraftingDataPacket; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; @@ -49,6 +50,8 @@ import java.util.stream.Collectors; public class JavaDeclareRecipesTranslator extends PacketTranslator { + private final int[] brewingIngredients = new int[]{372, 331, 348, 376, 289, 437, 353, 414, 382, 375, 462, 378, 396, 377, 370, 469, 470}; + @Override public void translate(ServerDeclareRecipesPacket packet, GeyserSession session) { CraftingDataPacket craftingDataPacket = new CraftingDataPacket(); @@ -80,6 +83,9 @@ public class JavaDeclareRecipesTranslator extends PacketTranslator Date: Sat, 21 Dec 2019 01:32:49 -0900 Subject: [PATCH 028/109] Handle new creative_items.json format --- .../src/main/java/org/geysermc/connector/utils/Toolbox.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java index 3b0d02a2..c47256da 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java +++ b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java @@ -116,7 +116,7 @@ public class Toolbox { List> creativeItemEntries = new ArrayList<>(); try { - creativeItemEntries = creativeItemMapper.readValue(creativeItemStream, ArrayList.class); + creativeItemEntries = (ArrayList>) creativeItemMapper.readValue(creativeItemStream, HashMap.class).get("items"); } catch (Exception e) { e.printStackTrace(); } From 20595a6e03c323450ce7200ceeca2d05aab60ad8 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Sat, 21 Dec 2019 01:35:34 -0900 Subject: [PATCH 029/109] Exclude Edu items from creative --- .../resources/bedrock/creative_items.json | 372 ------------------ 1 file changed, 372 deletions(-) diff --git a/connector/src/main/resources/bedrock/creative_items.json b/connector/src/main/resources/bedrock/creative_items.json index d55839ba..8045b219 100644 --- a/connector/src/main/resources/bedrock/creative_items.json +++ b/connector/src/main/resources/bedrock/creative_items.json @@ -3008,21 +3008,6 @@ { "id" : -198 }, - { - "id" : 238, - "damage" : 8 - }, - { - "id" : 238 - }, - { - "id" : 238, - "damage" : 12 - }, - { - "id" : 238, - "damage" : 4 - }, { "id" : 379 }, @@ -3419,363 +3404,6 @@ { "id" : 386 }, - { - "id" : 36 - }, - { - "id" : -12 - }, - { - "id" : -13 - }, - { - "id" : -14 - }, - { - "id" : -15 - }, - { - "id" : -16 - }, - { - "id" : -17 - }, - { - "id" : -18 - }, - { - "id" : -19 - }, - { - "id" : -20 - }, - { - "id" : -21 - }, - { - "id" : -22 - }, - { - "id" : -23 - }, - { - "id" : -24 - }, - { - "id" : -25 - }, - { - "id" : -26 - }, - { - "id" : -27 - }, - { - "id" : -28 - }, - { - "id" : -29 - }, - { - "id" : -30 - }, - { - "id" : -31 - }, - { - "id" : -32 - }, - { - "id" : -33 - }, - { - "id" : -34 - }, - { - "id" : -35 - }, - { - "id" : -36 - }, - { - "id" : -37 - }, - { - "id" : -38 - }, - { - "id" : -39 - }, - { - "id" : -40 - }, - { - "id" : -41 - }, - { - "id" : -42 - }, - { - "id" : -43 - }, - { - "id" : -44 - }, - { - "id" : -45 - }, - { - "id" : -46 - }, - { - "id" : -47 - }, - { - "id" : -48 - }, - { - "id" : -49 - }, - { - "id" : -50 - }, - { - "id" : -51 - }, - { - "id" : -52 - }, - { - "id" : -53 - }, - { - "id" : -54 - }, - { - "id" : -55 - }, - { - "id" : -56 - }, - { - "id" : -57 - }, - { - "id" : -58 - }, - { - "id" : -59 - }, - { - "id" : -60 - }, - { - "id" : -61 - }, - { - "id" : -62 - }, - { - "id" : -63 - }, - { - "id" : -64 - }, - { - "id" : -65 - }, - { - "id" : -66 - }, - { - "id" : -67 - }, - { - "id" : -68 - }, - { - "id" : -69 - }, - { - "id" : -70 - }, - { - "id" : -71 - }, - { - "id" : -72 - }, - { - "id" : -73 - }, - { - "id" : -74 - }, - { - "id" : -75 - }, - { - "id" : -76 - }, - { - "id" : -77 - }, - { - "id" : -78 - }, - { - "id" : -79 - }, - { - "id" : -80 - }, - { - "id" : -81 - }, - { - "id" : -82 - }, - { - "id" : -83 - }, - { - "id" : -84 - }, - { - "id" : -85 - }, - { - "id" : -86 - }, - { - "id" : -87 - }, - { - "id" : -88 - }, - { - "id" : -89 - }, - { - "id" : -90 - }, - { - "id" : -91 - }, - { - "id" : -92 - }, - { - "id" : -93 - }, - { - "id" : -94 - }, - { - "id" : -95 - }, - { - "id" : -96 - }, - { - "id" : -97 - }, - { - "id" : -98 - }, - { - "id" : -99 - }, - { - "id" : -100 - }, - { - "id" : -101 - }, - { - "id" : -102 - }, - { - "id" : -103 - }, - { - "id" : -104 - }, - { - "id" : -105 - }, - { - "id" : -106 - }, - { - "id" : -107 - }, - { - "id" : -108 - }, - { - "id" : -109 - }, - { - "id" : -110 - }, - { - "id" : -111 - }, - { - "id" : -112 - }, - { - "id" : -113 - }, - { - "id" : -114 - }, - { - "id" : -115 - }, - { - "id" : -116 - }, - { - "id" : -117 - }, - { - "id" : -118 - }, - { - "id" : -119 - }, - { - "id" : -120 - }, - { - "id" : -121 - }, - { - "id" : -122 - }, - { - "id" : -123 - }, - { - "id" : -124 - }, - { - "id" : -125 - }, - { - "id" : -126 - }, - { - "id" : -127 - }, - { - "id" : -128 - }, - { - "id" : -129 - }, { "id" : 403, "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZAAAAAA=" From 46205600dd38e86ac579495f2ce11659fa3e5757 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Mon, 23 Dec 2019 17:00:31 -0900 Subject: [PATCH 030/109] Fix block ids --- .../network/translators/TranslatorsInit.java | 8 ++++---- .../inventory/AnvilInventoryTranslator.java | 2 +- .../inventory/BlockInventoryTranslator.java | 10 +++++----- .../inventory/BrewingStandInventoryTranslator.java | 2 +- .../inventory/DoubleChestInventoryTranslator.java | 11 +++++------ .../inventory/EnchantmentInventoryTranslator.java | 2 +- .../inventory/FurnaceInventoryTranslator.java | 2 +- .../inventory/SingleChestInventoryTranslator.java | 2 +- 8 files changed, 19 insertions(+), 20 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java index 77a4fa12..31559d96 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java @@ -183,9 +183,9 @@ public class TranslatorsInit { inventoryTranslators.put(WindowType.BLAST_FURNACE, furnace); inventoryTranslators.put(WindowType.SMOKER, furnace); - inventoryTranslators.put(WindowType.GENERIC_3X3, new BlockInventoryTranslator(9, 23 << 4, ContainerType.DISPENSER)); - inventoryTranslators.put(WindowType.HOPPER, new BlockInventoryTranslator(5, 154 << 4, ContainerType.HOPPER)); - inventoryTranslators.put(WindowType.SHULKER_BOX, new BlockInventoryTranslator(27, 205 << 4, ContainerType.CONTAINER)); - //inventoryTranslators.put(WindowType.BEACON, new BlockInventoryTranslator(1, 138 << 4, ContainerType.BEACON)); //TODO + inventoryTranslators.put(WindowType.GENERIC_3X3, new BlockInventoryTranslator(9, "minecraft:dispenser[facing=north,triggered=false]", ContainerType.DISPENSER)); + inventoryTranslators.put(WindowType.HOPPER, new BlockInventoryTranslator(5, "minecraft:hopper[enabled=false,facing=down]", ContainerType.HOPPER)); + inventoryTranslators.put(WindowType.SHULKER_BOX, new BlockInventoryTranslator(27, "minecraft:shulker_box[facing=north]", ContainerType.CONTAINER)); + //inventoryTranslators.put(WindowType.BEACON, new BlockInventoryTranslator(1, "minecraft:beacon", ContainerType.BEACON)); //TODO } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java index 33815596..115a7dbd 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java @@ -31,7 +31,7 @@ import com.nukkitx.protocol.bedrock.data.InventoryAction; public class AnvilInventoryTranslator extends BlockInventoryTranslator { public AnvilInventoryTranslator() { - super(3, 145 << 4, ContainerType.ANVIL); + super(3, "minecraft:anvil[facing=north]", ContainerType.ANVIL); } @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BlockInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BlockInventoryTranslator.java index 0112dc9e..54ab9bce 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BlockInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BlockInventoryTranslator.java @@ -34,16 +34,16 @@ import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.TranslatorsInit; import org.geysermc.connector.network.translators.block.BlockEntry; -import org.geysermc.connector.world.GlobalBlockPalette; public class BlockInventoryTranslator extends ContainerInventoryTranslator { final int blockId; private final ContainerType containerType; - public BlockInventoryTranslator(int size, int blockId, ContainerType containerType) { + public BlockInventoryTranslator(int size, String javaBlockIdentifier, ContainerType containerType) { super(size); - this.blockId = blockId; + this.blockId = TranslatorsInit.getBlockTranslator().getBlockEntry(javaBlockIdentifier).getBedrockRuntimeId(); this.containerType = containerType; } @@ -54,7 +54,7 @@ public class BlockInventoryTranslator extends ContainerInventoryTranslator { UpdateBlockPacket blockPacket = new UpdateBlockPacket(); blockPacket.setDataLayer(0); blockPacket.setBlockPosition(position); - blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(blockId)); + blockPacket.setRuntimeId(blockId); blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); session.getUpstream().sendPacket(blockPacket); inventory.setHolderPosition(position); @@ -88,7 +88,7 @@ public class BlockInventoryTranslator extends ContainerInventoryTranslator { UpdateBlockPacket blockPacket = new UpdateBlockPacket(); blockPacket.setDataLayer(0); blockPacket.setBlockPosition(holderPos); - blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(realBlock.getBedrockId() << 4 | realBlock.getBedrockData())); + blockPacket.setRuntimeId(realBlock.getBedrockRuntimeId()); session.getUpstream().sendPacket(blockPacket); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingStandInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingStandInventoryTranslator.java index 91f9d327..532928e6 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingStandInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingStandInventoryTranslator.java @@ -33,7 +33,7 @@ import org.geysermc.connector.network.session.GeyserSession; public class BrewingStandInventoryTranslator extends BlockInventoryTranslator { public BrewingStandInventoryTranslator() { - super(5, 117 << 4, ContainerType.BREWING_STAND); + super(5, "minecraft:brewing_stand[has_bottle_0=false,has_bottle_1=false,has_bottle_2=false]", ContainerType.BREWING_STAND); } @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java index 6c5057bb..e0825ed8 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java @@ -37,11 +37,10 @@ import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.TranslatorsInit; import org.geysermc.connector.network.translators.block.BlockEntry; -import org.geysermc.connector.world.GlobalBlockPalette; public class DoubleChestInventoryTranslator extends BlockInventoryTranslator { public DoubleChestInventoryTranslator(int size) { - super(size, 54 << 4, ContainerType.CONTAINER); + super(size, "minecraft:chest[facing=north,type=single,waterlogged=false]", ContainerType.CONTAINER); } @Override @@ -51,7 +50,7 @@ public class DoubleChestInventoryTranslator extends BlockInventoryTranslator { UpdateBlockPacket blockPacket = new UpdateBlockPacket(); blockPacket.setDataLayer(0); blockPacket.setBlockPosition(position); - blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(blockId)); + blockPacket.setRuntimeId(blockId); blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); session.getUpstream().sendPacket(blockPacket); @@ -71,7 +70,7 @@ public class DoubleChestInventoryTranslator extends BlockInventoryTranslator { blockPacket = new UpdateBlockPacket(); blockPacket.setDataLayer(0); blockPacket.setBlockPosition(pairPosition); - blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(blockId)); + blockPacket.setRuntimeId(blockId); blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); session.getUpstream().sendPacket(blockPacket); @@ -99,7 +98,7 @@ public class DoubleChestInventoryTranslator extends BlockInventoryTranslator { UpdateBlockPacket blockPacket = new UpdateBlockPacket(); blockPacket.setDataLayer(0); blockPacket.setBlockPosition(holderPos); - blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(realBlock.getBedrockId() << 4 | realBlock.getBedrockData())); + blockPacket.setRuntimeId(realBlock.getBedrockRuntimeId()); session.getUpstream().sendPacket(blockPacket); holderPos = holderPos.add(Vector3i.UNIT_X); @@ -108,7 +107,7 @@ public class DoubleChestInventoryTranslator extends BlockInventoryTranslator { blockPacket = new UpdateBlockPacket(); blockPacket.setDataLayer(0); blockPacket.setBlockPosition(holderPos); - blockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(realBlock.getBedrockId() << 4 | realBlock.getBedrockData())); + blockPacket.setRuntimeId(realBlock.getBedrockRuntimeId()); session.getUpstream().sendPacket(blockPacket); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/EnchantmentInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/EnchantmentInventoryTranslator.java index 410bdc6a..0b4ed4ba 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/EnchantmentInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/EnchantmentInventoryTranslator.java @@ -31,7 +31,7 @@ import org.geysermc.connector.network.session.GeyserSession; public class EnchantmentInventoryTranslator extends BlockInventoryTranslator { public EnchantmentInventoryTranslator() { - super(2, 116 << 4, ContainerType.ENCHANTMENT); + super(2, "minecraft:enchanting_table", ContainerType.ENCHANTMENT); } @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java index 12a634ff..a2eefac4 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java @@ -33,7 +33,7 @@ import org.geysermc.connector.network.session.GeyserSession; public class FurnaceInventoryTranslator extends BlockInventoryTranslator { public FurnaceInventoryTranslator() { - super(3, 61 << 4, ContainerType.FURNACE); + super(3, "minecraft:furnace[facing=north,lit=false]", ContainerType.FURNACE); } @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java index 3b2c70d9..16111708 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java @@ -34,7 +34,7 @@ import org.geysermc.connector.network.translators.TranslatorsInit; public class SingleChestInventoryTranslator extends BlockInventoryTranslator { public SingleChestInventoryTranslator(int size) { - super(size, 54 << 4, ContainerType.CONTAINER); + super(size, "minecraft:chest[facing=north,type=single,waterlogged=false]", ContainerType.CONTAINER); } @Override From da8bd8a6599bd6d945c903da03bb37c07ef5d053 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Mon, 30 Dec 2019 21:55:17 -0600 Subject: [PATCH 031/109] Actually fix signs and start on campfire/container translators Since signs are not sent as block (tile) entities in chunks when it comes to later Minecraft versions, caching and sending the signs after the chunk packet has been sent was the only way to fix this. Sign data sending has intentionally been delayed in JavaUpdateTileEntityTranslator in the event that a chunk takes a long time to send and the block entity data is sent first. --- .../network/translators/TranslatorsInit.java | 6 +- .../block/entity/BlockEntityTranslator.java | 19 ++-- .../ContainerBlockEntityTranslator.java | 92 +++++++++++++++++++ .../entity/EmptyBlockEntityTranslator.java | 8 +- .../entity/SignBlockEntityTranslator.java | 12 ++- .../translators/item/ItemTranslator.java | 8 ++ .../java/world/JavaChunkDataTranslator.java | 18 +++- .../world/JavaUpdateTileEntityTranslator.java | 23 +++-- .../connector/utils/BlockEntityUtils.java | 17 +++- .../geysermc/connector/utils/ChunkUtils.java | 53 ++++++----- .../connector/world/chunk/ChunkPosition.java | 14 +-- 11 files changed, 204 insertions(+), 66 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ContainerBlockEntityTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java index 072b7aed..477734d8 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java @@ -46,6 +46,7 @@ import lombok.Getter; import org.geysermc.connector.network.translators.bedrock.*; import org.geysermc.connector.network.translators.block.BlockTranslator; import org.geysermc.connector.network.translators.block.entity.BlockEntityTranslator; +import org.geysermc.connector.network.translators.block.entity.ContainerBlockEntityTranslator; import org.geysermc.connector.network.translators.block.entity.EmptyBlockEntityTranslator; import org.geysermc.connector.network.translators.block.entity.SignBlockEntityTranslator; import org.geysermc.connector.network.translators.inventory.GenericInventoryTranslator; @@ -174,8 +175,9 @@ public class TranslatorsInit { } private static void registerBlockEntityTranslators() { - blockEntityTranslators.put("Empty", new EmptyBlockEntityTranslator()); - blockEntityTranslators.put("Sign", new SignBlockEntityTranslator()); + blockEntityTranslators.put("Empty", new EmptyBlockEntityTranslator("empty", "Empty")); + blockEntityTranslators.put("Sign", new SignBlockEntityTranslator("minecraft:sign", "Sign")); + blockEntityTranslators.put("Campfire", new ContainerBlockEntityTranslator("minecraft:campfire", "Campfire")); } private static void registerInventoryTranslators() { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java index 61d3fd08..e5e3a50d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java @@ -30,43 +30,48 @@ import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.nukkitx.nbt.CompoundTagBuilder; import com.nukkitx.nbt.tag.Tag; -import org.geysermc.connector.utils.BlockEntityUtils; + +import lombok.AllArgsConstructor; import java.util.List; +@AllArgsConstructor public abstract class BlockEntityTranslator { + protected String javaId; + protected String bedrockId; + public abstract List> translateTag(CompoundTag tag); public abstract CompoundTag getDefaultJavaTag(int x, int y, int z); public abstract com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(int x, int y, int z); - public com.nukkitx.nbt.tag.CompoundTag getBlockEntityTag(CompoundTag tag, String id) { + public com.nukkitx.nbt.tag.CompoundTag getBlockEntityTag(CompoundTag tag) { int x = Integer.parseInt(String.valueOf(tag.getValue().get("x").getValue())); int y = Integer.parseInt(String.valueOf(tag.getValue().get("y").getValue())); int z = Integer.parseInt(String.valueOf(tag.getValue().get("z").getValue())); - CompoundTagBuilder tagBuilder = getConstantBedrockTag(id, x, y, z).toBuilder(); + CompoundTagBuilder tagBuilder = getConstantBedrockTag(x, y, z).toBuilder(); translateTag(tag).forEach(tagBuilder::tag); return tagBuilder.buildRootTag(); } - protected CompoundTag getConstantJavaTag(String id, int x, int y, int z) { + protected CompoundTag getConstantJavaTag(int x, int y, int z) { CompoundTag tag = new CompoundTag(""); tag.put(new IntTag("x", x)); tag.put(new IntTag("y", y)); tag.put(new IntTag("z", z)); - tag.put(new StringTag("id", id)); + tag.put(new StringTag("id", javaId)); return tag; } - protected com.nukkitx.nbt.tag.CompoundTag getConstantBedrockTag(String id, int x, int y, int z) { + protected com.nukkitx.nbt.tag.CompoundTag getConstantBedrockTag(int x, int y, int z) { CompoundTagBuilder tagBuilder = CompoundTagBuilder.builder() .intTag("x", x) .intTag("y", y) .intTag("z", z) - .stringTag("id", id); + .stringTag("id", bedrockId); return tagBuilder.buildRootTag(); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ContainerBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ContainerBlockEntityTranslator.java new file mode 100644 index 00000000..18168348 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ContainerBlockEntityTranslator.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.block.entity; + +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.ListTag; +import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.tag.IntArrayTag; +import com.nukkitx.nbt.tag.Tag; + +import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.item.ItemEntry; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class ContainerBlockEntityTranslator extends BlockEntityTranslator { + + public ContainerBlockEntityTranslator(String javaId, String bedrockId) { + super(javaId, bedrockId); + } + + @Override + public List> translateTag(CompoundTag tag) { + List> tags = new ArrayList<>(); + ListTag items = tag.get("Items"); + List tagsList = new ArrayList<>(); + for (com.github.steveice10.opennbt.tag.builtin.Tag itemTag : items.getValue()) { + tagsList.add(getItem((CompoundTag) itemTag)); + } + + int[] fakeCookingTime = new int[4]; + Arrays.fill(fakeCookingTime, 3); + + com.nukkitx.nbt.tag.ListTag bedrockItems = + new com.nukkitx.nbt.tag.ListTag<>("Items", com.nukkitx.nbt.tag.CompoundTag.class, tagsList); + tags.add(bedrockItems); + + tags.add(new IntArrayTag("CookingTimes", fakeCookingTime)); + tags.add(new IntArrayTag("CookingTotalTimes", fakeCookingTime)); + return tags; + } + + @Override + public CompoundTag getDefaultJavaTag(int x, int y, int z) { + CompoundTag tag = getConstantJavaTag(x, y, z); + tag.put(new ListTag("Items")); + return tag; + } + + @Override + public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(int x, int y, int z) { + CompoundTagBuilder tagBuilder = getConstantBedrockTag(x, y, z).toBuilder(); + tagBuilder.listTag("Items", com.nukkitx.nbt.tag.CompoundTag.class, new ArrayList<>()); + return tagBuilder.buildRootTag(); + } + + protected com.nukkitx.nbt.tag.CompoundTag getItem(CompoundTag tag) { + ItemEntry entry = TranslatorsInit.getItemTranslator().getItemEntry((String) tag.get("id").getValue()); + CompoundTagBuilder tagBuilder = CompoundTagBuilder.builder() + .shortTag("id", (short) entry.getBedrockId()) + .byteTag("Count", (byte) tag.get("Count").getValue()) + .shortTag("Damage", (short) entry.getBedrockData()) + .byteTag("Slot", (byte) tag.get("Slot").getValue()) + .tag(CompoundTagBuilder.builder().build("tag")); + return tagBuilder.buildRootTag(); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java index 927337bc..700b50db 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java @@ -33,6 +33,10 @@ import java.util.List; public class EmptyBlockEntityTranslator extends BlockEntityTranslator { + public EmptyBlockEntityTranslator(String javaId, String bedrockId) { + super(javaId, bedrockId); + } + @Override public List> translateTag(CompoundTag tag) { return new ArrayList<>(); @@ -40,11 +44,11 @@ public class EmptyBlockEntityTranslator extends BlockEntityTranslator { @Override public CompoundTag getDefaultJavaTag(int x, int y, int z) { - return getConstantJavaTag("empty", x, y, z); + return getConstantJavaTag(x, y, z); } @Override public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(int x, int y, int z) { - return getConstantBedrockTag("Empty", x, y, z); + return getConstantBedrockTag(x, y, z); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java index 182eedd9..7029143b 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java @@ -28,9 +28,9 @@ package org.geysermc.connector.network.translators.block.entity; import com.github.steveice10.mc.protocol.data.message.Message; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.nukkitx.nbt.CompoundTagBuilder; -import com.nukkitx.nbt.tag.ByteTag; import com.nukkitx.nbt.tag.StringTag; import com.nukkitx.nbt.tag.Tag; + import org.geysermc.connector.utils.MessageUtils; import java.util.ArrayList; @@ -38,6 +38,10 @@ import java.util.List; public class SignBlockEntityTranslator extends BlockEntityTranslator { + public SignBlockEntityTranslator(String javaId, String bedrockId) { + super(javaId, bedrockId); + } + @Override public List> translateTag(CompoundTag tag) { List> tags = new ArrayList<>(); @@ -53,13 +57,12 @@ public class SignBlockEntityTranslator extends BlockEntityTranslator { + "\n" + MessageUtils.getBedrockMessage(Message.fromString(line4)) )); - tags.add(new ByteTag("isMovable", (byte) 0)); return tags; } @Override public CompoundTag getDefaultJavaTag(int x, int y, int z) { - CompoundTag tag = getConstantJavaTag("minecraft:sign", x, y, z); + CompoundTag tag = getConstantJavaTag(x, y, z); tag.put(new com.github.steveice10.opennbt.tag.builtin.StringTag("Text1", "{\"text\":\"\"}")); tag.put(new com.github.steveice10.opennbt.tag.builtin.StringTag("Text2", "{\"text\":\"\"}")); tag.put(new com.github.steveice10.opennbt.tag.builtin.StringTag("Text3", "{\"text\":\"\"}")); @@ -69,9 +72,8 @@ public class SignBlockEntityTranslator extends BlockEntityTranslator { @Override public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(int x, int y, int z) { - CompoundTagBuilder tagBuilder = getConstantBedrockTag("Sign", x, y, z).toBuilder(); + CompoundTagBuilder tagBuilder = getConstantBedrockTag(x, y, z).toBuilder(); tagBuilder.stringTag("Text", ""); - tagBuilder.byteTag("isMovable", (byte) 0); return tagBuilder.buildRootTag(); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java index 20421059..22f2c9f1 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java @@ -41,6 +41,7 @@ import com.github.steveice10.opennbt.tag.builtin.ShortTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import com.nukkitx.protocol.bedrock.data.ItemData; + import org.geysermc.connector.console.GeyserLogger; import org.geysermc.connector.utils.MessageUtils; import org.geysermc.connector.utils.Toolbox; @@ -52,6 +53,8 @@ import java.util.Map; public class ItemTranslator { + private Map javaIdentifierMap = new HashMap<>(); + public ItemStack translateToJava(ItemData data) { ItemEntry javaItem = getItem(data); @@ -89,6 +92,11 @@ public class ItemTranslator { return ItemEntry.AIR; } + public ItemEntry getItemEntry(String javaIdentifier) { + return javaIdentifierMap.computeIfAbsent(javaIdentifier, key -> Toolbox.ITEM_ENTRIES.values() + .stream().filter(itemEntry -> itemEntry.getJavaIdentifier().equals(key)).findFirst().orElse(null)); + } + private CompoundTag translateToJavaNBT(com.nukkitx.nbt.tag.CompoundTag tag) { CompoundTag javaTag = new CompoundTag(tag.getName()); Map javaValue = javaTag.getValue(); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java index 1c83579a..c7c9af5b 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java @@ -1,5 +1,7 @@ package org.geysermc.connector.network.translators.java.world; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerChunkDataPacket; import com.nukkitx.math.vector.Vector2i; import com.nukkitx.math.vector.Vector3f; @@ -9,9 +11,13 @@ import com.nukkitx.nbt.tag.CompoundTag; import com.nukkitx.network.VarInts; import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket; import com.nukkitx.protocol.bedrock.packet.NetworkChunkPublisherUpdatePacket; + import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufOutputStream; import io.netty.buffer.Unpooled; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; + import org.geysermc.api.Geyser; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; @@ -22,7 +28,6 @@ public class JavaChunkDataTranslator extends PacketTranslator { Vector2i chunkPos = session.getLastChunkPosition(); Vector3f position = session.getPlayerEntity().getPosition(); @@ -33,7 +38,6 @@ public class JavaChunkDataTranslator extends PacketTranslator blockEntityEntry : chunkData.signs.int2ObjectEntrySet()) { + int x = blockEntityEntry.getValue().getAsInt("x"); + int y = blockEntityEntry.getValue().getAsInt("y"); + int z = blockEntityEntry.getValue().getAsInt("z"); + + ChunkUtils.updateBlock(session, new BlockState(blockEntityEntry.getIntKey()), new Position(x, y, z)); + } + chunkData.signs.clear(); } catch (Exception ex) { ex.printStackTrace(); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java index 2b55e27e..20601104 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java @@ -26,26 +26,29 @@ package org.geysermc.connector.network.translators.java.world; import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerUpdateTileEntityPacket; -import com.nukkitx.math.vector.Vector3i; -import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; + import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.block.entity.BlockEntityTranslator; import org.geysermc.connector.utils.BlockEntityUtils; +import java.util.concurrent.TimeUnit; + public class JavaUpdateTileEntityTranslator extends PacketTranslator { @Override public void translate(ServerUpdateTileEntityPacket packet, GeyserSession session) { - BlockEntityDataPacket blockEntityPacket = new BlockEntityDataPacket(); - blockEntityPacket.setBlockPosition(Vector3i.from(packet.getPosition().getX(), - packet.getPosition().getY(), - packet.getPosition().getZ()) - ); - String id = BlockEntityUtils.getBedrockBlockEntityId(packet.getType().name()); BlockEntityTranslator translator = BlockEntityUtils.getBlockEntityTranslator(id); - blockEntityPacket.setData(translator.getBlockEntityTag(packet.getNbt(), id)); - session.getUpstream().sendPacket(blockEntityPacket); + if (id.equalsIgnoreCase("Sign")) { + // Delay so chunks can finish sending + session.getConnector().getGeneralThreadPool().schedule(() -> + BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag(packet.getNbt()), packet.getPosition()), + 5, + TimeUnit.SECONDS + ); + } else { + BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag(packet.getNbt()), packet.getPosition()); + } } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java index 6fb62b55..f610f271 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java @@ -1,5 +1,10 @@ package org.geysermc.connector.utils; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; +import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; + +import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.TranslatorsInit; import org.geysermc.connector.network.translators.block.entity.BlockEntityTranslator; @@ -10,8 +15,9 @@ public class BlockEntityUtils { if (id.contains("piston_head")) return "PistonArm"; - id = id.replace("minecraft:", ""); - id = id.replace("_", " "); + id = id.toLowerCase() + .replace("minecraft:", "") + .replace("_", " "); String[] words = id.split(" "); for (int i = 0; i < words.length; i++) { words[i] = words[i].substring(0, 1).toUpperCase() + words[i].substring(1).toLowerCase(); @@ -29,4 +35,11 @@ public class BlockEntityUtils { return blockEntityTranslator; } + + public static void updateBlockEntity(GeyserSession session, com.nukkitx.nbt.tag.CompoundTag blockEntity, Position position) { + BlockEntityDataPacket blockEntityPacket = new BlockEntityDataPacket(); + blockEntityPacket.setBlockPosition(Vector3i.from(position.getX(), position.getY(), position.getZ())); + blockEntityPacket.setData(blockEntity); + session.getUpstream().sendPacket(blockEntityPacket); + } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java index cf214625..0059b523 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -3,35 +3,31 @@ package org.geysermc.connector.utils; import com.github.steveice10.mc.protocol.data.game.chunk.Chunk; import com.github.steveice10.mc.protocol.data.game.chunk.Column; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockChangeRecord; import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; -import org.geysermc.connector.console.GeyserLogger; import com.nukkitx.math.vector.Vector3i; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + +import org.geysermc.connector.console.GeyserLogger; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.TranslatorsInit; import org.geysermc.connector.network.translators.block.BlockEntry; import org.geysermc.connector.network.translators.block.entity.BlockEntityTranslator; -import org.geysermc.connector.network.translators.block.entity.SignBlockEntityTranslator; +import org.geysermc.connector.world.chunk.ChunkPosition; import org.geysermc.connector.world.chunk.ChunkSection; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - public class ChunkUtils { public static ChunkData translateToBedrock(Column column) { ChunkData chunkData = new ChunkData(); - Chunk[] chunks = column.getChunks(); - int chunkSectionCount = chunks.length; - chunkData.sections = new ChunkSection[chunkSectionCount]; + chunkData.sections = new ChunkSection[chunks.length]; - List blockEntities = new ArrayList<>(Arrays.asList(column.getTileEntities())); - for (int chunkY = 0; chunkY < chunkSectionCount; chunkY++) { + CompoundTag[] blockEntities = column.getTileEntities(); + for (int chunkY = 0; chunkY < chunks.length; chunkY++) { chunkData.sections[chunkY] = new ChunkSection(); Chunk chunk = chunks[chunkY]; @@ -39,15 +35,17 @@ public class ChunkUtils { continue; ChunkSection section = chunkData.sections[chunkY]; - for (int x = 0; x < 16; x++) { for (int y = 0; y < 16; y++) { for (int z = 0; z < 16; z++) { BlockState blockState = chunk.get(x, y, z); BlockEntry block = TranslatorsInit.getBlockTranslator().getBlockEntry(blockState); - - section.getBlockStorageArray()[0].setFullBlock(ChunkSection.blockPosition(x, y, z), - block.getBedrockRuntimeId()); + if (block.getJavaIdentifier().contains("sign[")) { + Position pos = new ChunkPosition(column.getX(), column.getZ()).getBlock(x, (chunkY << 4) + y, z); + chunkData.signs.put(block.getJavaId(), TranslatorsInit.getBlockEntityTranslators().get("Sign").getDefaultBedrockTag(pos.getX(), pos.getY(), pos.getZ())); + } else { + section.getBlockStorageArray()[0].setFullBlock(ChunkSection.blockPosition(x, y, z), block.getBedrockRuntimeId()); + } if (block.isWaterlogged()) { BlockEntry water = TranslatorsInit.getBlockTranslator().getBlockEntry("minecraft:water[level=0]"); @@ -58,17 +56,20 @@ public class ChunkUtils { } } - List bedrockBlockEntities = new ArrayList<>(); - for (CompoundTag tag : blockEntities) { - Tag idTag = tag.get("id"); - if (idTag == null && !tag.contains("Sign")) { + com.nukkitx.nbt.tag.CompoundTag[] bedrockBlockEntities = new com.nukkitx.nbt.tag.CompoundTag[blockEntities.length]; + for (int i = 0; i < bedrockBlockEntities.length; i++) { + CompoundTag tag = blockEntities[i]; + String tagName; + if (!tag.contains("id")) { GeyserLogger.DEFAULT.debug("Got tag with no id: " + tag.getValue()); - continue; + tagName = "Empty"; + } else { + tagName = (String) tag.get("id").getValue(); } - String id = idTag == null ? "Sign" : BlockEntityUtils.getBedrockBlockEntityId((String) idTag.getValue()); + String id = BlockEntityUtils.getBedrockBlockEntityId(tagName); BlockEntityTranslator blockEntityTranslator = BlockEntityUtils.getBlockEntityTranslator(id); - bedrockBlockEntities.add(blockEntityTranslator.getBlockEntityTag(tag, id)); + bedrockBlockEntities[i] = blockEntityTranslator.getBlockEntityTag(tag); } chunkData.blockEntities = bedrockBlockEntities; @@ -102,6 +103,8 @@ public class ChunkUtils { public ChunkSection[] sections; public byte[] biomes = new byte[256]; - public List blockEntities = new ArrayList<>(); + public com.nukkitx.nbt.tag.CompoundTag[] blockEntities = new com.nukkitx.nbt.tag.CompoundTag[0]; + + public Int2ObjectMap signs = new Int2ObjectOpenHashMap<>(); } } diff --git a/connector/src/main/java/org/geysermc/connector/world/chunk/ChunkPosition.java b/connector/src/main/java/org/geysermc/connector/world/chunk/ChunkPosition.java index 86da2da4..4af2bcc2 100644 --- a/connector/src/main/java/org/geysermc/connector/world/chunk/ChunkPosition.java +++ b/connector/src/main/java/org/geysermc/connector/world/chunk/ChunkPosition.java @@ -18,17 +18,9 @@ public class ChunkPosition { } public Position getChunkBlock(int x, int y, int z) { - int chunkX = x % 16; - int chunkY = y % 16; - int chunkZ = z % 16; - - if (chunkX < 0) - chunkX = -chunkX; - if (chunkY < 0) - chunkY = -chunkY; - if (chunkZ < 0) - chunkZ = -chunkZ; - + int chunkX = x & 15; + int chunkY = y & 15; + int chunkZ = z & 15; return new Position(chunkX, chunkY, chunkZ); } } From bc2df705ef9b3a3d1526aa8d8ecd37cebb159bc9 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Tue, 31 Dec 2019 11:53:42 -0600 Subject: [PATCH 032/109] Fix campfires --- .../network/translators/TranslatorsInit.java | 7 +- .../entity/CampfireBlockEntityTranslator.java | 76 +++++++++++++++++++ .../ContainerBlockEntityTranslator.java | 8 -- 3 files changed, 78 insertions(+), 13 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/block/entity/CampfireBlockEntityTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java index 477734d8..268d443f 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java @@ -45,10 +45,7 @@ import com.nukkitx.protocol.bedrock.packet.*; import lombok.Getter; import org.geysermc.connector.network.translators.bedrock.*; import org.geysermc.connector.network.translators.block.BlockTranslator; -import org.geysermc.connector.network.translators.block.entity.BlockEntityTranslator; -import org.geysermc.connector.network.translators.block.entity.ContainerBlockEntityTranslator; -import org.geysermc.connector.network.translators.block.entity.EmptyBlockEntityTranslator; -import org.geysermc.connector.network.translators.block.entity.SignBlockEntityTranslator; +import org.geysermc.connector.network.translators.block.entity.*; import org.geysermc.connector.network.translators.inventory.GenericInventoryTranslator; import org.geysermc.connector.network.translators.inventory.InventoryTranslator; import org.geysermc.connector.network.translators.item.ItemTranslator; @@ -177,7 +174,7 @@ public class TranslatorsInit { private static void registerBlockEntityTranslators() { blockEntityTranslators.put("Empty", new EmptyBlockEntityTranslator("empty", "Empty")); blockEntityTranslators.put("Sign", new SignBlockEntityTranslator("minecraft:sign", "Sign")); - blockEntityTranslators.put("Campfire", new ContainerBlockEntityTranslator("minecraft:campfire", "Campfire")); + blockEntityTranslators.put("Campfire", new CampfireBlockEntityTranslator("minecraft:campfire", "Campfire")); } private static void registerInventoryTranslators() { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/CampfireBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/CampfireBlockEntityTranslator.java new file mode 100644 index 00000000..f2776213 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/CampfireBlockEntityTranslator.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.block.entity; + +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.ListTag; +import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.tag.Tag; + +import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.item.ItemEntry; + +import java.util.ArrayList; +import java.util.List; + +public class CampfireBlockEntityTranslator extends BlockEntityTranslator { + + public CampfireBlockEntityTranslator(String javaId, String bedrockId) { + super(javaId, bedrockId); + } + + @Override + public List> translateTag(CompoundTag tag) { + List> tags = new ArrayList<>(); + ListTag items = tag.get("Items"); + int i = 1; + for (com.github.steveice10.opennbt.tag.builtin.Tag itemTag : items.getValue()) { + tags.add(getItem((CompoundTag) itemTag).toBuilder().build("Item" + i)); + i++; + } + return tags; + } + + @Override + public CompoundTag getDefaultJavaTag(int x, int y, int z) { + return null; + } + + @Override + public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(int x, int y, int z) { + return null; + } + + protected com.nukkitx.nbt.tag.CompoundTag getItem(CompoundTag tag) { + ItemEntry entry = TranslatorsInit.getItemTranslator().getItemEntry((String) tag.get("id").getValue()); + CompoundTagBuilder tagBuilder = CompoundTagBuilder.builder() + .shortTag("id", (short) entry.getBedrockId()) + .byteTag("Count", (byte) tag.get("Count").getValue()) + .shortTag("Damage", (short) entry.getBedrockData()) + .tag(CompoundTagBuilder.builder().build("tag")); + return tagBuilder.buildRootTag(); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ContainerBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ContainerBlockEntityTranslator.java index 18168348..78566d60 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ContainerBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ContainerBlockEntityTranslator.java @@ -28,14 +28,12 @@ package org.geysermc.connector.network.translators.block.entity; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.nukkitx.nbt.CompoundTagBuilder; -import com.nukkitx.nbt.tag.IntArrayTag; import com.nukkitx.nbt.tag.Tag; import org.geysermc.connector.network.translators.TranslatorsInit; import org.geysermc.connector.network.translators.item.ItemEntry; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; public class ContainerBlockEntityTranslator extends BlockEntityTranslator { @@ -53,15 +51,9 @@ public class ContainerBlockEntityTranslator extends BlockEntityTranslator { tagsList.add(getItem((CompoundTag) itemTag)); } - int[] fakeCookingTime = new int[4]; - Arrays.fill(fakeCookingTime, 3); - com.nukkitx.nbt.tag.ListTag bedrockItems = new com.nukkitx.nbt.tag.ListTag<>("Items", com.nukkitx.nbt.tag.CompoundTag.class, tagsList); tags.add(bedrockItems); - - tags.add(new IntArrayTag("CookingTimes", fakeCookingTime)); - tags.add(new IntArrayTag("CookingTotalTimes", fakeCookingTime)); return tags; } From da645abec432699862f6b46dfaab0fea605802ac Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Tue, 31 Dec 2019 12:31:04 -0600 Subject: [PATCH 033/109] Add support for banner block entities Colored banners still need to be implemented. The color for banners themselves is set as part of the block entity on bedrock meanwhile in java edition its set as part of the block state. --- .../network/translators/TranslatorsInit.java | 1 + .../entity/BannerBlockEntityTranslator.java | 81 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BannerBlockEntityTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java index 268d443f..90a2b742 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java @@ -175,6 +175,7 @@ public class TranslatorsInit { blockEntityTranslators.put("Empty", new EmptyBlockEntityTranslator("empty", "Empty")); blockEntityTranslators.put("Sign", new SignBlockEntityTranslator("minecraft:sign", "Sign")); blockEntityTranslators.put("Campfire", new CampfireBlockEntityTranslator("minecraft:campfire", "Campfire")); + blockEntityTranslators.put("Banner", new BannerBlockEntityTranslator("minecraft:banner", "Banner")); } private static void registerInventoryTranslators() { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BannerBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BannerBlockEntityTranslator.java new file mode 100644 index 00000000..22c68843 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BannerBlockEntityTranslator.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.block.entity; + +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.ListTag; +import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.tag.StringTag; +import com.nukkitx.nbt.tag.Tag; + +import java.util.ArrayList; +import java.util.List; + +public class BannerBlockEntityTranslator extends BlockEntityTranslator { + + public BannerBlockEntityTranslator(String javaId, String bedrockId) { + super(javaId, bedrockId); + } + + @Override + public List> translateTag(CompoundTag tag) { + List> tags = new ArrayList<>(); + ListTag patterns = tag.get("Patterns"); + List tagsList = new ArrayList<>(); + for (com.github.steveice10.opennbt.tag.builtin.Tag patternTag : patterns.getValue()) { + tagsList.add(getPattern((CompoundTag) patternTag)); + } + com.nukkitx.nbt.tag.ListTag bedrockPatterns = + new com.nukkitx.nbt.tag.ListTag<>("Patterns", com.nukkitx.nbt.tag.CompoundTag.class, tagsList); + tags.add(bedrockPatterns); + + if (tag.contains("CustomName")) { + tags.add(new StringTag("CustomName", (String) tag.get("CustomName").getValue())); + } + return tags; + } + + @Override + public CompoundTag getDefaultJavaTag(int x, int y, int z) { + CompoundTag tag = getConstantJavaTag(x, y, z); + tag.put(new ListTag("Patterns")); + return tag; + } + + @Override + public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(int x, int y, int z) { + CompoundTagBuilder tagBuilder = getConstantBedrockTag(x, y, z).toBuilder(); + tagBuilder.listTag("Patterns", com.nukkitx.nbt.tag.CompoundTag.class, new ArrayList<>()); + return tagBuilder.buildRootTag(); + } + + protected com.nukkitx.nbt.tag.CompoundTag getPattern(CompoundTag pattern) { + return CompoundTagBuilder.builder() + .intTag("Color", (int) pattern.get("Color").getValue()) + .stringTag("Pattern", (String) pattern.get("Pattern").getValue()) + .buildRootTag(); + } +} From a59e330db9a1c0a54efbadabe492de01c600068d Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Tue, 31 Dec 2019 12:33:42 -0600 Subject: [PATCH 034/109] Add default tags for campfire block entity --- .../block/entity/CampfireBlockEntityTranslator.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/CampfireBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/CampfireBlockEntityTranslator.java index f2776213..ee1c1275 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/CampfireBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/CampfireBlockEntityTranslator.java @@ -34,6 +34,7 @@ import org.geysermc.connector.network.translators.TranslatorsInit; import org.geysermc.connector.network.translators.item.ItemEntry; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; public class CampfireBlockEntityTranslator extends BlockEntityTranslator { @@ -56,12 +57,19 @@ public class CampfireBlockEntityTranslator extends BlockEntityTranslator { @Override public CompoundTag getDefaultJavaTag(int x, int y, int z) { - return null; + CompoundTag tag = getConstantJavaTag(x, y, z); + tag.put(new ListTag("Items")); + return tag; } @Override public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(int x, int y, int z) { - return null; + CompoundTagBuilder tagBuilder = getConstantBedrockTag(x, y, z).toBuilder(); + tagBuilder.tag(new com.nukkitx.nbt.tag.CompoundTag("Item1", new HashMap<>())); + tagBuilder.tag(new com.nukkitx.nbt.tag.CompoundTag("Item2", new HashMap<>())); + tagBuilder.tag(new com.nukkitx.nbt.tag.CompoundTag("Item3", new HashMap<>())); + tagBuilder.tag(new com.nukkitx.nbt.tag.CompoundTag("Item4", new HashMap<>())); + return tagBuilder.buildRootTag(); } protected com.nukkitx.nbt.tag.CompoundTag getItem(CompoundTag tag) { From 0eb182d0da1bd5d3a8d910d0ed73f74ba2559495 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Tue, 31 Dec 2019 13:24:59 -0600 Subject: [PATCH 035/109] Add block value translator You can now see chest opening/closing animations :) --- .../network/translators/TranslatorsInit.java | 1 + .../java/world/JavaBlockValueTranslator.java | 55 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockValueTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java index 90a2b742..a08a0c81 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java @@ -151,6 +151,7 @@ public class TranslatorsInit { Registry.registerJava(ServerMultiBlockChangePacket.class, new JavaMultiBlockChangeTranslator()); Registry.registerJava(ServerUnloadChunkPacket.class, new JavaUnloadChunkTranslator()); Registry.registerJava(ServerUpdateTileEntityPacket.class, new JavaUpdateTileEntityTranslator()); + Registry.registerJava(ServerBlockValuePacket.class, new JavaBlockValueTranslator()); Registry.registerJava(ServerOpenWindowPacket.class, new OpenWindowPacketTranslator()); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockValueTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockValueTranslator.java new file mode 100644 index 00000000..ac699fd9 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockValueTranslator.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.java.world; + +import com.github.steveice10.mc.protocol.data.game.world.block.value.ChestValue; +import com.github.steveice10.mc.protocol.data.game.world.block.value.EndGatewayValue; +import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerBlockValuePacket; +import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.protocol.bedrock.packet.BlockEventPacket; + +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; + +public class JavaBlockValueTranslator extends PacketTranslator { + + @Override + public void translate(ServerBlockValuePacket packet, GeyserSession session) { + BlockEventPacket blockEventPacket = new BlockEventPacket(); + blockEventPacket.setBlockPosition(Vector3i.from(packet.getPosition().getX(), + packet.getPosition().getY(), packet.getPosition().getZ())); + if (packet.getValue() instanceof ChestValue) { + ChestValue value = (ChestValue) packet.getValue() ; + blockEventPacket.setEventType(1); + blockEventPacket.setEventData(value.getViewers() > 0 ? 1 : 0); + session.getUpstream().sendPacket(blockEventPacket); + } + if (packet.getValue() instanceof EndGatewayValue) { + blockEventPacket.setEventType(1); + session.getUpstream().sendPacket(blockEventPacket); + } + } +} From e0f6c8a1700fa0df130cc884f84e5ac91eace754 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sat, 25 Jan 2020 23:51:29 -0600 Subject: [PATCH 036/109] Fix chests and potentially other block entities --- .../network/translators/TranslatorsInit.java | 8 ++++---- .../entity/BannerBlockEntityTranslator.java | 12 ++++-------- .../block/entity/BlockEntityTranslator.java | 16 +++++++--------- .../entity/CampfireBlockEntityTranslator.java | 12 ++++-------- .../entity/ContainerBlockEntityTranslator.java | 12 ++++-------- .../block/entity/EmptyBlockEntityTranslator.java | 12 ++++-------- .../block/entity/SignBlockEntityTranslator.java | 12 ++++-------- .../connector/utils/BlockEntityUtils.java | 4 +++- .../org/geysermc/connector/utils/ChunkUtils.java | 2 +- 9 files changed, 35 insertions(+), 55 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java index 6d5a1efa..21b57b25 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java @@ -176,10 +176,10 @@ public class TranslatorsInit { } private static void registerBlockEntityTranslators() { - blockEntityTranslators.put("Empty", new EmptyBlockEntityTranslator("empty", "Empty")); - blockEntityTranslators.put("Sign", new SignBlockEntityTranslator("minecraft:sign", "Sign")); - blockEntityTranslators.put("Campfire", new CampfireBlockEntityTranslator("minecraft:campfire", "Campfire")); - blockEntityTranslators.put("Banner", new BannerBlockEntityTranslator("minecraft:banner", "Banner")); + blockEntityTranslators.put("Empty", new EmptyBlockEntityTranslator()); + blockEntityTranslators.put("Sign", new SignBlockEntityTranslator()); + blockEntityTranslators.put("Campfire", new CampfireBlockEntityTranslator()); + blockEntityTranslators.put("Banner", new BannerBlockEntityTranslator()); } private static void registerInventoryTranslators() { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BannerBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BannerBlockEntityTranslator.java index 22c68843..a5ed5994 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BannerBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BannerBlockEntityTranslator.java @@ -36,10 +36,6 @@ import java.util.List; public class BannerBlockEntityTranslator extends BlockEntityTranslator { - public BannerBlockEntityTranslator(String javaId, String bedrockId) { - super(javaId, bedrockId); - } - @Override public List> translateTag(CompoundTag tag) { List> tags = new ArrayList<>(); @@ -59,15 +55,15 @@ public class BannerBlockEntityTranslator extends BlockEntityTranslator { } @Override - public CompoundTag getDefaultJavaTag(int x, int y, int z) { - CompoundTag tag = getConstantJavaTag(x, y, z); + public CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) { + CompoundTag tag = getConstantJavaTag(javaId, x, y, z); tag.put(new ListTag("Patterns")); return tag; } @Override - public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(int x, int y, int z) { - CompoundTagBuilder tagBuilder = getConstantBedrockTag(x, y, z).toBuilder(); + public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { + CompoundTagBuilder tagBuilder = getConstantBedrockTag(bedrockId, x, y, z).toBuilder(); tagBuilder.listTag("Patterns", com.nukkitx.nbt.tag.CompoundTag.class, new ArrayList<>()); return tagBuilder.buildRootTag(); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java index e5e3a50d..71b83d59 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java @@ -32,32 +32,30 @@ import com.nukkitx.nbt.CompoundTagBuilder; import com.nukkitx.nbt.tag.Tag; import lombok.AllArgsConstructor; +import org.geysermc.connector.utils.BlockEntityUtils; import java.util.List; -@AllArgsConstructor public abstract class BlockEntityTranslator { - protected String javaId; - protected String bedrockId; - public abstract List> translateTag(CompoundTag tag); - public abstract CompoundTag getDefaultJavaTag(int x, int y, int z); + public abstract CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z); - public abstract com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(int x, int y, int z); + public abstract com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z); public com.nukkitx.nbt.tag.CompoundTag getBlockEntityTag(CompoundTag tag) { int x = Integer.parseInt(String.valueOf(tag.getValue().get("x").getValue())); int y = Integer.parseInt(String.valueOf(tag.getValue().get("y").getValue())); int z = Integer.parseInt(String.valueOf(tag.getValue().get("z").getValue())); - CompoundTagBuilder tagBuilder = getConstantBedrockTag(x, y, z).toBuilder(); + CompoundTagBuilder tagBuilder = getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId( + String.valueOf(tag.get("id").getValue())), x, y, z).toBuilder(); translateTag(tag).forEach(tagBuilder::tag); return tagBuilder.buildRootTag(); } - protected CompoundTag getConstantJavaTag(int x, int y, int z) { + protected CompoundTag getConstantJavaTag(String javaId, int x, int y, int z) { CompoundTag tag = new CompoundTag(""); tag.put(new IntTag("x", x)); tag.put(new IntTag("y", y)); @@ -66,7 +64,7 @@ public abstract class BlockEntityTranslator { return tag; } - protected com.nukkitx.nbt.tag.CompoundTag getConstantBedrockTag(int x, int y, int z) { + protected com.nukkitx.nbt.tag.CompoundTag getConstantBedrockTag(String bedrockId, int x, int y, int z) { CompoundTagBuilder tagBuilder = CompoundTagBuilder.builder() .intTag("x", x) .intTag("y", y) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/CampfireBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/CampfireBlockEntityTranslator.java index ee1c1275..b40626dc 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/CampfireBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/CampfireBlockEntityTranslator.java @@ -39,10 +39,6 @@ import java.util.List; public class CampfireBlockEntityTranslator extends BlockEntityTranslator { - public CampfireBlockEntityTranslator(String javaId, String bedrockId) { - super(javaId, bedrockId); - } - @Override public List> translateTag(CompoundTag tag) { List> tags = new ArrayList<>(); @@ -56,15 +52,15 @@ public class CampfireBlockEntityTranslator extends BlockEntityTranslator { } @Override - public CompoundTag getDefaultJavaTag(int x, int y, int z) { - CompoundTag tag = getConstantJavaTag(x, y, z); + public CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) { + CompoundTag tag = getConstantJavaTag(javaId, x, y, z); tag.put(new ListTag("Items")); return tag; } @Override - public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(int x, int y, int z) { - CompoundTagBuilder tagBuilder = getConstantBedrockTag(x, y, z).toBuilder(); + public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { + CompoundTagBuilder tagBuilder = getConstantBedrockTag(bedrockId, x, y, z).toBuilder(); tagBuilder.tag(new com.nukkitx.nbt.tag.CompoundTag("Item1", new HashMap<>())); tagBuilder.tag(new com.nukkitx.nbt.tag.CompoundTag("Item2", new HashMap<>())); tagBuilder.tag(new com.nukkitx.nbt.tag.CompoundTag("Item3", new HashMap<>())); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ContainerBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ContainerBlockEntityTranslator.java index 78566d60..123290db 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ContainerBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ContainerBlockEntityTranslator.java @@ -38,10 +38,6 @@ import java.util.List; public class ContainerBlockEntityTranslator extends BlockEntityTranslator { - public ContainerBlockEntityTranslator(String javaId, String bedrockId) { - super(javaId, bedrockId); - } - @Override public List> translateTag(CompoundTag tag) { List> tags = new ArrayList<>(); @@ -58,15 +54,15 @@ public class ContainerBlockEntityTranslator extends BlockEntityTranslator { } @Override - public CompoundTag getDefaultJavaTag(int x, int y, int z) { - CompoundTag tag = getConstantJavaTag(x, y, z); + public CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) { + CompoundTag tag = getConstantJavaTag(javaId, x, y, z); tag.put(new ListTag("Items")); return tag; } @Override - public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(int x, int y, int z) { - CompoundTagBuilder tagBuilder = getConstantBedrockTag(x, y, z).toBuilder(); + public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { + CompoundTagBuilder tagBuilder = getConstantBedrockTag(bedrockId, x, y, z).toBuilder(); tagBuilder.listTag("Items", com.nukkitx.nbt.tag.CompoundTag.class, new ArrayList<>()); return tagBuilder.buildRootTag(); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java index 700b50db..16bc4d7a 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java @@ -33,22 +33,18 @@ import java.util.List; public class EmptyBlockEntityTranslator extends BlockEntityTranslator { - public EmptyBlockEntityTranslator(String javaId, String bedrockId) { - super(javaId, bedrockId); - } - @Override public List> translateTag(CompoundTag tag) { return new ArrayList<>(); } @Override - public CompoundTag getDefaultJavaTag(int x, int y, int z) { - return getConstantJavaTag(x, y, z); + public CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) { + return getConstantJavaTag(javaId, x, y, z); } @Override - public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(int x, int y, int z) { - return getConstantBedrockTag(x, y, z); + public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { + return getConstantBedrockTag(bedrockId, x, y, z); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java index 7029143b..3d9a4a7a 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java @@ -38,10 +38,6 @@ import java.util.List; public class SignBlockEntityTranslator extends BlockEntityTranslator { - public SignBlockEntityTranslator(String javaId, String bedrockId) { - super(javaId, bedrockId); - } - @Override public List> translateTag(CompoundTag tag) { List> tags = new ArrayList<>(); @@ -61,8 +57,8 @@ public class SignBlockEntityTranslator extends BlockEntityTranslator { } @Override - public CompoundTag getDefaultJavaTag(int x, int y, int z) { - CompoundTag tag = getConstantJavaTag(x, y, z); + public CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) { + CompoundTag tag = getConstantJavaTag(javaId, x, y, z); tag.put(new com.github.steveice10.opennbt.tag.builtin.StringTag("Text1", "{\"text\":\"\"}")); tag.put(new com.github.steveice10.opennbt.tag.builtin.StringTag("Text2", "{\"text\":\"\"}")); tag.put(new com.github.steveice10.opennbt.tag.builtin.StringTag("Text3", "{\"text\":\"\"}")); @@ -71,8 +67,8 @@ public class SignBlockEntityTranslator extends BlockEntityTranslator { } @Override - public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(int x, int y, int z) { - CompoundTagBuilder tagBuilder = getConstantBedrockTag(x, y, z).toBuilder(); + public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { + CompoundTagBuilder tagBuilder = getConstantBedrockTag(bedrockId, x, y, z).toBuilder(); tagBuilder.stringTag("Text", ""); return tagBuilder.buildRootTag(); } diff --git a/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java index f610f271..58eadb1b 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java @@ -10,6 +10,8 @@ import org.geysermc.connector.network.translators.block.entity.BlockEntityTransl public class BlockEntityUtils { + private static final BlockEntityTranslator EMPTY_TRANSLATOR = TranslatorsInit.getBlockEntityTranslators().get("Empty"); + public static String getBedrockBlockEntityId(String id) { // This is the only exception when it comes to block entity ids if (id.contains("piston_head")) @@ -30,7 +32,7 @@ public class BlockEntityUtils { public static BlockEntityTranslator getBlockEntityTranslator(String name) { BlockEntityTranslator blockEntityTranslator = TranslatorsInit.getBlockEntityTranslators().get(name); if (blockEntityTranslator == null) { - return TranslatorsInit.getBlockEntityTranslators().get("Empty"); + return EMPTY_TRANSLATOR; } return blockEntityTranslator; diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java index fba9e788..4e0b6826 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -69,7 +69,7 @@ public class ChunkUtils { BlockEntry block = TranslatorsInit.getBlockTranslator().getBlockEntry(blockState); if (block.getJavaIdentifier().contains("sign[")) { Position pos = new ChunkPosition(column.getX(), column.getZ()).getBlock(x, (chunkY << 4) + y, z); - chunkData.signs.put(block.getJavaId(), TranslatorsInit.getBlockEntityTranslators().get("Sign").getDefaultBedrockTag(pos.getX(), pos.getY(), pos.getZ())); + chunkData.signs.put(block.getJavaId(), TranslatorsInit.getBlockEntityTranslators().get("Sign").getDefaultBedrockTag("Sign", pos.getX(), pos.getY(), pos.getZ())); } else { section.getBlockStorageArray()[0].setFullBlock(ChunkSection.blockPosition(x, y, z), block.getBedrockRuntimeId()); } From 1a9aa4255f092a609c63a86b53b99f131113ac60 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Thu, 30 Jan 2020 16:05:57 -0900 Subject: [PATCH 037/109] Some refactoring and bug fixes Still much to do. Inventory desyncing when crafting will be fixed soon. --- .../network/translators/TranslatorsInit.java | 16 +- ...BedrockInventoryTransactionTranslator.java | 499 +----------------- .../inventory/AnvilInventoryTranslator.java | 63 ++- ...ator.java => BaseInventoryTranslator.java} | 63 +-- .../inventory/BlockInventoryTranslator.java | 71 +-- ...r.java => BrewingInventoryTranslator.java} | 22 +- ....java => CraftingInventoryTranslator.java} | 49 +- .../DoubleChestInventoryTranslator.java | 58 +- .../EnchantmentInventoryTranslator.java | 5 +- .../inventory/FurnaceInventoryTranslator.java | 5 +- .../inventory/InventoryTranslator.java | 9 +- .../inventory/PlayerInventoryTranslator.java | 77 ++- .../SingleChestInventoryTranslator.java | 31 +- .../translators/inventory/SlotType.java | 2 +- .../translators/inventory/action/Click.java | 38 ++ .../inventory/action/ClickPlan.java | 125 +++++ .../action/InventoryActionTranslator.java | 330 ++++++++++++ .../holder/BlockInventoryHolder.java | 90 ++++ .../inventory/holder/InventoryHolder.java | 36 ++ .../updater/ChestInventoryUpdater.java | 72 +++ .../updater/ContainerInventoryUpdater.java | 64 +++ .../updater/CursorInventoryUpdater.java | 64 +++ .../inventory/updater/InventoryUpdater.java | 61 +++ .../network/translators/item/Enchantment.java | 2 +- .../translators/item/ItemTranslator.java | 3 +- .../network/translators/item/Potion.java | 2 +- .../java/JavaDeclareRecipesTranslator.java | 15 +- .../JavaPlayerChangeHeldItemTranslator.java | 45 ++ .../window/JavaCloseWindowTranslator.java | 2 +- .../JavaConfirmTransactionTranslator.java | 2 +- .../java/window/JavaOpenWindowTranslator.java | 2 +- .../java/window/JavaSetSlotTranslator.java | 4 +- .../window/JavaWindowPropertyTranslator.java | 2 +- .../connector/utils/InventoryUtils.java | 34 ++ .../org/geysermc/connector/utils/Toolbox.java | 21 +- 35 files changed, 1282 insertions(+), 702 deletions(-) rename connector/src/main/java/org/geysermc/connector/network/translators/inventory/{ContainerInventoryTranslator.java => BaseInventoryTranslator.java} (50%) rename connector/src/main/java/org/geysermc/connector/network/translators/inventory/{BrewingStandInventoryTranslator.java => BrewingInventoryTranslator.java} (86%) rename connector/src/main/java/org/geysermc/connector/network/translators/inventory/{CraftingTableInventoryTranslator.java => CraftingInventoryTranslator.java} (61%) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/Click.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/ClickPlan.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/holder/BlockInventoryHolder.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/holder/InventoryHolder.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerChangeHeldItemTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java index 53850009..6b3adf15 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java @@ -46,6 +46,8 @@ import lombok.Getter; import org.geysermc.connector.network.translators.bedrock.*; import org.geysermc.connector.network.translators.block.BlockTranslator; import org.geysermc.connector.network.translators.inventory.*; +import org.geysermc.connector.network.translators.inventory.updater.ContainerInventoryUpdater; +import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater; import org.geysermc.connector.network.translators.item.ItemTranslator; import org.geysermc.connector.network.translators.java.*; import org.geysermc.connector.network.translators.java.entity.*; @@ -72,7 +74,7 @@ public class TranslatorsInit { private static BlockTranslator blockTranslator; @Getter - private static Map inventoryTranslators = new HashMap(); + private static Map inventoryTranslators = new HashMap<>(); private static final CompoundTag EMPTY_TAG = CompoundTagBuilder.builder().buildRootTag(); public static final byte[] EMPTY_LEVEL_CHUNK_DATA; @@ -127,6 +129,7 @@ public class TranslatorsInit { Registry.registerJava(ServerPlayerSetExperiencePacket.class, new JavaPlayerSetExperienceTranslator()); Registry.registerJava(ServerPlayerHealthPacket.class, new JavaPlayerHealthTranslator()); Registry.registerJava(ServerPlayerActionAckPacket.class, new JavaPlayerActionAckTranslator()); + Registry.registerJava(ServerPlayerChangeHeldItemPacket.class, new JavaPlayerChangeHeldItemTranslator()); // FIXME: This translator messes with allowing flight in creative mode. Will need to be addressed later // Registry.registerJava(ServerPlayerAbilitiesPacket.class, new JavaPlayerAbilitiesTranslator()); @@ -176,9 +179,9 @@ public class TranslatorsInit { inventoryTranslators.put(WindowType.GENERIC_9X4, new DoubleChestInventoryTranslator(36)); inventoryTranslators.put(WindowType.GENERIC_9X5, new DoubleChestInventoryTranslator(45)); inventoryTranslators.put(WindowType.GENERIC_9X6, new DoubleChestInventoryTranslator(54)); - inventoryTranslators.put(WindowType.BREWING_STAND, new BrewingStandInventoryTranslator()); + inventoryTranslators.put(WindowType.BREWING_STAND, new BrewingInventoryTranslator()); inventoryTranslators.put(WindowType.ANVIL, new AnvilInventoryTranslator()); - inventoryTranslators.put(WindowType.CRAFTING, new CraftingTableInventoryTranslator()); + inventoryTranslators.put(WindowType.CRAFTING, new CraftingInventoryTranslator()); //inventoryTranslators.put(WindowType.ENCHANTMENT, new EnchantmentInventoryTranslator()); //TODO InventoryTranslator furnace = new FurnaceInventoryTranslator(); @@ -186,9 +189,10 @@ public class TranslatorsInit { inventoryTranslators.put(WindowType.BLAST_FURNACE, furnace); inventoryTranslators.put(WindowType.SMOKER, furnace); - inventoryTranslators.put(WindowType.GENERIC_3X3, new BlockInventoryTranslator(9, "minecraft:dispenser[facing=north,triggered=false]", ContainerType.DISPENSER)); - inventoryTranslators.put(WindowType.HOPPER, new BlockInventoryTranslator(5, "minecraft:hopper[enabled=false,facing=down]", ContainerType.HOPPER)); - inventoryTranslators.put(WindowType.SHULKER_BOX, new BlockInventoryTranslator(27, "minecraft:shulker_box[facing=north]", ContainerType.CONTAINER)); + InventoryUpdater containerUpdater = new ContainerInventoryUpdater(); + inventoryTranslators.put(WindowType.GENERIC_3X3, new BlockInventoryTranslator(9, "minecraft:dispenser[facing=north,triggered=false]", ContainerType.DISPENSER, containerUpdater)); + inventoryTranslators.put(WindowType.HOPPER, new BlockInventoryTranslator(5, "minecraft:hopper[enabled=false,facing=down]", ContainerType.HOPPER, containerUpdater)); + inventoryTranslators.put(WindowType.SHULKER_BOX, new BlockInventoryTranslator(27, "minecraft:shulker_box[facing=north]", ContainerType.CONTAINER, containerUpdater)); //inventoryTranslators.put(WindowType.BEACON, new BlockInventoryTranslator(1, "minecraft:beacon", ContainerType.BEACON)); //TODO } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java index ca6729b9..ee12b5aa 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java @@ -25,13 +25,7 @@ package org.geysermc.connector.network.translators.bedrock; -import com.github.steveice10.mc.protocol.data.game.window.*; -import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientConfirmTransactionPacket; -import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientCreativeInventoryActionPacket; -import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientRenameItemPacket; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.nukkitx.math.vector.Vector3f; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; @@ -41,382 +35,31 @@ 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; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerUseItemPacket; -import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientWindowActionPacket; -import com.nukkitx.protocol.bedrock.data.ContainerId; -import com.nukkitx.protocol.bedrock.data.InventoryAction; -import com.nukkitx.protocol.bedrock.data.InventorySource; -import com.nukkitx.protocol.bedrock.data.ItemData; -import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import com.nukkitx.protocol.bedrock.packet.InventoryTransactionPacket; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.inventory.Inventory; -import org.geysermc.connector.inventory.PlayerInventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.TranslatorsInit; -import org.geysermc.connector.network.translators.inventory.InventoryTranslator; -import org.geysermc.connector.network.translators.inventory.SlotType; +import org.geysermc.connector.utils.InventoryUtils; import java.util.*; public class BedrockInventoryTransactionTranslator extends PacketTranslator { - private final ItemStack refreshItem = new ItemStack(1, 127, new CompoundTag("")); @Override public void translate(InventoryTransactionPacket packet, GeyserSession session) { switch (packet.getTransactionType()) { case NORMAL: - for (InventoryAction action : packet.getActions()) { - if (action.getSource().getContainerId() == ContainerId.CRAFTING_USE_INGREDIENT || - action.getSource().getContainerId() == ContainerId.CRAFTING_RESULT) { - return; - } - } - Inventory inventory = session.getInventoryCache().getOpenInventory(); - if (inventory == null) - inventory = session.getInventory(); - InventoryTranslator translator = TranslatorsInit.getInventoryTranslators().get(inventory.getWindowType()); - - int craftSlot = session.getCraftSlot(); - session.setCraftSlot(0); - - if (session.getGameMode() == GameMode.CREATIVE && inventory.getId() == 0) { - ItemStack javaItem; - for (InventoryAction action : packet.getActions()) { - switch (action.getSource().getContainerId()) { - case ContainerId.INVENTORY: - case ContainerId.ARMOR: - case ContainerId.OFFHAND: - int javaSlot = translator.bedrockSlotToJava(action); - if (action.getToItem().getId() == 0) { - javaItem = new ItemStack(-1, 0, null); - } else { - javaItem = TranslatorsInit.getItemTranslator().translateToJava(action.getToItem()); - if (javaItem.getId() == 0) { //item missing mapping - translator.updateInventory(session, inventory); - break; - } - } - ClientCreativeInventoryActionPacket creativePacket = new ClientCreativeInventoryActionPacket(javaSlot, fixStack(javaItem)); - session.getDownstream().getSession().send(creativePacket); - inventory.setItem(javaSlot, javaItem); - break; - case ContainerId.NONE: - if (action.getSource().getType() == InventorySource.Type.WORLD_INTERACTION && - action.getSource().getFlag() == InventorySource.Flag.DROP_ITEM) { - javaItem = TranslatorsInit.getItemTranslator().translateToJava(action.getToItem()); - if (javaItem.getId() == 0) { //item missing mapping - break; - } - ClientCreativeInventoryActionPacket creativeDropPacket = new ClientCreativeInventoryActionPacket(-1, fixStack(javaItem)); - session.getDownstream().getSession().send(creativeDropPacket); - } - break; - } - } - return; - } - - InventoryAction worldAction = null; - InventoryAction cursorAction = null; - for (InventoryAction action : packet.getActions()) { - if (action.getSource().getType() == InventorySource.Type.WORLD_INTERACTION) { - worldAction = action; - } else if (action.getSource().getContainerId() == ContainerId.CURSOR && action.getSlot() == 0) { - cursorAction = action; - } - } - List actions = packet.getActions(); - if (inventory.getWindowType() == WindowType.ANVIL) { - InventoryAction anvilResult = null; - InventoryAction anvilInput = null; - for (InventoryAction action : packet.getActions()) { - if (action.getSource().getContainerId() == ContainerId.ANVIL_MATERIAL) { - //useless packet - return; - } else if (action.getSource().getContainerId() == ContainerId.ANVIL_RESULT) { - anvilResult = action; - } else if (translator.bedrockSlotToJava(action) == 0) { - anvilInput = action; - } - } - ItemData itemName = null; - if (anvilResult != null) { - itemName = anvilResult.getFromItem(); - } else if (anvilInput != null) { - itemName = anvilInput.getToItem(); - } - if (itemName != null) { - String rename; - com.nukkitx.nbt.tag.CompoundTag tag = itemName.getTag(); - if (tag != null) { - rename = tag.getAsCompound("display").getAsString("Name"); - } else { - rename = ""; - } - ClientRenameItemPacket renameItemPacket = new ClientRenameItemPacket(rename); - session.getDownstream().getSession().send(renameItemPacket); - } - if (anvilResult != null) { - //client will send another packet to grab anvil output - //this packet was only used to send rename packet - return; - } - } - - if (actions.size() == 2) { - if (worldAction != null) { - //find container action - InventoryAction containerAction = null; - for (InventoryAction action : actions) { - if (action != worldAction) { - containerAction = action; - break; - } - } - if (containerAction != null && worldAction.getSource().getFlag() == InventorySource.Flag.DROP_ITEM) { - //quick dropping from hotbar? - if (session.getInventoryCache().getOpenInventory() == null && containerAction.getSource().getContainerId() == ContainerId.INVENTORY) { - int heldSlot = session.getInventory().getHeldItemSlot(); - if (containerAction.getSlot() == heldSlot) { - ClientPlayerActionPacket actionPacket = new ClientPlayerActionPacket( - containerAction.getToItem().getCount() == 0 ? PlayerAction.DROP_ITEM_STACK : PlayerAction.DROP_ITEM, - new Position(0, 0, 0), BlockFace.DOWN); - session.getDownstream().getSession().send(actionPacket); - ItemStack item = session.getInventory().getItem(heldSlot); - if (item != null) { - session.getInventory().setItem(heldSlot, new ItemStack(item.getId(), item.getAmount() - 1, item.getNbt())); - } - return; - } - } - int dropAmount = containerAction.getFromItem().getCount() - containerAction.getToItem().getCount(); - if (containerAction != cursorAction) { //dropping directly from inventory - int javaSlot = translator.bedrockSlotToJava(containerAction); - if (dropAmount == containerAction.getFromItem().getCount()) { - ClientWindowActionPacket dropPacket = new ClientWindowActionPacket(inventory.getId(), - inventory.getTransactionId().getAndIncrement(), - javaSlot, null, WindowAction.DROP_ITEM, - DropItemParam.DROP_SELECTED_STACK); - session.getDownstream().getSession().send(dropPacket); - } else { - for (int i = 0; i < dropAmount; i++) { - ClientWindowActionPacket dropPacket = new ClientWindowActionPacket(inventory.getId(), - inventory.getTransactionId().getAndIncrement(), - javaSlot, null, WindowAction.DROP_ITEM, - DropItemParam.DROP_FROM_SELECTED); - session.getDownstream().getSession().send(dropPacket); - } - } - ItemStack item = session.getInventory().getItem(javaSlot); - if (item != null) { - session.getInventory().setItem(javaSlot, new ItemStack(item.getId(), item.getAmount() - dropAmount, item.getNbt())); - } - return; - } else { //clicking outside of inventory - ClientWindowActionPacket dropPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getTransactionId().getAndIncrement(), - -999, null, WindowAction.CLICK_ITEM, - dropAmount > 1 ? ClickItemParam.LEFT_CLICK : ClickItemParam.RIGHT_CLICK); - session.getDownstream().getSession().send(dropPacket); - ItemStack cursor = session.getInventory().getCursor(); - if (cursor != null) { - session.getInventory().setCursor(new ItemStack(cursor.getId(), dropAmount > 1 ? 0 : cursor.getAmount() - 1, cursor.getNbt())); - } - return; - } - } - } else if (cursorAction != null) { - //find container action - InventoryAction containerAction = null; - for (InventoryAction action : actions) { - if (action != cursorAction) { - containerAction = action; - break; - } - } - if (containerAction != null) { - //left/right click - List plan = new ArrayList<>(); - ItemStack translatedCursor = cursorAction.getFromItem().isValid() ? - TranslatorsInit.getItemTranslator().translateToJava(cursorAction.getFromItem()) : null; - ItemStack currentCursor = session.getInventory().getCursor(); - boolean refresh = false; - if (currentCursor != null) { - if (translatedCursor != null) { - refresh = !(currentCursor.getId() == translatedCursor.getId() && - currentCursor.getAmount() == translatedCursor.getAmount()); - } else { - refresh = true; - } - } - - int javaSlot = translator.bedrockSlotToJava(containerAction); - if (cursorAction.getFromItem().equals(containerAction.getToItem()) && - containerAction.getFromItem().equals(cursorAction.getToItem()) && - !canStack(cursorAction.getFromItem(), containerAction.getFromItem())) { //simple swap - Click.LEFT.onSlot(javaSlot, plan); - } else if (cursorAction.getFromItem().getCount() > cursorAction.getToItem().getCount()) { //release - if (cursorAction.getToItem().getCount() == 0) { - Click.LEFT.onSlot(javaSlot, plan); - } else { - int difference = cursorAction.getFromItem().getCount() - cursorAction.getToItem().getCount(); - for (int i = 0; i < difference; i++) { - Click.RIGHT.onSlot(javaSlot, plan); - } - } - } else { //pickup - if (cursorAction.getFromItem().getCount() == 0) { - if (containerAction.getToItem().getCount() == 0) { //pickup all - Click.LEFT.onSlot(javaSlot, plan); - } else { //pickup some - if (translator.getSlotType(javaSlot) == SlotType.FURNACE_OUTPUT || - containerAction.getToItem().getCount() == containerAction.getFromItem().getCount() / 2) { //right click - Click.RIGHT.onSlot(javaSlot, plan); - } else { - Click.LEFT.onSlot(javaSlot, plan); - int difference = containerAction.getFromItem().getCount() - cursorAction.getToItem().getCount(); - for (int i = 0; i < difference; i++) { - Click.RIGHT.onSlot(javaSlot, plan); - } - } - } - } else { //pickup into non-empty cursor - if (translator.getSlotType(javaSlot) == SlotType.FURNACE_OUTPUT) { - if (containerAction.getToItem().getCount() == 0) { - Click.LEFT.onSlot(javaSlot, plan); - } else { - ClientWindowActionPacket shiftClickPacket = new ClientWindowActionPacket(inventory.getId(), - inventory.getTransactionId().getAndIncrement(), - javaSlot, refreshItem, WindowAction.SHIFT_CLICK_ITEM, - ShiftClickItemParam.LEFT_CLICK); - session.getDownstream().getSession().send(shiftClickPacket); - translator.updateInventory(session, inventory); - return; - } - } else if (translator.getSlotType(javaSlot) == SlotType.OUTPUT) { - Click.LEFT.onSlot(javaSlot, plan); - } else { - int cursorSlot = findTempSlot(inventory, session.getInventory().getCursor(), Collections.singletonList(javaSlot)); - if (cursorSlot != -1) { - Click.LEFT.onSlot(cursorSlot, plan); - } else { - translator.updateInventory(session, inventory); - return; - } - Click.LEFT.onSlot(javaSlot, plan); - int difference = cursorAction.getToItem().getCount() - cursorAction.getFromItem().getCount(); - for (int i = 0; i < difference; i++) { - Click.RIGHT.onSlot(cursorSlot, plan); - } - Click.LEFT.onSlot(javaSlot, plan); - Click.LEFT.onSlot(cursorSlot, plan); - } - } - } - executePlan(session, inventory, translator, plan, refresh); - return; - } - } else { - List plan = new ArrayList<>(); - InventoryAction fromAction; - InventoryAction toAction; - if (actions.get(0).getFromItem().getCount() >= actions.get(0).getToItem().getCount()) { - fromAction = actions.get(0); - toAction = actions.get(1); - } else { - fromAction = actions.get(1); - toAction = actions.get(0); - } - int fromSlot = translator.bedrockSlotToJava(fromAction); - int toSlot = translator.bedrockSlotToJava(toAction); - - if (translator.getSlotType(fromSlot) == SlotType.OUTPUT) { - if ((craftSlot != 0 && craftSlot != -2) && (inventory.getItem(toSlot) == null || - canStack(session.getInventory().getCursor(), inventory.getItem(toSlot)))) { - boolean refresh = false; - if (fromAction.getToItem().getCount() == 0) { - refresh = true; - Click.LEFT.onSlot(toSlot, plan); - if (craftSlot != -1) { - Click.LEFT.onSlot(craftSlot, plan); - } - } else { - int difference = toAction.getToItem().getCount() - toAction.getFromItem().getCount(); - for (int i = 0; i < difference; i++) { - Click.RIGHT.onSlot(toSlot, plan); - } - session.setCraftSlot(craftSlot); - } - executePlan(session, inventory, translator, plan, refresh); - return; - } else { - session.setCraftSlot(-2); - } - } - - int cursorSlot = -1; - if (session.getInventory().getCursor() != null) { //move cursor contents to a temporary slot - cursorSlot = findTempSlot(inventory, session.getInventory().getCursor(), Arrays.asList(fromSlot, toSlot)); - if (cursorSlot != -1) { - Click.LEFT.onSlot(cursorSlot, plan); - } else { - translator.updateInventory(session, inventory); - return; - } - } - if ((fromAction.getFromItem().equals(toAction.getToItem()) && !canStack(fromAction.getFromItem(), toAction.getFromItem())) || fromAction.getToItem().getId() == 0) { //slot swap - Click.LEFT.onSlot(fromSlot, plan); - Click.LEFT.onSlot(toSlot, plan); - if (fromAction.getToItem().getId() != 0) { - Click.LEFT.onSlot(fromSlot, plan); - } - } else if (canStack(fromAction.getFromItem(), toAction.getToItem())) { //partial item move - if (translator.getSlotType(fromSlot) == SlotType.FURNACE_OUTPUT) { - ClientWindowActionPacket shiftClickPacket = new ClientWindowActionPacket(inventory.getId(), - inventory.getTransactionId().getAndIncrement(), - fromSlot, refreshItem, WindowAction.SHIFT_CLICK_ITEM, - ShiftClickItemParam.LEFT_CLICK); - session.getDownstream().getSession().send(shiftClickPacket); - translator.updateInventory(session, inventory); - return; - } else if (translator.getSlotType(fromSlot) == SlotType.OUTPUT) { - session.setCraftSlot(cursorSlot); - Click.LEFT.onSlot(fromSlot, plan); - int difference = toAction.getToItem().getCount() - toAction.getFromItem().getCount(); - for (int i = 0; i < difference; i++) { - Click.RIGHT.onSlot(toSlot, plan); - } - //client will send additional packets later to finish transferring crafting output - //translator will know how to handle this using the craftSlot variable - } else { - Click.LEFT.onSlot(fromSlot, plan); - int difference = toAction.getToItem().getCount() - toAction.getFromItem().getCount(); - for (int i = 0; i < difference; i++) { - Click.RIGHT.onSlot(toSlot, plan); - } - Click.LEFT.onSlot(fromSlot, plan); - } - } - if (cursorSlot != -1) { - Click.LEFT.onSlot(cursorSlot, plan); - } - executePlan(session, inventory, translator, plan, false); - return; - } - } - translator.updateInventory(session, inventory); + if (inventory == null) inventory = session.getInventory(); + TranslatorsInit.getInventoryTranslators().get(inventory.getWindowType()).translateActions(session, inventory, packet.getActions()); break; case INVENTORY_MISMATCH: - InventorySlotPacket cursorPacket = new InventorySlotPacket(); - cursorPacket.setContainerId(ContainerId.CURSOR); - cursorPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(session.getInventory().getCursor())); - //session.getUpstream().sendPacket(cursorPacket); - Inventory inv = session.getInventoryCache().getOpenInventory(); - if (inv == null) - inv = session.getInventory(); + if (inv == null) inv = session.getInventory(); TranslatorsInit.getInventoryTranslators().get(inv.getWindowType()).updateInventory(session, inv); + InventoryUtils.updateCursor(session); break; case ITEM_USE: if (packet.getActionType() == 1) { @@ -448,136 +91,4 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator slotBlacklist) { - /*try and find a slot that can temporarily store the given item - only look in the main inventory and hotbar - only slots that are empty or contain a different type of item are valid*/ - int offset = inventory.getId() == 0 ? 1 : 0; //offhand is not a viable slot (some servers disable it) - List itemBlacklist = new ArrayList<>(slotBlacklist.size() + 1); - itemBlacklist.add(item); - for (int slot : slotBlacklist) { - ItemStack blacklistItem = inventory.getItem(slot); - if (blacklistItem != null) - itemBlacklist.add(blacklistItem); - } - for (int i = inventory.getSize() - (36 + offset); i < inventory.getSize() - offset; i++) { - ItemStack testItem = inventory.getItem(i); - boolean acceptable = true; - if (testItem != null) { - for (ItemStack blacklistItem : itemBlacklist) { - if (canStack(testItem, blacklistItem)) { - acceptable = false; - break; - } - } - } - if (acceptable && !slotBlacklist.contains(i)) - return i; - } - //could not find a viable temp slot - return -1; - } - - //NPE if compound tag is null - private ItemStack fixStack(ItemStack stack) { - if (stack == null || stack.getId() == 0) - return null; - return new ItemStack(stack.getId(), stack.getAmount(), stack.getNbt() == null ? new CompoundTag("") : stack.getNbt()); - } - - private boolean canStack(ItemStack item1, ItemStack item2) { - if (item1 == null || item2 == null) - return false; - return item1.getId() == item2.getId() && Objects.equals(item1.getNbt(), item2.getNbt()); - } - - private boolean canStack(ItemData item1, ItemData item2) { - if (item1 == null || item2 == null) - return false; - return item1.equals(item2, false, true, true); - } - - private void executePlan(GeyserSession session, Inventory inventory, InventoryTranslator translator, List plan, boolean refresh) { - PlayerInventory playerInventory = session.getInventory(); - ListIterator planIter = plan.listIterator(); - while (planIter.hasNext()) { - ClickAction action = planIter.next(); - ItemStack cursorItem = playerInventory.getCursor(); - ItemStack clickedItem = inventory.getItem(action.slot); - short actionId = (short) inventory.getTransactionId().getAndIncrement(); - boolean isOutput = translator.getSlotType(action.slot) == SlotType.OUTPUT; - - if (isOutput || translator.getSlotType(action.slot) == SlotType.FURNACE_OUTPUT) - refresh = true; - ClientWindowActionPacket clickPacket = new ClientWindowActionPacket(inventory.getId(), - actionId, action.slot, !planIter.hasNext() && refresh ? refreshItem : fixStack(clickedItem), - WindowAction.CLICK_ITEM, action.click.actionParam); - - if (isOutput) { - if (cursorItem == null && clickedItem != null) { - playerInventory.setCursor(clickedItem); - } else if (canStack(cursorItem, clickedItem)) { - playerInventory.setCursor(new ItemStack(cursorItem.getId(), - cursorItem.getAmount() + clickedItem.getAmount(), cursorItem.getNbt())); - } - } else { - switch (action.click) { - case LEFT: - if (!canStack(cursorItem, clickedItem)) { - playerInventory.setCursor(clickedItem); - inventory.setItem(action.slot, cursorItem); - } else { - playerInventory.setCursor(null); - inventory.setItem(action.slot, new ItemStack(clickedItem.getId(), - clickedItem.getAmount() + cursorItem.getAmount(), clickedItem.getNbt())); - } - break; - case RIGHT: - if (cursorItem == null && clickedItem != null) { - ItemStack halfItem = new ItemStack(clickedItem.getId(), - clickedItem.getAmount() / 2, clickedItem.getNbt()); - inventory.setItem(action.slot, halfItem); - playerInventory.setCursor(new ItemStack(clickedItem.getId(), - clickedItem.getAmount() - halfItem.getAmount(), clickedItem.getNbt())); - } else if (cursorItem != null && clickedItem == null) { - playerInventory.setCursor(new ItemStack(cursorItem.getId(), - cursorItem.getAmount() - 1, cursorItem.getNbt())); - inventory.setItem(action.slot, new ItemStack(cursorItem.getId(), - 1, cursorItem.getNbt())); - } else if (canStack(cursorItem, clickedItem)) { - playerInventory.setCursor(new ItemStack(cursorItem.getId(), - cursorItem.getAmount() - 1, cursorItem.getNbt())); - inventory.setItem(action.slot, new ItemStack(clickedItem.getId(), - clickedItem.getAmount() + 1, clickedItem.getNbt())); - } - break; - } - } - session.getDownstream().getSession().send(clickPacket); - session.getDownstream().getSession().send(new ClientConfirmTransactionPacket(inventory.getId(), actionId, true)); - } - } - - private enum Click { - LEFT(ClickItemParam.LEFT_CLICK), - RIGHT(ClickItemParam.RIGHT_CLICK); - - final WindowActionParam actionParam; - Click(WindowActionParam actionParam) { - this.actionParam = actionParam; - } - void onSlot(int slot, List plan) { - plan.add(new ClickAction(slot, this)); - } - } - - private static class ClickAction { - final int slot; - final Click click; - ClickAction(int slot, Click click) { - this.slot = slot; - this.click = click; - } - } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java index 115a7dbd..39575188 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,13 +25,20 @@ package org.geysermc.connector.network.translators.inventory; +import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientRenameItemPacket; import com.nukkitx.protocol.bedrock.data.ContainerId; import com.nukkitx.protocol.bedrock.data.ContainerType; import com.nukkitx.protocol.bedrock.data.InventoryAction; +import com.nukkitx.protocol.bedrock.data.ItemData; +import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.inventory.updater.CursorInventoryUpdater; + +import java.util.List; public class AnvilInventoryTranslator extends BlockInventoryTranslator { public AnvilInventoryTranslator() { - super(3, "minecraft:anvil[facing=north]", ContainerType.ANVIL); + super(3, "minecraft:anvil[facing=north]", ContainerType.ANVIL, new CursorInventoryUpdater()); } @Override @@ -49,10 +56,62 @@ public class AnvilInventoryTranslator extends BlockInventoryTranslator { return super.bedrockSlotToJava(action); } + @Override + public int javaSlotToBedrock(int slot) { + switch (slot) { + case 0: + return 1; + case 1: + return 2; + case 2: + return 50; + } + return super.javaSlotToBedrock(slot); + } + @Override public SlotType getSlotType(int javaSlot) { if (javaSlot == 2) return SlotType.OUTPUT; return SlotType.NORMAL; } + + @Override + public void translateActions(GeyserSession session, Inventory inventory, List actions) { + InventoryAction anvilResult = null; + InventoryAction anvilInput = null; + for (InventoryAction action : actions) { + if (action.getSource().getContainerId() == ContainerId.ANVIL_MATERIAL) { + //useless packet + return; + } else if (action.getSource().getContainerId() == ContainerId.ANVIL_RESULT) { + anvilResult = action; + } else if (bedrockSlotToJava(action) == 0) { + anvilInput = action; + } + } + ItemData itemName = null; + if (anvilResult != null) { + itemName = anvilResult.getFromItem(); + } else if (anvilInput != null) { + itemName = anvilInput.getToItem(); + } + if (itemName != null) { + String rename; + com.nukkitx.nbt.tag.CompoundTag tag = itemName.getTag(); + if (tag != null) { + rename = tag.getAsCompound("display").getAsString("Name"); + } else { + rename = ""; + } + ClientRenameItemPacket renameItemPacket = new ClientRenameItemPacket(rename); + session.getDownstream().getSession().send(renameItemPacket); + } + if (anvilResult != null) { + //client will send another packet to grab anvil output + return; + } + + super.translateActions(session, inventory, actions); + } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/ContainerInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BaseInventoryTranslator.java similarity index 50% rename from connector/src/main/java/org/geysermc/connector/network/translators/inventory/ContainerInventoryTranslator.java rename to connector/src/main/java/org/geysermc/connector/network/translators/inventory/BaseInventoryTranslator.java index 8f66675b..d64c0e78 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/ContainerInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BaseInventoryTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,53 +27,20 @@ package org.geysermc.connector.network.translators.inventory; import com.nukkitx.protocol.bedrock.data.ContainerId; import com.nukkitx.protocol.bedrock.data.InventoryAction; -import com.nukkitx.protocol.bedrock.data.ItemData; -import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket; -import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.inventory.action.InventoryActionTranslator; -public abstract class ContainerInventoryTranslator extends InventoryTranslator { - ContainerInventoryTranslator(int size) { +import java.util.List; + +public abstract class BaseInventoryTranslator extends InventoryTranslator{ + BaseInventoryTranslator(int size) { super(size); } - @Override - public void updateInventory(GeyserSession session, Inventory inventory) { - ItemData[] bedrockItems = new ItemData[this.size]; - for (int i = 0; i < bedrockItems.length; i++) { - bedrockItems[javaSlotToBedrock(i)] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i)); - } - InventoryContentPacket contentPacket = new InventoryContentPacket(); - contentPacket.setContainerId(inventory.getId()); - contentPacket.setContents(bedrockItems); - session.getUpstream().sendPacket(contentPacket); - - Inventory playerInventory = session.getInventory(); - for (int i = 0; i < 36; i++) { - playerInventory.setItem(i + 9, inventory.getItem(i + this.size)); - } - TranslatorsInit.getInventoryTranslators().get(playerInventory.getWindowType()).updateInventory(session, playerInventory); - } - - @Override - public void updateSlot(GeyserSession session, Inventory inventory, int slot) { - if (slot >= this.size) { - Inventory playerInventory = session.getInventory(); - playerInventory.setItem((slot + 9) - this.size, inventory.getItem(slot)); - TranslatorsInit.getInventoryTranslators().get(playerInventory.getWindowType()).updateSlot(session, playerInventory, (slot + 9) - this.size); - } else { - InventorySlotPacket slotPacket = new InventorySlotPacket(); - slotPacket.setContainerId(inventory.getId()); - slotPacket.setInventorySlot(javaSlotToBedrock(slot)); - slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(slot))); - session.getUpstream().sendPacket(slotPacket); - } - } - @Override public void updateProperty(GeyserSession session, Inventory inventory, int key, int value) { + // } @Override @@ -86,13 +53,20 @@ public abstract class ContainerInventoryTranslator extends InventoryTranslator { } else { return slotnum + this.size + 27; } - } else { - return slotnum; } + return slotnum; } @Override public int javaSlotToBedrock(int slot) { + if (slot >= this.size) { + final int tmp = slot - this.size; + if (tmp < 27) { + return tmp + 9; + } else { + return tmp - 27; + } + } return slot; } @@ -100,4 +74,9 @@ public abstract class ContainerInventoryTranslator extends InventoryTranslator { public SlotType getSlotType(int javaSlot) { return SlotType.NORMAL; } + + @Override + public void translateActions(GeyserSession session, Inventory inventory, List actions) { + InventoryActionTranslator.translate(this, session, inventory, actions); + } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BlockInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BlockInventoryTranslator.java index 54ab9bce..32dfc2a6 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BlockInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BlockInventoryTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,70 +25,47 @@ package org.geysermc.connector.network.translators.inventory; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; -import com.nukkitx.math.vector.Vector3i; -import com.nukkitx.nbt.tag.CompoundTag; import com.nukkitx.protocol.bedrock.data.ContainerType; -import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; -import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket; -import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.TranslatorsInit; -import org.geysermc.connector.network.translators.block.BlockEntry; +import org.geysermc.connector.network.translators.inventory.holder.BlockInventoryHolder; +import org.geysermc.connector.network.translators.inventory.holder.InventoryHolder; +import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater; -public class BlockInventoryTranslator extends ContainerInventoryTranslator { - final int blockId; - private final ContainerType containerType; +public class BlockInventoryTranslator extends BaseInventoryTranslator { + private final InventoryHolder holder; + private final InventoryUpdater updater; - public BlockInventoryTranslator(int size, String javaBlockIdentifier, ContainerType containerType) { + public BlockInventoryTranslator(int size, String javaBlockIdentifier, ContainerType containerType, InventoryUpdater updater) { super(size); - this.blockId = TranslatorsInit.getBlockTranslator().getBlockEntry(javaBlockIdentifier).getBedrockRuntimeId(); - this.containerType = containerType; + final int blockId = TranslatorsInit.getBlockTranslator().getBlockEntry(javaBlockIdentifier).getBedrockRuntimeId(); + this.holder = new BlockInventoryHolder(blockId, containerType); + this.updater = updater; } @Override public void prepareInventory(GeyserSession session, Inventory inventory) { - Vector3i position = session.getPlayerEntity().getPosition().toInt(); - position = position.add(Vector3i.UP); - UpdateBlockPacket blockPacket = new UpdateBlockPacket(); - blockPacket.setDataLayer(0); - blockPacket.setBlockPosition(position); - blockPacket.setRuntimeId(blockId); - blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); - session.getUpstream().sendPacket(blockPacket); - inventory.setHolderPosition(position); - - CompoundTag tag = CompoundTag.EMPTY.toBuilder() - .intTag("x", position.getX()) - .intTag("y", position.getY()) - .intTag("z", position.getZ()) - .stringTag("CustomName", inventory.getTitle()).buildRootTag(); - BlockEntityDataPacket dataPacket = new BlockEntityDataPacket(); - dataPacket.setData(tag); - dataPacket.setBlockPosition(position); - session.getUpstream().sendPacket(dataPacket); + holder.prepareInventory(this, session, inventory); } @Override public void openInventory(GeyserSession session, Inventory inventory) { - ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket(); - containerOpenPacket.setWindowId((byte) inventory.getId()); - containerOpenPacket.setType((byte) containerType.id()); - containerOpenPacket.setBlockPosition(inventory.getHolderPosition()); - containerOpenPacket.setUniqueEntityId(inventory.getHolderId()); - session.getUpstream().sendPacket(containerOpenPacket); + holder.openInventory(this, session, inventory); } @Override public void closeInventory(GeyserSession session, Inventory inventory) { - Vector3i holderPos = inventory.getHolderPosition(); - Position pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ()); - BlockEntry realBlock = session.getChunkCache().getBlockAt(pos); - UpdateBlockPacket blockPacket = new UpdateBlockPacket(); - blockPacket.setDataLayer(0); - blockPacket.setBlockPosition(holderPos); - blockPacket.setRuntimeId(realBlock.getBedrockRuntimeId()); - session.getUpstream().sendPacket(blockPacket); + holder.closeInventory(this, session, inventory); + } + + @Override + public void updateInventory(GeyserSession session, Inventory inventory) { + updater.updateInventory(this, session, inventory); + } + + @Override + public void updateSlot(GeyserSession session, Inventory inventory, int slot) { + updater.updateSlot(this, session, inventory, slot); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingStandInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingInventoryTranslator.java similarity index 86% rename from connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingStandInventoryTranslator.java rename to connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingInventoryTranslator.java index 532928e6..c5f67a03 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingStandInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingInventoryTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,10 +30,11 @@ import com.nukkitx.protocol.bedrock.data.InventoryAction; import com.nukkitx.protocol.bedrock.packet.ContainerSetDataPacket; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.inventory.updater.ContainerInventoryUpdater; -public class BrewingStandInventoryTranslator extends BlockInventoryTranslator { - public BrewingStandInventoryTranslator() { - super(5, "minecraft:brewing_stand[has_bottle_0=false,has_bottle_1=false,has_bottle_2=false]", ContainerType.BREWING_STAND); +public class BrewingInventoryTranslator extends BlockInventoryTranslator { + public BrewingInventoryTranslator() { + super(5, "minecraft:brewing_stand[has_bottle_0=false,has_bottle_1=false,has_bottle_2=false]", ContainerType.BREWING_STAND, new ContainerInventoryUpdater()); } @Override @@ -66,8 +67,8 @@ public class BrewingStandInventoryTranslator extends BlockInventoryTranslator { @Override public int bedrockSlotToJava(InventoryAction action) { - int slotnum = super.bedrockSlotToJava(action); - switch (slotnum) { + final int slot = super.bedrockSlotToJava(action); + switch (slot) { case 0: return 3; case 1: @@ -77,13 +78,13 @@ public class BrewingStandInventoryTranslator extends BlockInventoryTranslator { case 3: return 2; default: - return slotnum; + return slot; } } @Override - public int javaSlotToBedrock(int slotnum) { - switch (slotnum) { + public int javaSlotToBedrock(int slot) { + switch (slot) { case 0: return 1; case 1: @@ -92,8 +93,7 @@ public class BrewingStandInventoryTranslator extends BlockInventoryTranslator { return 3; case 3: return 0; - default: - return slotnum; } + return super.javaSlotToBedrock(slot); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingTableInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingInventoryTranslator.java similarity index 61% rename from connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingTableInventoryTranslator.java rename to connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingInventoryTranslator.java index 28ad0cb2..fe70609f 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingTableInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingInventoryTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,21 +25,33 @@ package org.geysermc.connector.network.translators.inventory; +import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import com.nukkitx.protocol.bedrock.data.ContainerId; import com.nukkitx.protocol.bedrock.data.ContainerType; import com.nukkitx.protocol.bedrock.data.InventoryAction; +import com.nukkitx.protocol.bedrock.data.InventorySource; import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket; +import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.inventory.updater.CursorInventoryUpdater; +import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater; +import org.geysermc.connector.utils.InventoryUtils; -public class CraftingTableInventoryTranslator extends ContainerInventoryTranslator { - public CraftingTableInventoryTranslator() { +import java.util.List; + +public class CraftingInventoryTranslator extends BaseInventoryTranslator { + private final InventoryUpdater updater; + + public CraftingInventoryTranslator() { super(10); + this.updater = new CursorInventoryUpdater(); } @Override public void prepareInventory(GeyserSession session, Inventory inventory) { - + // } @Override @@ -54,7 +66,17 @@ public class CraftingTableInventoryTranslator extends ContainerInventoryTranslat @Override public void closeInventory(GeyserSession session, Inventory inventory) { + // + } + @Override + public void updateInventory(GeyserSession session, Inventory inventory) { + updater.updateInventory(this, session, inventory); + } + + @Override + public void updateSlot(GeyserSession session, Inventory inventory, int slot) { + updater.updateSlot(this, session, inventory, slot); } @Override @@ -70,10 +92,29 @@ public class CraftingTableInventoryTranslator extends ContainerInventoryTranslat return super.bedrockSlotToJava(action); } + @Override + public int javaSlotToBedrock(int slot) { + return slot == 0 ? 50 : slot + 31; + } + @Override public SlotType getSlotType(int javaSlot) { if (javaSlot == 0) return SlotType.OUTPUT; return SlotType.NORMAL; } + + @Override + public void translateActions(GeyserSession session, Inventory inventory, List actions) { + if (session.getGameMode() == GameMode.CREATIVE) { + for (InventoryAction action : actions) { + if (action.getSource().getType() == InventorySource.Type.CREATIVE) { + updateInventory(session, inventory); + InventoryUtils.updateCursor(session); + return; + } + } + } + super.translateActions(session, inventory, actions); + } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java index e0825ed8..07d3a414 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,32 +29,39 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.nukkitx.math.vector.Vector3i; import com.nukkitx.nbt.tag.CompoundTag; import com.nukkitx.protocol.bedrock.data.ContainerType; -import com.nukkitx.protocol.bedrock.data.ItemData; import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; -import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket; +import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.TranslatorsInit; import org.geysermc.connector.network.translators.block.BlockEntry; +import org.geysermc.connector.network.translators.inventory.updater.ChestInventoryUpdater; +import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater; + +public class DoubleChestInventoryTranslator extends BaseInventoryTranslator { + private final int blockId; + private final InventoryUpdater updater; -public class DoubleChestInventoryTranslator extends BlockInventoryTranslator { public DoubleChestInventoryTranslator(int size) { - super(size, "minecraft:chest[facing=north,type=single,waterlogged=false]", ContainerType.CONTAINER); + super(size); + this.blockId = TranslatorsInit.getBlockTranslator().getBlockEntry("minecraft:chest[facing=north,type=single,waterlogged=false]").getBedrockRuntimeId(); + this.updater = new ChestInventoryUpdater(54); } @Override public void prepareInventory(GeyserSession session, Inventory inventory) { Vector3i position = session.getPlayerEntity().getPosition().toInt().add(Vector3i.UP); Vector3i pairPosition = position.add(Vector3i.UNIT_X); + UpdateBlockPacket blockPacket = new UpdateBlockPacket(); blockPacket.setDataLayer(0); blockPacket.setBlockPosition(position); blockPacket.setRuntimeId(blockId); - blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); + blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY); session.getUpstream().sendPacket(blockPacket); - CompoundTag tag = CompoundTag.EMPTY.toBuilder() + CompoundTag tag = CompoundTag.builder() .stringTag("id", "Chest") .intTag("x", position.getX()) .intTag("y", position.getY()) @@ -71,10 +78,10 @@ public class DoubleChestInventoryTranslator extends BlockInventoryTranslator { blockPacket.setDataLayer(0); blockPacket.setBlockPosition(pairPosition); blockPacket.setRuntimeId(blockId); - blockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); + blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY); session.getUpstream().sendPacket(blockPacket); - tag = CompoundTag.EMPTY.toBuilder() + tag = CompoundTag.builder() .stringTag("id", "Chest") .intTag("x", pairPosition.getX()) .intTag("y", pairPosition.getY()) @@ -90,6 +97,16 @@ public class DoubleChestInventoryTranslator extends BlockInventoryTranslator { inventory.setHolderPosition(position); } + @Override + public void openInventory(GeyserSession session, Inventory inventory) { + ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket(); + containerOpenPacket.setWindowId((byte) inventory.getId()); + containerOpenPacket.setType((byte) ContainerType.CONTAINER.id()); + containerOpenPacket.setBlockPosition(inventory.getHolderPosition()); + containerOpenPacket.setUniqueEntityId(inventory.getHolderId()); + session.getUpstream().sendPacket(containerOpenPacket); + } + @Override public void closeInventory(GeyserSession session, Inventory inventory) { Vector3i holderPos = inventory.getHolderPosition(); @@ -113,24 +130,11 @@ public class DoubleChestInventoryTranslator extends BlockInventoryTranslator { @Override public void updateInventory(GeyserSession session, Inventory inventory) { - //need to pad empty slots for 4x9 and 5x9 - ItemData[] bedrockItems = new ItemData[54]; - for (int i = 0; i < bedrockItems.length; i++) { - if (i <= this.size) { - bedrockItems[i] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i)); - } else { - bedrockItems[i] = ItemData.AIR; - } - } - InventoryContentPacket contentPacket = new InventoryContentPacket(); - contentPacket.setContainerId(inventory.getId()); - contentPacket.setContents(bedrockItems); - session.getUpstream().sendPacket(contentPacket); + updater.updateInventory(this, session, inventory); + } - Inventory playerInventory = session.getInventory(); - for (int i = 0; i < 36; i++) { - playerInventory.setItem(i + 9, inventory.getItem(i + this.size)); - } - TranslatorsInit.getInventoryTranslators().get(playerInventory.getWindowType()).updateInventory(session, playerInventory); + @Override + public void updateSlot(GeyserSession session, Inventory inventory, int slot) { + updater.updateSlot(this, session, inventory, slot); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/EnchantmentInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/EnchantmentInventoryTranslator.java index 0b4ed4ba..ba7f8cc7 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/EnchantmentInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/EnchantmentInventoryTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,10 +28,11 @@ package org.geysermc.connector.network.translators.inventory; import com.nukkitx.protocol.bedrock.data.ContainerType; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.inventory.updater.ContainerInventoryUpdater; public class EnchantmentInventoryTranslator extends BlockInventoryTranslator { public EnchantmentInventoryTranslator() { - super(2, "minecraft:enchanting_table", ContainerType.ENCHANTMENT); + super(2, "minecraft:enchanting_table", ContainerType.ENCHANTMENT, new ContainerInventoryUpdater()); } @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java index a2eefac4..9b45201e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,10 +30,11 @@ import com.nukkitx.protocol.bedrock.data.ContainerType; import com.nukkitx.protocol.bedrock.packet.ContainerSetDataPacket; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.inventory.updater.ContainerInventoryUpdater; public class FurnaceInventoryTranslator extends BlockInventoryTranslator { public FurnaceInventoryTranslator() { - super(3, "minecraft:furnace[facing=north,lit=false]", ContainerType.FURNACE); + super(3, "minecraft:furnace[facing=north,lit=false]", ContainerType.FURNACE, new ContainerInventoryUpdater()); } @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java index 91562194..7baef61a 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java @@ -26,16 +26,16 @@ package org.geysermc.connector.network.translators.inventory; import com.nukkitx.protocol.bedrock.data.InventoryAction; +import lombok.AllArgsConstructor; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; +import java.util.List; + +@AllArgsConstructor public abstract class InventoryTranslator { public final int size; - InventoryTranslator(int size) { - this.size = size; - } - public abstract void prepareInventory(GeyserSession session, Inventory inventory); public abstract void openInventory(GeyserSession session, Inventory inventory); public abstract void closeInventory(GeyserSession session, Inventory inventory); @@ -45,4 +45,5 @@ public abstract class InventoryTranslator { public abstract int bedrockSlotToJava(InventoryAction action); public abstract int javaSlotToBedrock(int slot); public abstract SlotType getSlotType(int javaSlot); + public abstract void translateActions(GeyserSession session, Inventory inventory, List actions); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java index 6ba25bc5..acad709f 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,12 +25,19 @@ package org.geysermc.connector.network.translators.inventory; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; +import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientCreativeInventoryActionPacket; import com.nukkitx.protocol.bedrock.data.*; import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket; import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.inventory.action.InventoryActionTranslator; +import org.geysermc.connector.utils.InventoryUtils; + +import java.util.List; public class PlayerInventoryTranslator extends InventoryTranslator { public PlayerInventoryTranslator() { @@ -39,20 +46,26 @@ public class PlayerInventoryTranslator extends InventoryTranslator { @Override public void updateInventory(GeyserSession session, Inventory inventory) { + // Crafting grid + for (int i = 1; i < 5; i++) { + InventorySlotPacket slotPacket = new InventorySlotPacket(); + slotPacket.setContainerId(ContainerId.CURSOR); + slotPacket.setInventorySlot(i + 27); + slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i))); + session.getUpstream().sendPacket(slotPacket); + } + InventoryContentPacket inventoryContentPacket = new InventoryContentPacket(); inventoryContentPacket.setContainerId(ContainerId.INVENTORY); - ItemData[] contents = new ItemData[36]; // Inventory for (int i = 9; i < 36; i++) { contents[i] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i)); } - // Hotbar for (int i = 36; i < 45; i++) { contents[i - 36] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i)); } - inventoryContentPacket.setContents(contents); session.getUpstream().sendPacket(inventoryContentPacket); @@ -75,7 +88,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { @Override public void updateSlot(GeyserSession session, Inventory inventory, int slot) { - if (slot >= 5 && slot <= 44) { + if (slot >= 1 && slot <= 44) { InventorySlotPacket slotPacket = new InventorySlotPacket(); if (slot >= 9) { slotPacket.setContainerId(ContainerId.INVENTORY); @@ -84,9 +97,12 @@ public class PlayerInventoryTranslator extends InventoryTranslator { } else { slotPacket.setInventorySlot(slot); } - } else { + } else if (slot >= 5) { slotPacket.setContainerId(ContainerId.ARMOR); slotPacket.setInventorySlot(slot - 5); + } else { + slotPacket.setContainerId(ContainerId.CURSOR); + slotPacket.setInventorySlot(slot + 27); } slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(slot))); session.getUpstream().sendPacket(slotPacket); @@ -142,6 +158,55 @@ public class PlayerInventoryTranslator extends InventoryTranslator { return SlotType.NORMAL; } + @Override + public void translateActions(GeyserSession session, Inventory inventory, List actions) { + if (session.getGameMode() == GameMode.CREATIVE) { + //crafting grid is not visible in creative mode in java edition + for (InventoryAction action : actions) { + if (action.getSource().getContainerId() == ContainerId.CURSOR && (action.getSlot() >= 28 && 31 >= action.getSlot())) { + updateInventory(session, inventory); + InventoryUtils.updateCursor(session); + return; + } + } + + ItemStack javaItem; + for (InventoryAction action : actions) { + switch (action.getSource().getContainerId()) { + case ContainerId.INVENTORY: + case ContainerId.ARMOR: + case ContainerId.OFFHAND: + int javaSlot = bedrockSlotToJava(action); + if (action.getToItem().getId() == 0) { + javaItem = new ItemStack(-1, 0, null); + } else { + javaItem = TranslatorsInit.getItemTranslator().translateToJava(action.getToItem()); + } + ClientCreativeInventoryActionPacket creativePacket = new ClientCreativeInventoryActionPacket(javaSlot, InventoryUtils.fixStack(javaItem)); + session.getDownstream().getSession().send(creativePacket); + inventory.setItem(javaSlot, javaItem); + break; + case ContainerId.CURSOR: + if (action.getSlot() == 0) { + session.getInventory().setCursor(TranslatorsInit.getItemTranslator().translateToJava(action.getToItem())); + } + break; + case ContainerId.NONE: + if (action.getSource().getType() == InventorySource.Type.WORLD_INTERACTION + && action.getSource().getFlag() == InventorySource.Flag.DROP_ITEM) { + javaItem = TranslatorsInit.getItemTranslator().translateToJava(action.getToItem()); + ClientCreativeInventoryActionPacket creativeDropPacket = new ClientCreativeInventoryActionPacket(-1, InventoryUtils.fixStack(javaItem)); + session.getDownstream().getSession().send(creativeDropPacket); + } + break; + } + } + return; + } + + InventoryActionTranslator.translate(this, session, inventory, actions); + } + @Override public void prepareInventory(GeyserSession session, Inventory inventory) { } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java index 84426eaa..5c99b012 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java @@ -26,37 +26,10 @@ package org.geysermc.connector.network.translators.inventory; import com.nukkitx.protocol.bedrock.data.ContainerType; -import com.nukkitx.protocol.bedrock.data.ItemData; -import com.nukkitx.protocol.bedrock.packet.*; -import org.geysermc.connector.inventory.Inventory; -import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.inventory.updater.ChestInventoryUpdater; public class SingleChestInventoryTranslator extends BlockInventoryTranslator { public SingleChestInventoryTranslator(int size) { - super(size, "minecraft:chest[facing=north,type=single,waterlogged=false]", ContainerType.CONTAINER); - } - - @Override - public void updateInventory(GeyserSession session, Inventory inventory) { - //need to pad empty slots for 1x9 and 2x9 - ItemData[] bedrockItems = new ItemData[27]; - for (int i = 0; i < bedrockItems.length; i++) { - if (i <= this.size) { - bedrockItems[i] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i)); - } else { - bedrockItems[i] = ItemData.AIR; - } - } - InventoryContentPacket contentPacket = new InventoryContentPacket(); - contentPacket.setContainerId(inventory.getId()); - contentPacket.setContents(bedrockItems); - session.getUpstream().sendPacket(contentPacket); - - Inventory playerInventory = session.getInventory(); - for (int i = 0; i < 36; i++) { - playerInventory.setItem(i + 9, inventory.getItem(i + this.size)); - } - TranslatorsInit.getInventoryTranslators().get(playerInventory.getWindowType()).updateInventory(session, playerInventory); + super(size, "minecraft:chest[facing=north,type=single,waterlogged=false]", ContainerType.CONTAINER, new ChestInventoryUpdater(27)); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SlotType.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SlotType.java index b5657af4..045adbd3 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SlotType.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SlotType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/Click.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/Click.java new file mode 100644 index 00000000..1fdfa364 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/Click.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.inventory.action; + +import com.github.steveice10.mc.protocol.data.game.window.ClickItemParam; +import com.github.steveice10.mc.protocol.data.game.window.WindowActionParam; +import lombok.AllArgsConstructor; + +@AllArgsConstructor +enum Click { + LEFT(ClickItemParam.LEFT_CLICK), + RIGHT(ClickItemParam.RIGHT_CLICK); + + public final WindowActionParam actionParam; +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/ClickPlan.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/ClickPlan.java new file mode 100644 index 00000000..3abdd284 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/ClickPlan.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.inventory.action; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.window.WindowAction; +import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientConfirmTransactionPacket; +import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientWindowActionPacket; +import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.inventory.PlayerInventory; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.inventory.InventoryTranslator; +import org.geysermc.connector.network.translators.inventory.SlotType; +import org.geysermc.connector.utils.InventoryUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +class ClickPlan { + private final List plan = new ArrayList<>(); + + public void add(Click click, int slot) { + plan.add(new ClickAction(click, slot)); + } + + public void execute(GeyserSession session, InventoryTranslator translator, Inventory inventory, boolean refresh) { + PlayerInventory playerInventory = session.getInventory(); + ListIterator planIter = plan.listIterator(); + while (planIter.hasNext()) { + final ClickAction action = planIter.next(); + final ItemStack cursorItem = playerInventory.getCursor(); + final ItemStack clickedItem = inventory.getItem(action.slot); + final short actionId = (short) inventory.getTransactionId().getAndIncrement(); + + //TODO: stop relying on refreshing the inventory for crafting to work properly + if (translator.getSlotType(action.slot) != SlotType.NORMAL) + refresh = true; + + ClientWindowActionPacket clickPacket = new ClientWindowActionPacket(inventory.getId(), + actionId, action.slot, !planIter.hasNext() && refresh ? InventoryUtils.REFRESH_ITEM : InventoryUtils.fixStack(clickedItem), + WindowAction.CLICK_ITEM, action.click.actionParam); + + if (translator.getSlotType(action.slot) == SlotType.OUTPUT) { + if (cursorItem == null && clickedItem != null) { + playerInventory.setCursor(clickedItem); + } else if (InventoryUtils.canStack(cursorItem, clickedItem)) { + playerInventory.setCursor(new ItemStack(cursorItem.getId(), + cursorItem.getAmount() + clickedItem.getAmount(), cursorItem.getNbt())); + } + } else { + switch (action.click) { + case LEFT: + if (!InventoryUtils.canStack(cursorItem, clickedItem)) { + playerInventory.setCursor(clickedItem); + inventory.setItem(action.slot, cursorItem); + } else { + playerInventory.setCursor(null); + inventory.setItem(action.slot, new ItemStack(clickedItem.getId(), + clickedItem.getAmount() + cursorItem.getAmount(), clickedItem.getNbt())); + } + break; + case RIGHT: + if (cursorItem == null && clickedItem != null) { + ItemStack halfItem = new ItemStack(clickedItem.getId(), + clickedItem.getAmount() / 2, clickedItem.getNbt()); + inventory.setItem(action.slot, halfItem); + playerInventory.setCursor(new ItemStack(clickedItem.getId(), + clickedItem.getAmount() - halfItem.getAmount(), clickedItem.getNbt())); + } else if (cursorItem != null && clickedItem == null) { + playerInventory.setCursor(new ItemStack(cursorItem.getId(), + cursorItem.getAmount() - 1, cursorItem.getNbt())); + inventory.setItem(action.slot, new ItemStack(cursorItem.getId(), + 1, cursorItem.getNbt())); + } else if (InventoryUtils.canStack(cursorItem, clickedItem)) { + playerInventory.setCursor(new ItemStack(cursorItem.getId(), + cursorItem.getAmount() - 1, cursorItem.getNbt())); + inventory.setItem(action.slot, new ItemStack(clickedItem.getId(), + clickedItem.getAmount() + 1, clickedItem.getNbt())); + } + break; + } + } + session.getDownstream().getSession().send(clickPacket); + session.getDownstream().getSession().send(new ClientConfirmTransactionPacket(inventory.getId(), actionId, true)); + } + + /*if (refresh) { + translator.updateInventory(session, inventory); + InventoryUtils.updateCursor(session); + }*/ + } + + private static class ClickAction { + final Click click; + final int slot; + ClickAction(Click click, int slot) { + this.click = click; + this.slot = slot; + } + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionTranslator.java new file mode 100644 index 00000000..586c2c02 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionTranslator.java @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.inventory.action; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; +import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction; +import com.github.steveice10.mc.protocol.data.game.window.*; +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.window.ClientWindowActionPacket; +import com.nukkitx.protocol.bedrock.data.ContainerId; +import com.nukkitx.protocol.bedrock.data.InventoryAction; +import com.nukkitx.protocol.bedrock.data.InventorySource; +import com.nukkitx.protocol.bedrock.data.ItemData; +import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.inventory.InventoryTranslator; +import org.geysermc.connector.network.translators.inventory.SlotType; +import org.geysermc.connector.utils.InventoryUtils; + +import java.util.*; + +public class InventoryActionTranslator { + public static void translate(InventoryTranslator translator, GeyserSession session, Inventory inventory, List actions) { + if (actions.size() != 2) + return; + + InventoryAction worldAction = null; + InventoryAction cursorAction = null; + InventoryAction containerAction = null; + boolean refresh = false; + for (InventoryAction action : actions) { + if (action.getSource().getContainerId() == ContainerId.CRAFTING_USE_INGREDIENT || action.getSource().getContainerId() == ContainerId.CRAFTING_RESULT) { + return; + } else if (action.getSource().getType() == InventorySource.Type.WORLD_INTERACTION) { + worldAction = action; + } else if (action.getSource().getContainerId() == ContainerId.CURSOR && action.getSlot() == 0) { + cursorAction = action; + ItemData translatedCursor = TranslatorsInit.getItemTranslator().translateToBedrock(session.getInventory().getCursor()); + if (!translatedCursor.equals(action.getFromItem())) { + refresh = true; + } + } else { + containerAction = action; + ItemData translatedItem = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(translator.bedrockSlotToJava(action))); + if (!translatedItem.equals(action.getFromItem())) { + refresh = true; + } + } + } + + final int craftSlot = session.getCraftSlot(); + session.setCraftSlot(0); + + if (worldAction != null) { + InventoryAction sourceAction; + if (cursorAction != null) { + sourceAction = cursorAction; + } else { + sourceAction = containerAction; + } + + if (sourceAction != null) { + if (worldAction.getSource().getFlag() == InventorySource.Flag.DROP_ITEM) { + //quick dropping from hotbar? + if (session.getInventoryCache().getOpenInventory() == null && sourceAction.getSource().getContainerId() == ContainerId.INVENTORY) { + int heldSlot = session.getInventory().getHeldItemSlot(); + if (sourceAction.getSlot() == heldSlot) { + ClientPlayerActionPacket actionPacket = new ClientPlayerActionPacket( + sourceAction.getToItem().getCount() == 0 ? PlayerAction.DROP_ITEM_STACK : PlayerAction.DROP_ITEM, + new Position(0, 0, 0), BlockFace.DOWN); + session.getDownstream().getSession().send(actionPacket); + ItemStack item = session.getInventory().getItem(heldSlot); + if (item != null) { + session.getInventory().setItem(heldSlot, new ItemStack(item.getId(), item.getAmount() - 1, item.getNbt())); + } + return; + } + } + int dropAmount = sourceAction.getFromItem().getCount() - sourceAction.getToItem().getCount(); + if (sourceAction != cursorAction) { //dropping directly from inventory + int javaSlot = translator.bedrockSlotToJava(sourceAction); + if (dropAmount == sourceAction.getFromItem().getCount()) { + ClientWindowActionPacket dropPacket = new ClientWindowActionPacket(inventory.getId(), + inventory.getTransactionId().getAndIncrement(), + javaSlot, null, WindowAction.DROP_ITEM, + DropItemParam.DROP_SELECTED_STACK); + session.getDownstream().getSession().send(dropPacket); + } else { + for (int i = 0; i < dropAmount; i++) { + ClientWindowActionPacket dropPacket = new ClientWindowActionPacket(inventory.getId(), + inventory.getTransactionId().getAndIncrement(), + javaSlot, null, WindowAction.DROP_ITEM, + DropItemParam.DROP_FROM_SELECTED); + session.getDownstream().getSession().send(dropPacket); + } + } + ItemStack item = session.getInventory().getItem(javaSlot); + if (item != null) { + session.getInventory().setItem(javaSlot, new ItemStack(item.getId(), item.getAmount() - dropAmount, item.getNbt())); + } + return; + } else { //clicking outside of inventory + ClientWindowActionPacket dropPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getTransactionId().getAndIncrement(), + -999, null, WindowAction.CLICK_ITEM, + dropAmount > 1 ? ClickItemParam.LEFT_CLICK : ClickItemParam.RIGHT_CLICK); + session.getDownstream().getSession().send(dropPacket); + ItemStack cursor = session.getInventory().getCursor(); + if (cursor != null) { + session.getInventory().setCursor(new ItemStack(cursor.getId(), dropAmount > 1 ? 0 : cursor.getAmount() - 1, cursor.getNbt())); + } + return; + } + } + } + } else if (cursorAction != null && containerAction != null) { + //left/right click + ClickPlan plan = new ClickPlan(); + int javaSlot = translator.bedrockSlotToJava(containerAction); + if (cursorAction.getFromItem().equals(containerAction.getToItem()) + && containerAction.getFromItem().equals(cursorAction.getToItem()) + && !InventoryUtils.canStack(cursorAction.getFromItem(), containerAction.getFromItem())) { //simple swap + plan.add(Click.LEFT, javaSlot); + } else if (cursorAction.getFromItem().getCount() > cursorAction.getToItem().getCount()) { //release + if (cursorAction.getToItem().getCount() == 0) { + plan.add(Click.LEFT, javaSlot); + } else { + int difference = cursorAction.getFromItem().getCount() - cursorAction.getToItem().getCount(); + for (int i = 0; i < difference; i++) { + plan.add(Click.RIGHT, javaSlot); + } + } + } else { //pickup + if (cursorAction.getFromItem().getCount() == 0) { + if (containerAction.getToItem().getCount() == 0) { //pickup all + plan.add(Click.LEFT, javaSlot); + } else { //pickup some + if (translator.getSlotType(javaSlot) == SlotType.FURNACE_OUTPUT + || containerAction.getToItem().getCount() == containerAction.getFromItem().getCount() / 2) { //right click + plan.add(Click.RIGHT, javaSlot); + } else { + plan.add(Click.LEFT, javaSlot); + int difference = containerAction.getFromItem().getCount() - cursorAction.getToItem().getCount(); + for (int i = 0; i < difference; i++) { + plan.add(Click.RIGHT, javaSlot); + } + } + } + } else { //pickup into non-empty cursor + if (translator.getSlotType(javaSlot) == SlotType.FURNACE_OUTPUT) { + if (containerAction.getToItem().getCount() == 0) { + plan.add(Click.LEFT, javaSlot); + } else { + ClientWindowActionPacket shiftClickPacket = new ClientWindowActionPacket(inventory.getId(), + inventory.getTransactionId().getAndIncrement(), + javaSlot, InventoryUtils.REFRESH_ITEM, WindowAction.SHIFT_CLICK_ITEM, + ShiftClickItemParam.LEFT_CLICK); + session.getDownstream().getSession().send(shiftClickPacket); + translator.updateInventory(session, inventory); + return; + } + } else if (translator.getSlotType(javaSlot) == SlotType.OUTPUT) { + plan.add(Click.LEFT, javaSlot); + } else { + int cursorSlot = findTempSlot(inventory, session.getInventory().getCursor(), Collections.singletonList(javaSlot)); + if (cursorSlot != -1) { + plan.add(Click.LEFT, cursorSlot); + } else { + translator.updateInventory(session, inventory); + return; + } + plan.add(Click.LEFT, javaSlot); + int difference = cursorAction.getToItem().getCount() - cursorAction.getFromItem().getCount(); + for (int i = 0; i < difference; i++) { + plan.add(Click.RIGHT, cursorSlot); + } + plan.add(Click.LEFT, javaSlot); + plan.add(Click.LEFT, cursorSlot); + } + } + } + plan.execute(session, translator, inventory, refresh); + return; + } else { + ClickPlan plan = new ClickPlan(); + InventoryAction fromAction; + InventoryAction toAction; + if (actions.get(0).getFromItem().getCount() >= actions.get(0).getToItem().getCount()) { + fromAction = actions.get(0); + toAction = actions.get(1); + } else { + fromAction = actions.get(1); + toAction = actions.get(0); + } + int fromSlot = translator.bedrockSlotToJava(fromAction); + int toSlot = translator.bedrockSlotToJava(toAction); + + if (translator.getSlotType(fromSlot) == SlotType.OUTPUT) { + if ((craftSlot != 0 && craftSlot != -2) && (inventory.getItem(toSlot) == null + || InventoryUtils.canStack(session.getInventory().getCursor(), inventory.getItem(toSlot)))) { + if (fromAction.getToItem().getCount() == 0) { + refresh = true; + plan.add(Click.LEFT, toSlot); + if (craftSlot != -1) { + plan.add(Click.LEFT, craftSlot); + } + } else { + int difference = toAction.getToItem().getCount() - toAction.getFromItem().getCount(); + for (int i = 0; i < difference; i++) { + plan.add(Click.RIGHT, toSlot); + } + session.setCraftSlot(craftSlot); + } + plan.execute(session, translator, inventory, refresh); + return; + } else { + session.setCraftSlot(-2); + } + } + + int cursorSlot = -1; + if (session.getInventory().getCursor() != null) { //move cursor contents to a temporary slot + cursorSlot = findTempSlot(inventory, session.getInventory().getCursor(), Arrays.asList(fromSlot, toSlot)); + if (cursorSlot != -1) { + plan.add(Click.LEFT, cursorSlot); + } else { + translator.updateInventory(session, inventory); + return; + } + } + if ((fromAction.getFromItem().equals(toAction.getToItem()) && !InventoryUtils.canStack(fromAction.getFromItem(), toAction.getFromItem())) + || fromAction.getToItem().getId() == 0) { //slot swap + plan.add(Click.LEFT, fromSlot); + plan.add(Click.LEFT, toSlot); + if (fromAction.getToItem().getId() != 0) { + plan.add(Click.LEFT, fromSlot); + } + } else if (InventoryUtils.canStack(fromAction.getFromItem(), toAction.getToItem())) { //partial item move + if (translator.getSlotType(fromSlot) == SlotType.FURNACE_OUTPUT) { + ClientWindowActionPacket shiftClickPacket = new ClientWindowActionPacket(inventory.getId(), + inventory.getTransactionId().getAndIncrement(), + fromSlot, InventoryUtils.REFRESH_ITEM, WindowAction.SHIFT_CLICK_ITEM, + ShiftClickItemParam.LEFT_CLICK); + session.getDownstream().getSession().send(shiftClickPacket); + translator.updateInventory(session, inventory); + return; + } else if (translator.getSlotType(fromSlot) == SlotType.OUTPUT) { + session.setCraftSlot(cursorSlot); + plan.add(Click.LEFT, fromSlot); + int difference = toAction.getToItem().getCount() - toAction.getFromItem().getCount(); + for (int i = 0; i < difference; i++) { + plan.add(Click.RIGHT, toSlot); + } + //client will send additional packets later to finish transferring crafting output + //translator will know how to handle this using the craftSlot variable + } else { + plan.add(Click.LEFT, fromSlot); + int difference = toAction.getToItem().getCount() - toAction.getFromItem().getCount(); + for (int i = 0; i < difference; i++) { + plan.add(Click.RIGHT, toSlot); + } + plan.add(Click.LEFT, fromSlot); + } + } + if (cursorSlot != -1) { + plan.add(Click.LEFT, cursorSlot); + } + plan.execute(session, translator, inventory, refresh); + return; + } + + translator.updateInventory(session, inventory); + InventoryUtils.updateCursor(session); + } + + private static int findTempSlot(Inventory inventory, ItemStack item, List slotBlacklist) { + /*try and find a slot that can temporarily store the given item + only look in the main inventory and hotbar + only slots that are empty or contain a different type of item are valid*/ + int offset = inventory.getId() == 0 ? 1 : 0; //offhand is not a viable slot (some servers disable it) + List itemBlacklist = new ArrayList<>(slotBlacklist.size() + 1); + itemBlacklist.add(item); + for (int slot : slotBlacklist) { + ItemStack blacklistItem = inventory.getItem(slot); + if (blacklistItem != null) + itemBlacklist.add(blacklistItem); + } + for (int i = inventory.getSize() - (36 + offset); i < inventory.getSize() - offset; i++) { + ItemStack testItem = inventory.getItem(i); + boolean acceptable = true; + if (testItem != null) { + for (ItemStack blacklistItem : itemBlacklist) { + if (InventoryUtils.canStack(testItem, blacklistItem)) { + acceptable = false; + break; + } + } + } + if (acceptable && !slotBlacklist.contains(i)) + return i; + } + //could not find a viable temp slot + return -1; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/holder/BlockInventoryHolder.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/holder/BlockInventoryHolder.java new file mode 100644 index 00000000..6c0db853 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/holder/BlockInventoryHolder.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.inventory.holder; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; +import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.nbt.tag.CompoundTag; +import com.nukkitx.protocol.bedrock.data.ContainerType; +import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; +import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket; +import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; +import lombok.AllArgsConstructor; +import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.block.BlockEntry; +import org.geysermc.connector.network.translators.inventory.InventoryTranslator; + +@AllArgsConstructor +public class BlockInventoryHolder extends InventoryHolder { + private final int blockId; + private final ContainerType containerType; + + @Override + public void prepareInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) { + Vector3i position = session.getPlayerEntity().getPosition().toInt(); + position = position.add(Vector3i.UP); + UpdateBlockPacket blockPacket = new UpdateBlockPacket(); + blockPacket.setDataLayer(0); + blockPacket.setBlockPosition(position); + blockPacket.setRuntimeId(blockId); + blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY); + session.getUpstream().sendPacket(blockPacket); + inventory.setHolderPosition(position); + + CompoundTag tag = CompoundTag.builder() + .intTag("x", position.getX()) + .intTag("y", position.getY()) + .intTag("z", position.getZ()) + .stringTag("CustomName", inventory.getTitle()).buildRootTag(); + BlockEntityDataPacket dataPacket = new BlockEntityDataPacket(); + dataPacket.setData(tag); + dataPacket.setBlockPosition(position); + session.getUpstream().sendPacket(dataPacket); + } + + @Override + public void openInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) { + ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket(); + containerOpenPacket.setWindowId((byte) inventory.getId()); + containerOpenPacket.setType((byte) containerType.id()); + containerOpenPacket.setBlockPosition(inventory.getHolderPosition()); + containerOpenPacket.setUniqueEntityId(inventory.getHolderId()); + session.getUpstream().sendPacket(containerOpenPacket); + } + + @Override + public void closeInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) { + Vector3i holderPos = inventory.getHolderPosition(); + Position pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ()); + BlockEntry realBlock = session.getChunkCache().getBlockAt(pos); + UpdateBlockPacket blockPacket = new UpdateBlockPacket(); + blockPacket.setDataLayer(0); + blockPacket.setBlockPosition(holderPos); + blockPacket.setRuntimeId(realBlock.getBedrockRuntimeId()); + session.getUpstream().sendPacket(blockPacket); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/holder/InventoryHolder.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/holder/InventoryHolder.java new file mode 100644 index 00000000..5a9e736e --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/holder/InventoryHolder.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.inventory.holder; + +import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.inventory.InventoryTranslator; + +public abstract class InventoryHolder { + public abstract void prepareInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory); + public abstract void openInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory); + public abstract void closeInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory); +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java new file mode 100644 index 00000000..4af1fba1 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.inventory.updater; + +import com.nukkitx.protocol.bedrock.data.ItemData; +import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket; +import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; +import lombok.AllArgsConstructor; +import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.inventory.InventoryTranslator; + +@AllArgsConstructor +public class ChestInventoryUpdater extends InventoryUpdater { + private final int paddedSize; + + @Override + public void updateInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) { + super.updateInventory(translator, session, inventory); + + ItemData[] bedrockItems = new ItemData[paddedSize]; + for (int i = 0; i < bedrockItems.length; i++) { + if (i <= translator.size) { + bedrockItems[i] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i)); + } else { + bedrockItems[i] = ItemData.AIR; + } + } + + InventoryContentPacket contentPacket = new InventoryContentPacket(); + contentPacket.setContainerId(inventory.getId()); + contentPacket.setContents(bedrockItems); + session.getUpstream().sendPacket(contentPacket); + } + + @Override + public boolean updateSlot(InventoryTranslator translator, GeyserSession session, Inventory inventory, int javaSlot) { + if (super.updateSlot(translator, session, inventory, javaSlot)) + return true; + + InventorySlotPacket slotPacket = new InventorySlotPacket(); + slotPacket.setContainerId(inventory.getId()); + slotPacket.setInventorySlot(translator.javaSlotToBedrock(javaSlot)); + slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(javaSlot))); + session.getUpstream().sendPacket(slotPacket); + return true; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java new file mode 100644 index 00000000..7169311e --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.inventory.updater; + +import com.nukkitx.protocol.bedrock.data.ItemData; +import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket; +import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; +import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.inventory.InventoryTranslator; + +public class ContainerInventoryUpdater extends InventoryUpdater { + @Override + public void updateInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) { + super.updateInventory(translator, session, inventory); + + ItemData[] bedrockItems = new ItemData[translator.size]; + for (int i = 0; i < bedrockItems.length; i++) { + bedrockItems[translator.javaSlotToBedrock(i)] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i)); + } + + InventoryContentPacket contentPacket = new InventoryContentPacket(); + contentPacket.setContainerId(inventory.getId()); + contentPacket.setContents(bedrockItems); + session.getUpstream().sendPacket(contentPacket); + } + + @Override + public boolean updateSlot(InventoryTranslator translator, GeyserSession session, Inventory inventory, int javaSlot) { + if (super.updateSlot(translator, session, inventory, javaSlot)) + return true; + + InventorySlotPacket slotPacket = new InventorySlotPacket(); + slotPacket.setContainerId(inventory.getId()); + slotPacket.setInventorySlot(translator.javaSlotToBedrock(javaSlot)); + slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(javaSlot))); + session.getUpstream().sendPacket(slotPacket); + return true; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java new file mode 100644 index 00000000..3df8d766 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.inventory.updater; + +import com.nukkitx.protocol.bedrock.data.ContainerId; +import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; +import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.inventory.InventoryTranslator; + +public class CursorInventoryUpdater extends InventoryUpdater { + @Override + public void updateInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) { + super.updateInventory(translator, session, inventory); + + for (int i = 0; i < translator.size; i++) { + final int bedrockSlot = translator.javaSlotToBedrock(i); + if (bedrockSlot == 50) + continue; + InventorySlotPacket slotPacket = new InventorySlotPacket(); + slotPacket.setContainerId(ContainerId.CURSOR); + slotPacket.setInventorySlot(bedrockSlot); + slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i))); + session.getUpstream().sendPacket(slotPacket); + } + } + + @Override + public boolean updateSlot(InventoryTranslator translator, GeyserSession session, Inventory inventory, int javaSlot) { + if (super.updateSlot(translator, session, inventory, javaSlot)) + return true; + + InventorySlotPacket slotPacket = new InventorySlotPacket(); + slotPacket.setContainerId(ContainerId.CURSOR); + slotPacket.setInventorySlot(translator.javaSlotToBedrock(javaSlot)); + slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(javaSlot))); + session.getUpstream().sendPacket(slotPacket); + return true; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java new file mode 100644 index 00000000..e5b6f4c5 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.inventory.updater; + +import com.nukkitx.protocol.bedrock.data.ContainerId; +import com.nukkitx.protocol.bedrock.data.ItemData; +import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket; +import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; +import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.inventory.InventoryTranslator; + +public abstract class InventoryUpdater { + public void updateInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) { + ItemData[] bedrockItems = new ItemData[36]; + for (int i = 0; i < 36; i++) { + final int offset = i < 9 ? 27 : -9; + bedrockItems[i] = TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(translator.size + i + offset)); + } + InventoryContentPacket contentPacket = new InventoryContentPacket(); + contentPacket.setContainerId(ContainerId.INVENTORY); + contentPacket.setContents(bedrockItems); + session.getUpstream().sendPacket(contentPacket); + } + + public boolean updateSlot(InventoryTranslator translator, GeyserSession session, Inventory inventory, int javaSlot) { + if (javaSlot >= translator.size) { + InventorySlotPacket slotPacket = new InventorySlotPacket(); + slotPacket.setContainerId(ContainerId.INVENTORY); + slotPacket.setInventorySlot(translator.javaSlotToBedrock(javaSlot)); + slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(javaSlot))); + session.getUpstream().sendPacket(slotPacket); + return true; + } + return false; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/Enchantment.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/Enchantment.java index 596ef215..c5c152a2 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/Enchantment.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/Enchantment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java index ed61e491..aaf00169 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java @@ -74,9 +74,8 @@ public class ItemTranslator { } public ItemData translateToBedrock(ItemStack stack) { - // Most likely dirt if null if (stack == null) { - return ItemData.of(3, (short)0, 0); + return ItemData.AIR; } ItemEntry bedrockItem = getItem(stack); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/Potion.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/Potion.java index ca5cd5c0..f711d3ea 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/Potion.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/Potion.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java index 9015fc28..9399d1dd 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -49,8 +49,10 @@ import java.util.*; import java.util.stream.Collectors; public class JavaDeclareRecipesTranslator extends PacketTranslator { - - private final int[] brewingIngredients = new int[]{372, 331, 348, 376, 289, 437, 353, 414, 382, 375, 462, 378, 396, 377, 370, 469, 470}; + private static final Collection POTION_MIXES = + Arrays.stream(new int[]{372, 331, 348, 376, 289, 437, 353, 414, 382, 375, 462, 378, 396, 377, 370, 469, 470}) + .mapToObj(ingredient -> new PotionMixData(0, ingredient, 0)) + .collect(Collectors.toList()); @Override public void translate(ServerDeclareRecipesPacket packet, GeyserSession session) { @@ -61,6 +63,7 @@ public class JavaDeclareRecipesTranslator extends PacketTranslator, IntSet> squashedOptions = new HashMap<>(); for (int i = 0; i < ingredients.length; i++) { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerChangeHeldItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerChangeHeldItemTranslator.java new file mode 100644 index 00000000..90042e32 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerChangeHeldItemTranslator.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.java.entity.player; + +import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerChangeHeldItemPacket; +import com.nukkitx.protocol.bedrock.packet.PlayerHotbarPacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; + +public class JavaPlayerChangeHeldItemTranslator extends PacketTranslator { + + @Override + public void translate(ServerPlayerChangeHeldItemPacket packet, GeyserSession session) { + PlayerHotbarPacket hotbarPacket = new PlayerHotbarPacket(); + hotbarPacket.setContainerId(0); + hotbarPacket.setSelectedHotbarSlot(packet.getSlot()); + hotbarPacket.setSelectHotbarSlot(true); + session.getUpstream().sendPacket(hotbarPacket); + + session.getInventory().setHeldItemSlot(packet.getSlot()); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaCloseWindowTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaCloseWindowTranslator.java index dcb0c9fe..cb532e60 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaCloseWindowTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaCloseWindowTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaConfirmTransactionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaConfirmTransactionTranslator.java index 09718dbd..10c85de4 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaConfirmTransactionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaConfirmTransactionTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaOpenWindowTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaOpenWindowTranslator.java index 43f3b6d1..4190ac5a 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaOpenWindowTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaOpenWindowTranslator.java @@ -80,7 +80,7 @@ public class JavaOpenWindowTranslator extends PacketTranslator InventoryUtils.openInventory(session, newInventory), 350, TimeUnit.MILLISECONDS); + Geyser.getGeneralThreadPool().schedule(() -> InventoryUtils.openInventory(session, newInventory), 500, TimeUnit.MILLISECONDS); return; } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java index 9443f86b..21c7217a 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java @@ -31,6 +31,7 @@ import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.TranslatorsInit; import org.geysermc.connector.network.translators.inventory.InventoryTranslator; +import org.geysermc.connector.utils.InventoryUtils; import java.util.Objects; @@ -43,8 +44,9 @@ public class JavaSetSlotTranslator extends PacketTranslator return; if (session.getCraftSlot() != 0) return; - //bedrock client is bugged when changing the cursor. do not send slot update packet + session.getInventory().setCursor(packet.getItem()); + InventoryUtils.updateCursor(session); return; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaWindowPropertyTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaWindowPropertyTranslator.java index c8e04d37..d7e2292e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaWindowPropertyTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaWindowPropertyTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java b/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java index 60779f52..f55f28bb 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java @@ -25,6 +25,11 @@ package org.geysermc.connector.utils; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.nukkitx.protocol.bedrock.data.ContainerId; +import com.nukkitx.protocol.bedrock.data.ItemData; +import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import org.geysermc.api.Geyser; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; @@ -32,9 +37,11 @@ import org.geysermc.connector.network.translators.TranslatorsInit; import org.geysermc.connector.network.translators.inventory.DoubleChestInventoryTranslator; import org.geysermc.connector.network.translators.inventory.InventoryTranslator; +import java.util.Objects; import java.util.concurrent.TimeUnit; public class InventoryUtils { + public static final ItemStack REFRESH_ITEM = new ItemStack(1, 127, new CompoundTag("")); //TODO: stop using this public static void openInventory(GeyserSession session, Inventory inventory) { InventoryTranslator translator = TranslatorsInit.getInventoryTranslators().get(inventory.getWindowType()); @@ -71,4 +78,31 @@ public class InventoryUtils { session.setCraftSlot(0); session.getInventory().setCursor(null); } + + public static void updateCursor(GeyserSession session) { + InventorySlotPacket cursorPacket = new InventorySlotPacket(); + cursorPacket.setContainerId(ContainerId.CURSOR); + cursorPacket.setInventorySlot(0); + cursorPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(session.getInventory().getCursor())); + session.getUpstream().sendPacket(cursorPacket); + } + + //NPE if compound tag is null + public static ItemStack fixStack(ItemStack stack) { + if (stack == null || stack.getId() == 0) + return null; + return new ItemStack(stack.getId(), stack.getAmount(), stack.getNbt() == null ? new CompoundTag("") : stack.getNbt()); + } + + public static boolean canStack(ItemStack item1, ItemStack item2) { + if (item1 == null || item2 == null) + return false; + return item1.getId() == item2.getId() && Objects.equals(item1.getNbt(), item2.getNbt()); + } + + public static boolean canStack(ItemData item1, ItemData item2) { + if (item1 == null || item2 == null) + return false; + return item1.equals(item2, false, true, true); + } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java index cc2f03b5..00bc86c2 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java +++ b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java @@ -25,6 +25,7 @@ package org.geysermc.connector.utils; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.nukkitx.nbt.NbtUtils; import com.nukkitx.nbt.stream.NBTInputStream; @@ -150,31 +151,31 @@ public class Toolbox { InputStream creativeItemStream = Toolbox.class.getClassLoader().getResourceAsStream("bedrock/creative_items.json"); ObjectMapper creativeItemMapper = new ObjectMapper(); - List> creativeItemEntries = new ArrayList<>(); + JsonNode creativeItemEntries; try { - creativeItemEntries = (ArrayList>) creativeItemMapper.readValue(creativeItemStream, HashMap.class).get("items"); + creativeItemEntries = creativeItemMapper.readTree(creativeItemStream).get("items"); } catch (Exception e) { - e.printStackTrace(); + throw new AssertionError("Unable to load creative items", e); } List creativeItems = new ArrayList<>(); - for (Map map : creativeItemEntries) { + for (JsonNode itemNode : creativeItemEntries) { short damage = 0; - if (map.containsKey("damage")) { - damage = (short)(int) map.get("damage"); + if (itemNode.has("damage")) { + damage = itemNode.get("damage").numberValue().shortValue(); } - if (map.containsKey("nbt_b64")) { - byte[] bytes = Base64.getDecoder().decode((String) map.get("nbt_b64")); + if (itemNode.has("nbt_b64")) { + byte[] bytes = Base64.getDecoder().decode(itemNode.get("nbt_b64").asText()); ByteArrayInputStream bais = new ByteArrayInputStream(bytes); try { com.nukkitx.nbt.tag.CompoundTag tag = (com.nukkitx.nbt.tag.CompoundTag) NbtUtils.createReaderLE(bais).readTag(); - creativeItems.add(ItemData.of((int) map.get("id"), damage, 1, tag)); + creativeItems.add(ItemData.of(itemNode.get("id").asInt(), damage, 1, tag)); } catch (IOException e) { e.printStackTrace(); } } else { - creativeItems.add(ItemData.of((int) map.get("id"), damage, 1)); + creativeItems.add(ItemData.of(itemNode.get("id").asInt(), damage, 1)); } } From 3d61b3ce280cf1ee3e207d2eeb5c05638bef2440 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Thu, 30 Jan 2020 23:15:18 -0900 Subject: [PATCH 038/109] Bump OpenNBT lib to 1.4-SNAPSHOT This fixes the NPE when sending an ItemStack with a null NBT tag. This also fixes some item movement bugs on pure vanilla servers. --- connector/pom.xml | 2 +- .../translators/inventory/PlayerInventoryTranslator.java | 4 ++-- .../network/translators/inventory/action/ClickPlan.java | 2 +- .../java/org/geysermc/connector/utils/InventoryUtils.java | 7 ------- 4 files changed, 4 insertions(+), 11 deletions(-) diff --git a/connector/pom.xml b/connector/pom.xml index 9de1e3e7..c6131159 100644 --- a/connector/pom.xml +++ b/connector/pom.xml @@ -79,7 +79,7 @@ com.github.steveice10 opennbt - 1.3-SNAPSHOT + 1.4-SNAPSHOT compile diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java index acad709f..31d898c2 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java @@ -182,7 +182,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { } else { javaItem = TranslatorsInit.getItemTranslator().translateToJava(action.getToItem()); } - ClientCreativeInventoryActionPacket creativePacket = new ClientCreativeInventoryActionPacket(javaSlot, InventoryUtils.fixStack(javaItem)); + ClientCreativeInventoryActionPacket creativePacket = new ClientCreativeInventoryActionPacket(javaSlot, javaItem); session.getDownstream().getSession().send(creativePacket); inventory.setItem(javaSlot, javaItem); break; @@ -195,7 +195,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { if (action.getSource().getType() == InventorySource.Type.WORLD_INTERACTION && action.getSource().getFlag() == InventorySource.Flag.DROP_ITEM) { javaItem = TranslatorsInit.getItemTranslator().translateToJava(action.getToItem()); - ClientCreativeInventoryActionPacket creativeDropPacket = new ClientCreativeInventoryActionPacket(-1, InventoryUtils.fixStack(javaItem)); + ClientCreativeInventoryActionPacket creativeDropPacket = new ClientCreativeInventoryActionPacket(-1, javaItem); session.getDownstream().getSession().send(creativeDropPacket); } break; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/ClickPlan.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/ClickPlan.java index 3abdd284..cdc42f96 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/ClickPlan.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/ClickPlan.java @@ -61,7 +61,7 @@ class ClickPlan { refresh = true; ClientWindowActionPacket clickPacket = new ClientWindowActionPacket(inventory.getId(), - actionId, action.slot, !planIter.hasNext() && refresh ? InventoryUtils.REFRESH_ITEM : InventoryUtils.fixStack(clickedItem), + actionId, action.slot, !planIter.hasNext() && refresh ? InventoryUtils.REFRESH_ITEM : clickedItem, WindowAction.CLICK_ITEM, action.click.actionParam); if (translator.getSlotType(action.slot) == SlotType.OUTPUT) { diff --git a/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java b/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java index f55f28bb..0fb9e0fc 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java @@ -87,13 +87,6 @@ public class InventoryUtils { session.getUpstream().sendPacket(cursorPacket); } - //NPE if compound tag is null - public static ItemStack fixStack(ItemStack stack) { - if (stack == null || stack.getId() == 0) - return null; - return new ItemStack(stack.getId(), stack.getAmount(), stack.getNbt() == null ? new CompoundTag("") : stack.getNbt()); - } - public static boolean canStack(ItemStack item1, ItemStack item2) { if (item1 == null || item2 == null) return false; From bf1835e69101d1e49587f0ebb7ef6c65164fe688 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Wed, 12 Feb 2020 22:29:44 -0900 Subject: [PATCH 039/109] Fix Block IDs Quick fix. Might have a different method for getting block IDs in the future --- .../network/translators/block/BlockTranslator.java | 12 ++++++++++-- .../inventory/BlockInventoryTranslator.java | 6 ++++-- .../inventory/DoubleChestInventoryTranslator.java | 13 +++++++------ .../inventory/holder/BlockInventoryHolder.java | 7 ++++--- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java index f4753b8d..970808b6 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java @@ -48,6 +48,7 @@ public class BlockTranslator { private static final Int2IntMap JAVA_TO_BEDROCK_BLOCK_MAP = new Int2IntOpenHashMap(); private static final Int2ObjectMap BEDROCK_TO_JAVA_BLOCK_MAP = new Int2ObjectOpenHashMap<>(); + private static final Map JAVA_ID_BLOCK_MAP = new HashMap<>(); private static final IntSet WATERLOGGED = new IntOpenHashSet(); private static final int BLOCK_STATE_VERSION = 17760256; @@ -89,18 +90,21 @@ public class BlockTranslator { javaRuntimeId++; Map.Entry entry = blocksIterator.next(); String javaId = entry.getKey(); + BlockState javaBlockState = new BlockState(javaRuntimeId); CompoundTag blockTag = buildBedrockState(entry.getValue()); + JAVA_ID_BLOCK_MAP.put(javaId, javaBlockState); + if ("minecraft:water[level=0]".equals(javaId)) { waterRuntimeId = bedrockRuntimeId; } boolean waterlogged = entry.getValue().has("waterlogged") && entry.getValue().get("waterlogged").booleanValue(); if (waterlogged) { - BEDROCK_TO_JAVA_BLOCK_MAP.putIfAbsent(bedrockRuntimeId | 1 << 31, new BlockState(javaRuntimeId)); + BEDROCK_TO_JAVA_BLOCK_MAP.putIfAbsent(bedrockRuntimeId | 1 << 31, javaBlockState); WATERLOGGED.add(javaRuntimeId); } else { - BEDROCK_TO_JAVA_BLOCK_MAP.putIfAbsent(bedrockRuntimeId, new BlockState(javaRuntimeId)); + BEDROCK_TO_JAVA_BLOCK_MAP.putIfAbsent(bedrockRuntimeId, javaBlockState); } CompoundTag runtimeTag = blockStateMap.remove(blockTag); @@ -175,6 +179,10 @@ public class BlockTranslator { return BEDROCK_TO_JAVA_BLOCK_MAP.get(bedrockId); } + public static BlockState getJavaBlockState(String javaId) { + return JAVA_ID_BLOCK_MAP.get(javaId); + } + public static boolean isWaterlogged(BlockState state) { return WATERLOGGED.contains(state.getId()); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BlockInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BlockInventoryTranslator.java index 32dfc2a6..5f6274f0 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BlockInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BlockInventoryTranslator.java @@ -25,10 +25,11 @@ package org.geysermc.connector.network.translators.inventory; +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.nukkitx.protocol.bedrock.data.ContainerType; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.block.BlockTranslator; import org.geysermc.connector.network.translators.inventory.holder.BlockInventoryHolder; import org.geysermc.connector.network.translators.inventory.holder.InventoryHolder; import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater; @@ -39,7 +40,8 @@ public class BlockInventoryTranslator extends BaseInventoryTranslator { public BlockInventoryTranslator(int size, String javaBlockIdentifier, ContainerType containerType, InventoryUpdater updater) { super(size); - final int blockId = TranslatorsInit.getBlockTranslator().getBlockEntry(javaBlockIdentifier).getBedrockRuntimeId(); + BlockState javaBlockState = BlockTranslator.getJavaBlockState(javaBlockIdentifier); + int blockId = BlockTranslator.getBedrockBlockId(javaBlockState); this.holder = new BlockInventoryHolder(blockId, containerType); this.updater = updater; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java index 07d3a414..c70a8995 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java @@ -26,6 +26,7 @@ package org.geysermc.connector.network.translators.inventory; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.nukkitx.math.vector.Vector3i; import com.nukkitx.nbt.tag.CompoundTag; import com.nukkitx.protocol.bedrock.data.ContainerType; @@ -34,8 +35,7 @@ import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.TranslatorsInit; -import org.geysermc.connector.network.translators.block.BlockEntry; +import org.geysermc.connector.network.translators.block.BlockTranslator; import org.geysermc.connector.network.translators.inventory.updater.ChestInventoryUpdater; import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater; @@ -45,7 +45,8 @@ public class DoubleChestInventoryTranslator extends BaseInventoryTranslator { public DoubleChestInventoryTranslator(int size) { super(size); - this.blockId = TranslatorsInit.getBlockTranslator().getBlockEntry("minecraft:chest[facing=north,type=single,waterlogged=false]").getBedrockRuntimeId(); + BlockState javaBlockState = BlockTranslator.getJavaBlockState("minecraft:chest[facing=north,type=single,waterlogged=false]"); + this.blockId = BlockTranslator.getBedrockBlockId(javaBlockState); this.updater = new ChestInventoryUpdater(54); } @@ -111,11 +112,11 @@ public class DoubleChestInventoryTranslator extends BaseInventoryTranslator { public void closeInventory(GeyserSession session, Inventory inventory) { Vector3i holderPos = inventory.getHolderPosition(); Position pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ()); - BlockEntry realBlock = session.getChunkCache().getBlockAt(pos); + BlockState realBlock = session.getChunkCache().getBlockAt(pos); UpdateBlockPacket blockPacket = new UpdateBlockPacket(); blockPacket.setDataLayer(0); blockPacket.setBlockPosition(holderPos); - blockPacket.setRuntimeId(realBlock.getBedrockRuntimeId()); + blockPacket.setRuntimeId(BlockTranslator.getBedrockBlockId(realBlock)); session.getUpstream().sendPacket(blockPacket); holderPos = holderPos.add(Vector3i.UNIT_X); @@ -124,7 +125,7 @@ public class DoubleChestInventoryTranslator extends BaseInventoryTranslator { blockPacket = new UpdateBlockPacket(); blockPacket.setDataLayer(0); blockPacket.setBlockPosition(holderPos); - blockPacket.setRuntimeId(realBlock.getBedrockRuntimeId()); + blockPacket.setRuntimeId(BlockTranslator.getBedrockBlockId(realBlock)); session.getUpstream().sendPacket(blockPacket); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/holder/BlockInventoryHolder.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/holder/BlockInventoryHolder.java index 6c0db853..a9b0d4ad 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/holder/BlockInventoryHolder.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/holder/BlockInventoryHolder.java @@ -26,6 +26,7 @@ package org.geysermc.connector.network.translators.inventory.holder; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.nukkitx.math.vector.Vector3i; import com.nukkitx.nbt.tag.CompoundTag; import com.nukkitx.protocol.bedrock.data.ContainerType; @@ -35,7 +36,7 @@ import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; import lombok.AllArgsConstructor; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.block.BlockEntry; +import org.geysermc.connector.network.translators.block.BlockTranslator; import org.geysermc.connector.network.translators.inventory.InventoryTranslator; @AllArgsConstructor @@ -80,11 +81,11 @@ public class BlockInventoryHolder extends InventoryHolder { public void closeInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) { Vector3i holderPos = inventory.getHolderPosition(); Position pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ()); - BlockEntry realBlock = session.getChunkCache().getBlockAt(pos); + BlockState realBlock = session.getChunkCache().getBlockAt(pos); UpdateBlockPacket blockPacket = new UpdateBlockPacket(); blockPacket.setDataLayer(0); blockPacket.setBlockPosition(holderPos); - blockPacket.setRuntimeId(realBlock.getBedrockRuntimeId()); + blockPacket.setRuntimeId(BlockTranslator.getBedrockBlockId(realBlock)); session.getUpstream().sendPacket(blockPacket); } } From bfca25bbe3534f1c58bc05465cf27d42b1002251 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Tue, 25 Feb 2020 22:31:55 -0900 Subject: [PATCH 040/109] Fix compile errors --- .../inventory/AnvilInventoryTranslator.java | 14 +++++----- .../inventory/BaseInventoryTranslator.java | 10 +++---- .../inventory/BrewingInventoryTranslator.java | 4 +-- .../CraftingInventoryTranslator.java | 10 +++---- .../inventory/InventoryTranslator.java | 6 ++--- .../inventory/PlayerInventoryTranslator.java | 26 +++++++++---------- ...ava => InventoryActionDataTranslator.java} | 20 +++++++------- .../updater/ChestInventoryUpdater.java | 4 +-- .../updater/ContainerInventoryUpdater.java | 4 +-- .../updater/CursorInventoryUpdater.java | 8 +++--- .../inventory/updater/InventoryUpdater.java | 4 +-- .../translators/item/ItemTranslator.java | 4 +-- .../connector/utils/InventoryUtils.java | 4 +-- .../connector/world/chunk/ChunkPosition.java | 17 ------------ 14 files changed, 58 insertions(+), 77 deletions(-) rename connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/{InventoryActionTranslator.java => InventoryActionDataTranslator.java} (97%) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java index 39575188..60700ba2 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java @@ -28,7 +28,7 @@ package org.geysermc.connector.network.translators.inventory; import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientRenameItemPacket; import com.nukkitx.protocol.bedrock.data.ContainerId; import com.nukkitx.protocol.bedrock.data.ContainerType; -import com.nukkitx.protocol.bedrock.data.InventoryAction; +import com.nukkitx.protocol.bedrock.data.InventoryActionData; import com.nukkitx.protocol.bedrock.data.ItemData; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; @@ -42,7 +42,7 @@ public class AnvilInventoryTranslator extends BlockInventoryTranslator { } @Override - public int bedrockSlotToJava(InventoryAction action) { + public int bedrockSlotToJava(InventoryActionData action) { if (action.getSource().getContainerId() == ContainerId.CURSOR) { switch (action.getSlot()) { case 1: @@ -77,10 +77,10 @@ public class AnvilInventoryTranslator extends BlockInventoryTranslator { } @Override - public void translateActions(GeyserSession session, Inventory inventory, List actions) { - InventoryAction anvilResult = null; - InventoryAction anvilInput = null; - for (InventoryAction action : actions) { + public void translateActions(GeyserSession session, Inventory inventory, List actions) { + InventoryActionData anvilResult = null; + InventoryActionData anvilInput = null; + for (InventoryActionData action : actions) { if (action.getSource().getContainerId() == ContainerId.ANVIL_MATERIAL) { //useless packet return; @@ -100,7 +100,7 @@ public class AnvilInventoryTranslator extends BlockInventoryTranslator { String rename; com.nukkitx.nbt.tag.CompoundTag tag = itemName.getTag(); if (tag != null) { - rename = tag.getAsCompound("display").getAsString("Name"); + rename = tag.getCompound("display").getString("Name"); } else { rename = ""; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BaseInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BaseInventoryTranslator.java index d64c0e78..5deb0370 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BaseInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BaseInventoryTranslator.java @@ -26,10 +26,10 @@ package org.geysermc.connector.network.translators.inventory; import com.nukkitx.protocol.bedrock.data.ContainerId; -import com.nukkitx.protocol.bedrock.data.InventoryAction; +import com.nukkitx.protocol.bedrock.data.InventoryActionData; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.inventory.action.InventoryActionTranslator; +import org.geysermc.connector.network.translators.inventory.action.InventoryActionDataTranslator; import java.util.List; @@ -44,7 +44,7 @@ public abstract class BaseInventoryTranslator extends InventoryTranslator{ } @Override - public int bedrockSlotToJava(InventoryAction action) { + public int bedrockSlotToJava(InventoryActionData action) { int slotnum = action.getSlot(); if (action.getSource().getContainerId() == ContainerId.INVENTORY) { //hotbar @@ -76,7 +76,7 @@ public abstract class BaseInventoryTranslator extends InventoryTranslator{ } @Override - public void translateActions(GeyserSession session, Inventory inventory, List actions) { - InventoryActionTranslator.translate(this, session, inventory, actions); + public void translateActions(GeyserSession session, Inventory inventory, List actions) { + InventoryActionDataTranslator.translate(this, session, inventory, actions); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingInventoryTranslator.java index c5f67a03..bd143698 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingInventoryTranslator.java @@ -26,7 +26,7 @@ package org.geysermc.connector.network.translators.inventory; import com.nukkitx.protocol.bedrock.data.ContainerType; -import com.nukkitx.protocol.bedrock.data.InventoryAction; +import com.nukkitx.protocol.bedrock.data.InventoryActionData; import com.nukkitx.protocol.bedrock.packet.ContainerSetDataPacket; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; @@ -66,7 +66,7 @@ public class BrewingInventoryTranslator extends BlockInventoryTranslator { } @Override - public int bedrockSlotToJava(InventoryAction action) { + public int bedrockSlotToJava(InventoryActionData action) { final int slot = super.bedrockSlotToJava(action); switch (slot) { case 0: diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingInventoryTranslator.java index fe70609f..92a1d90e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingInventoryTranslator.java @@ -28,13 +28,11 @@ package org.geysermc.connector.network.translators.inventory; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import com.nukkitx.protocol.bedrock.data.ContainerId; import com.nukkitx.protocol.bedrock.data.ContainerType; -import com.nukkitx.protocol.bedrock.data.InventoryAction; +import com.nukkitx.protocol.bedrock.data.InventoryActionData; import com.nukkitx.protocol.bedrock.data.InventorySource; import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket; -import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.TranslatorsInit; import org.geysermc.connector.network.translators.inventory.updater.CursorInventoryUpdater; import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater; import org.geysermc.connector.utils.InventoryUtils; @@ -80,7 +78,7 @@ public class CraftingInventoryTranslator extends BaseInventoryTranslator { } @Override - public int bedrockSlotToJava(InventoryAction action) { + public int bedrockSlotToJava(InventoryActionData action) { if (action.getSource().getContainerId() == ContainerId.CURSOR) { int slotnum = action.getSlot(); if (slotnum >= 32 && 42 >= slotnum) { @@ -105,9 +103,9 @@ public class CraftingInventoryTranslator extends BaseInventoryTranslator { } @Override - public void translateActions(GeyserSession session, Inventory inventory, List actions) { + public void translateActions(GeyserSession session, Inventory inventory, List actions) { if (session.getGameMode() == GameMode.CREATIVE) { - for (InventoryAction action : actions) { + for (InventoryActionData action : actions) { if (action.getSource().getType() == InventorySource.Type.CREATIVE) { updateInventory(session, inventory); InventoryUtils.updateCursor(session); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java index 7baef61a..2a5afb8c 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.connector.network.translators.inventory; -import com.nukkitx.protocol.bedrock.data.InventoryAction; +import com.nukkitx.protocol.bedrock.data.InventoryActionData; import lombok.AllArgsConstructor; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; @@ -42,8 +42,8 @@ public abstract class InventoryTranslator { public abstract void updateProperty(GeyserSession session, Inventory inventory, int key, int value); public abstract void updateInventory(GeyserSession session, Inventory inventory); public abstract void updateSlot(GeyserSession session, Inventory inventory, int slot); - public abstract int bedrockSlotToJava(InventoryAction action); + public abstract int bedrockSlotToJava(InventoryActionData action); public abstract int javaSlotToBedrock(int slot); public abstract SlotType getSlotType(int javaSlot); - public abstract void translateActions(GeyserSession session, Inventory inventory, List actions); + public abstract void translateActions(GeyserSession session, Inventory inventory, List actions); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java index 31d898c2..555e80a0 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java @@ -34,7 +34,7 @@ import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.TranslatorsInit; -import org.geysermc.connector.network.translators.inventory.action.InventoryActionTranslator; +import org.geysermc.connector.network.translators.inventory.action.InventoryActionDataTranslator; import org.geysermc.connector.utils.InventoryUtils; import java.util.List; @@ -50,8 +50,8 @@ public class PlayerInventoryTranslator extends InventoryTranslator { for (int i = 1; i < 5; i++) { InventorySlotPacket slotPacket = new InventorySlotPacket(); slotPacket.setContainerId(ContainerId.CURSOR); - slotPacket.setInventorySlot(i + 27); - slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i))); + slotPacket.setSlot(i + 27); + slotPacket.setItem(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i))); session.getUpstream().sendPacket(slotPacket); } @@ -93,18 +93,18 @@ public class PlayerInventoryTranslator extends InventoryTranslator { if (slot >= 9) { slotPacket.setContainerId(ContainerId.INVENTORY); if (slot >= 36) { - slotPacket.setInventorySlot(slot - 36); + slotPacket.setSlot(slot - 36); } else { - slotPacket.setInventorySlot(slot); + slotPacket.setSlot(slot); } } else if (slot >= 5) { slotPacket.setContainerId(ContainerId.ARMOR); - slotPacket.setInventorySlot(slot - 5); + slotPacket.setSlot(slot - 5); } else { slotPacket.setContainerId(ContainerId.CURSOR); - slotPacket.setInventorySlot(slot + 27); + slotPacket.setSlot(slot + 27); } - slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(slot))); + slotPacket.setItem(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(slot))); session.getUpstream().sendPacket(slotPacket); } else if (slot == 45) { InventoryContentPacket offhandPacket = new InventoryContentPacket(); @@ -115,7 +115,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { } @Override - public int bedrockSlotToJava(InventoryAction action) { + public int bedrockSlotToJava(InventoryActionData action) { int slotnum = action.getSlot(); switch (action.getSource().getContainerId()) { case ContainerId.INVENTORY: @@ -159,10 +159,10 @@ public class PlayerInventoryTranslator extends InventoryTranslator { } @Override - public void translateActions(GeyserSession session, Inventory inventory, List actions) { + public void translateActions(GeyserSession session, Inventory inventory, List actions) { if (session.getGameMode() == GameMode.CREATIVE) { //crafting grid is not visible in creative mode in java edition - for (InventoryAction action : actions) { + for (InventoryActionData action : actions) { if (action.getSource().getContainerId() == ContainerId.CURSOR && (action.getSlot() >= 28 && 31 >= action.getSlot())) { updateInventory(session, inventory); InventoryUtils.updateCursor(session); @@ -171,7 +171,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { } ItemStack javaItem; - for (InventoryAction action : actions) { + for (InventoryActionData action : actions) { switch (action.getSource().getContainerId()) { case ContainerId.INVENTORY: case ContainerId.ARMOR: @@ -204,7 +204,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { return; } - InventoryActionTranslator.translate(this, session, inventory, actions); + InventoryActionDataTranslator.translate(this, session, inventory, actions); } @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java similarity index 97% rename from connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionTranslator.java rename to connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java index 586c2c02..a94b6242 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java @@ -33,7 +33,7 @@ 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.window.ClientWindowActionPacket; import com.nukkitx.protocol.bedrock.data.ContainerId; -import com.nukkitx.protocol.bedrock.data.InventoryAction; +import com.nukkitx.protocol.bedrock.data.InventoryActionData; import com.nukkitx.protocol.bedrock.data.InventorySource; import com.nukkitx.protocol.bedrock.data.ItemData; import org.geysermc.connector.inventory.Inventory; @@ -45,16 +45,16 @@ import org.geysermc.connector.utils.InventoryUtils; import java.util.*; -public class InventoryActionTranslator { - public static void translate(InventoryTranslator translator, GeyserSession session, Inventory inventory, List actions) { +public class InventoryActionDataTranslator { + public static void translate(InventoryTranslator translator, GeyserSession session, Inventory inventory, List actions) { if (actions.size() != 2) return; - InventoryAction worldAction = null; - InventoryAction cursorAction = null; - InventoryAction containerAction = null; + InventoryActionData worldAction = null; + InventoryActionData cursorAction = null; + InventoryActionData containerAction = null; boolean refresh = false; - for (InventoryAction action : actions) { + for (InventoryActionData action : actions) { if (action.getSource().getContainerId() == ContainerId.CRAFTING_USE_INGREDIENT || action.getSource().getContainerId() == ContainerId.CRAFTING_RESULT) { return; } else if (action.getSource().getType() == InventorySource.Type.WORLD_INTERACTION) { @@ -78,7 +78,7 @@ public class InventoryActionTranslator { session.setCraftSlot(0); if (worldAction != null) { - InventoryAction sourceAction; + InventoryActionData sourceAction; if (cursorAction != null) { sourceAction = cursorAction; } else { @@ -208,8 +208,8 @@ public class InventoryActionTranslator { return; } else { ClickPlan plan = new ClickPlan(); - InventoryAction fromAction; - InventoryAction toAction; + InventoryActionData fromAction; + InventoryActionData toAction; if (actions.get(0).getFromItem().getCount() >= actions.get(0).getToItem().getCount()) { fromAction = actions.get(0); toAction = actions.get(1); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java index 4af1fba1..ab45cdc4 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java @@ -64,8 +64,8 @@ public class ChestInventoryUpdater extends InventoryUpdater { InventorySlotPacket slotPacket = new InventorySlotPacket(); slotPacket.setContainerId(inventory.getId()); - slotPacket.setInventorySlot(translator.javaSlotToBedrock(javaSlot)); - slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(javaSlot))); + slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); + slotPacket.setItem(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(javaSlot))); session.getUpstream().sendPacket(slotPacket); return true; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java index 7169311e..3efe1cee 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java @@ -56,8 +56,8 @@ public class ContainerInventoryUpdater extends InventoryUpdater { InventorySlotPacket slotPacket = new InventorySlotPacket(); slotPacket.setContainerId(inventory.getId()); - slotPacket.setInventorySlot(translator.javaSlotToBedrock(javaSlot)); - slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(javaSlot))); + slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); + slotPacket.setItem(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(javaSlot))); session.getUpstream().sendPacket(slotPacket); return true; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java index 3df8d766..13b8554b 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java @@ -43,8 +43,8 @@ public class CursorInventoryUpdater extends InventoryUpdater { continue; InventorySlotPacket slotPacket = new InventorySlotPacket(); slotPacket.setContainerId(ContainerId.CURSOR); - slotPacket.setInventorySlot(bedrockSlot); - slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i))); + slotPacket.setSlot(bedrockSlot); + slotPacket.setItem(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(i))); session.getUpstream().sendPacket(slotPacket); } } @@ -56,8 +56,8 @@ public class CursorInventoryUpdater extends InventoryUpdater { InventorySlotPacket slotPacket = new InventorySlotPacket(); slotPacket.setContainerId(ContainerId.CURSOR); - slotPacket.setInventorySlot(translator.javaSlotToBedrock(javaSlot)); - slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(javaSlot))); + slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); + slotPacket.setItem(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(javaSlot))); session.getUpstream().sendPacket(slotPacket); return true; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java index e5b6f4c5..888b14b1 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java @@ -51,8 +51,8 @@ public abstract class InventoryUpdater { if (javaSlot >= translator.size) { InventorySlotPacket slotPacket = new InventorySlotPacket(); slotPacket.setContainerId(ContainerId.INVENTORY); - slotPacket.setInventorySlot(translator.javaSlotToBedrock(javaSlot)); - slotPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(javaSlot))); + slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); + slotPacket.setItem(TranslatorsInit.getItemTranslator().translateToBedrock(inventory.getItem(javaSlot))); session.getUpstream().sendPacket(slotPacket); return true; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java index aaf00169..446b25db 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java @@ -189,13 +189,13 @@ public class ItemTranslator { continue; com.nukkitx.nbt.tag.CompoundTag tagValue = (com.nukkitx.nbt.tag.CompoundTag) value; - int bedrockId = tagValue.getAsShort("id", (short) -1); + int bedrockId = tagValue.getShort("id", (short) -1); Enchantment enchantment = Enchantment.getByBedrockId(bedrockId); if (enchantment != null) { CompoundTag javaTag = new CompoundTag(""); Map javaValue = javaTag.getValue(); javaValue.put("id", new StringTag("id", enchantment.getJavaIdentifier())); - javaValue.put("lvl", new IntTag("lvl", tagValue.getAsShort("lvl", (short) 1))); + javaValue.put("lvl", new IntTag("lvl", tagValue.getShort("lvl", (short) 1))); javaTag.setValue(javaValue); tags.add(javaTag); } else { diff --git a/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java b/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java index 0fb9e0fc..8eb407d0 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java @@ -82,8 +82,8 @@ public class InventoryUtils { public static void updateCursor(GeyserSession session) { InventorySlotPacket cursorPacket = new InventorySlotPacket(); cursorPacket.setContainerId(ContainerId.CURSOR); - cursorPacket.setInventorySlot(0); - cursorPacket.setSlot(TranslatorsInit.getItemTranslator().translateToBedrock(session.getInventory().getCursor())); + cursorPacket.setSlot(0); + cursorPacket.setItem(TranslatorsInit.getItemTranslator().translateToBedrock(session.getInventory().getCursor())); session.getUpstream().sendPacket(cursorPacket); } diff --git a/connector/src/main/java/org/geysermc/connector/world/chunk/ChunkPosition.java b/connector/src/main/java/org/geysermc/connector/world/chunk/ChunkPosition.java index a59b2031..26748dff 100644 --- a/connector/src/main/java/org/geysermc/connector/world/chunk/ChunkPosition.java +++ b/connector/src/main/java/org/geysermc/connector/world/chunk/ChunkPosition.java @@ -53,21 +53,4 @@ public class ChunkPosition { return new Position(chunkX, chunkY, chunkZ); } - - @Override - public boolean equals(Object obj) { - if (obj == this) - return true; - if (obj == null) - return false; - if (!(obj instanceof ChunkPosition)) - return false; - ChunkPosition other = (ChunkPosition)obj; - return x == other.x && z == other.z; - } - - @Override - public int hashCode() { - return Objects.hash(x, z); - } } From b2d611e24cbf0f7bf6e1fcb44d6025121d9e765a Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Thu, 5 Mar 2020 20:53:58 -0600 Subject: [PATCH 041/109] Fix some problems brought from merge conflicts --- .github/workflows/pullrequest.yml | 2 ++ .../geysermc/connector/network/session/GeyserSession.java | 6 +++--- .../java/org/geysermc/connector/utils/MessageUtils.java | 8 ++++---- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index a5c1dab8..ce6d7646 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -19,6 +19,8 @@ jobs: uses: actions/setup-java@v1 with: java-version: 1.8 + - name: submodules-init + uses: snickerbockers/submodules-init@v4 - name: Build with Maven run: mvn -B package - name: Archive artifacts diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index dfe4b458..acad78ea 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -165,9 +165,9 @@ public class GeyserSession implements CommandSender { ChunkUtils.sendEmptyChunks(this, playerEntity.getPosition().toInt(), 0, false); - BiomeDefinitionListPacket biomePacket = new BiomeDefinitionListPacket(); - biomePacket.setTag(CompoundTag.EMPTY); - upstream.sendPacket(biomePacket); + BiomeDefinitionListPacket biomeDefinitionListPacket = new BiomeDefinitionListPacket(); + biomeDefinitionListPacket.setTag(Toolbox.BIOMES); + upstream.sendPacket(biomeDefinitionListPacket); AvailableEntityIdentifiersPacket entityPacket = new AvailableEntityIdentifiersPacket(); entityPacket.setTag(CompoundTag.EMPTY); diff --git a/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java b/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java index 44d22265..604d4efa 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java @@ -157,14 +157,14 @@ public class MessageUtils { base += "r"; break; default: - return ""; + break; } return base; } private static String getFormat(List formats) { - String str = ""; + StringBuilder str = new StringBuilder(); for (ChatFormat cf : formats) { String base = "\u00a7"; switch (cf) { @@ -187,10 +187,10 @@ public class MessageUtils { break; } - str += base; + str.append(base); } - return str; + return str.toString(); } public static boolean isMessage(String text) { From 650a1e2ab1ed159c625d58c5cabd00b6d6b25daf Mon Sep 17 00:00:00 2001 From: William Johnstone Date: Fri, 20 Mar 2020 20:34:16 +0000 Subject: [PATCH 042/109] Start block breaking animations (inventory is broken) --- .../connector/inventory/Inventory.java | 1 + .../connector/inventory/PlayerInventory.java | 2 +- .../translators/block/BlockTranslator.java | 17 ++- .../inventory/BaseInventoryTranslator.java | 12 ++ .../network/translators/item/ItemEntry.java | 5 +- .../player/JavaPlayerActionAckTranslator.java | 143 ++++++++++++++++++ .../org/geysermc/connector/utils/Toolbox.java | 10 +- 7 files changed, 181 insertions(+), 9 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java b/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java index 24ec4a3c..859257bb 100644 --- a/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java +++ b/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java @@ -52,6 +52,7 @@ public class Inventory { @Setter protected String title; + @Getter @Setter protected ItemStack[] items; diff --git a/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java b/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java index a11ce856..52fb786b 100644 --- a/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java +++ b/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java @@ -50,6 +50,6 @@ public class PlayerInventory extends Inventory { } public ItemStack getItemInHand() { - return items[heldItemSlot]; + return items[36 + heldItemSlot]; } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java index 18ac3e6d..4b4f66db 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java @@ -32,9 +32,9 @@ import com.nukkitx.nbt.NbtUtils; import com.nukkitx.nbt.stream.NBTInputStream; import com.nukkitx.nbt.tag.CompoundTag; import com.nukkitx.nbt.tag.ListTag; -import gnu.trove.map.TObjectIntMap; -import gnu.trove.map.hash.TObjectIntHashMap; import it.unimi.dsi.fastutil.ints.*; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.utils.Toolbox; @@ -52,6 +52,8 @@ public class BlockTranslator { private static final IntSet WATERLOGGED = new IntOpenHashSet(); private static final Map JAVA_ID_TO_BLOCK_ENTITY_MAP = new HashMap<>(); + public static final Int2FloatMap JAVA_RUNTIME_ID_TO_HARDNESS = new Int2FloatOpenHashMap(); + private static final int BLOCK_STATE_VERSION = 17760256; @@ -81,7 +83,9 @@ public class BlockTranslator { } catch (Exception e) { throw new AssertionError("Unable to load Java block mappings", e); } - TObjectIntMap addedStatesMap = new TObjectIntHashMap<>(512, 0.5f, -1); + + Object2IntMap addedStatesMap = new Object2IntOpenHashMap<>(); + List paletteList = new ArrayList<>(); int waterRuntimeId = -1; @@ -94,6 +98,11 @@ public class BlockTranslator { String javaId = entry.getKey(); BlockState javaBlockState = new BlockState(javaRuntimeId); CompoundTag blockTag = buildBedrockState(entry.getValue()); + // TODO fix this, (no block should have a null hardness) + JsonNode hardnessNode = entry.getValue().get("block_hardness"); + if (hardnessNode != null) { + JAVA_RUNTIME_ID_TO_HARDNESS.put(javaRuntimeId, hardnessNode.floatValue()); + } JAVA_ID_BLOCK_MAP.put(javaId, javaBlockState); @@ -118,7 +127,7 @@ public class BlockTranslator { addedStatesMap.put(blockTag, bedrockRuntimeId); paletteList.add(runtimeTag); } else { - int duplicateRuntimeId = addedStatesMap.get(blockTag); + int duplicateRuntimeId = addedStatesMap.getOrDefault(blockTag, -1); if (duplicateRuntimeId == -1) { GeyserConnector.getInstance().getLogger().debug("Mapping " + javaId + " was not found for bedrock edition!"); } else { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BaseInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BaseInventoryTranslator.java index 5deb0370..bf4d19fc 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BaseInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BaseInventoryTranslator.java @@ -49,11 +49,17 @@ public abstract class BaseInventoryTranslator extends InventoryTranslator{ if (action.getSource().getContainerId() == ContainerId.INVENTORY) { //hotbar if (slotnum >= 9) { + // TODO REMOVE + System.out.println(slotnum); return slotnum + this.size - 9; } else { + // TODO REMOVE + System.out.println(slotnum); return slotnum + this.size + 27; } } + // TODO REMOVE + System.out.println(slotnum); return slotnum; } @@ -62,11 +68,17 @@ public abstract class BaseInventoryTranslator extends InventoryTranslator{ if (slot >= this.size) { final int tmp = slot - this.size; if (tmp < 27) { + // TODO REMOVE + System.out.println(slot); return tmp + 9; } else { + // TODO REMOVE + System.out.println(slot); return tmp - 27; } } + // TODO REMOVE + System.out.println(slot); return slot; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java index fd4f0b02..b9d515e9 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java @@ -32,7 +32,7 @@ import lombok.Getter; @AllArgsConstructor public class ItemEntry { - public static ItemEntry AIR = new ItemEntry("minecraft:air", 0, 0, 0); + public static ItemEntry AIR = new ItemEntry("minecraft:air", 0, 0, 0/*, "none", "none"*/); private String javaIdentifier; private int javaId; @@ -40,6 +40,9 @@ public class ItemEntry { private int bedrockId; private int bedrockData; + //private String toolType; + //private String toolTier; + @Override public boolean equals(Object obj) { return obj == this || (obj instanceof ItemEntry && ((ItemEntry) obj).getBedrockId() == this.getBedrockId() && ((ItemEntry) obj).getJavaIdentifier().equals(this.getJavaIdentifier())); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java index 451081a1..1f048256 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java @@ -25,10 +25,22 @@ package org.geysermc.connector.network.translators.java.entity.player; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerActionAckPacket; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.LevelEventType; +import com.nukkitx.protocol.bedrock.packet.LevelEventPacket; +import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.inventory.PlayerInventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.network.translators.block.BlockTranslator; +import org.geysermc.connector.network.translators.item.ItemEntry; import org.geysermc.connector.utils.ChunkUtils; +import org.geysermc.connector.utils.Toolbox; + +import java.util.Arrays; public class JavaPlayerActionAckTranslator extends PacketTranslator { @@ -38,6 +50,137 @@ public class JavaPlayerActionAckTranslator extends PacketTranslator l >= 1).orElse(false); + //boolean outOfWaterButNotOnGround = (!player.isInsideOfWater()) && (!player.isOnGround()); + //return breakTime0(blockHardness, correctTool, canHarvestWithHand, blockId, itemToolType, itemTier, + // efficiencyLoreLevel, hasteEffectLevel, insideOfWaterWithoutAquaAffinity, outOfWaterButNotOnGround); + return breakTime0(blockHardness/*, item.getToolTier()*/); + } + } diff --git a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java index 9601b581..4c1c2158 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java +++ b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java @@ -52,7 +52,7 @@ public class Toolbox { public static final CompoundTag BIOMES; public static final ItemData[] CREATIVE_ITEMS; - public static final Collection ITEMS = new ArrayList<>(); + public static final List ITEMS = new ArrayList<>(); public static final Int2ObjectMap ITEM_ENTRIES = new Int2ObjectOpenHashMap<>(); @@ -103,8 +103,12 @@ public class Toolbox { Iterator> iterator = items.fields(); while (iterator.hasNext()) { Map.Entry entry = iterator.next(); - ITEM_ENTRIES.put(itemIndex, new ItemEntry(entry.getKey(), itemIndex, - entry.getValue().get("bedrock_id").intValue(), entry.getValue().get("bedrock_data").intValue())); + ITEM_ENTRIES.put(itemIndex, new ItemEntry( + entry.getKey(), itemIndex, + entry.getValue().get("bedrock_id").intValue(), + entry.getValue().get("bedrock_data").intValue()/*, + entry.getValue().get("tool_type").textValue(), + entry.getValue().get("tool_tier").textValue()*/)); itemIndex++; } From 350bb28c7cb9ed1596f9dd347392bf6b59e9cf47 Mon Sep 17 00:00:00 2001 From: William Johnstone Date: Fri, 20 Mar 2020 21:28:20 +0000 Subject: [PATCH 043/109] revert last commit as I'm starting over --- .../connector/inventory/Inventory.java | 1 - .../connector/inventory/PlayerInventory.java | 2 +- .../translators/block/BlockTranslator.java | 17 +-- .../inventory/BaseInventoryTranslator.java | 12 -- .../network/translators/item/ItemEntry.java | 5 +- .../player/JavaPlayerActionAckTranslator.java | 143 ------------------ .../org/geysermc/connector/utils/Toolbox.java | 10 +- 7 files changed, 9 insertions(+), 181 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java b/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java index 859257bb..24ec4a3c 100644 --- a/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java +++ b/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java @@ -52,7 +52,6 @@ public class Inventory { @Setter protected String title; - @Getter @Setter protected ItemStack[] items; diff --git a/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java b/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java index 52fb786b..a11ce856 100644 --- a/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java +++ b/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java @@ -50,6 +50,6 @@ public class PlayerInventory extends Inventory { } public ItemStack getItemInHand() { - return items[36 + heldItemSlot]; + return items[heldItemSlot]; } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java index 4b4f66db..18ac3e6d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java @@ -32,9 +32,9 @@ import com.nukkitx.nbt.NbtUtils; import com.nukkitx.nbt.stream.NBTInputStream; import com.nukkitx.nbt.tag.CompoundTag; import com.nukkitx.nbt.tag.ListTag; +import gnu.trove.map.TObjectIntMap; +import gnu.trove.map.hash.TObjectIntHashMap; import it.unimi.dsi.fastutil.ints.*; -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.utils.Toolbox; @@ -52,8 +52,6 @@ public class BlockTranslator { private static final IntSet WATERLOGGED = new IntOpenHashSet(); private static final Map JAVA_ID_TO_BLOCK_ENTITY_MAP = new HashMap<>(); - public static final Int2FloatMap JAVA_RUNTIME_ID_TO_HARDNESS = new Int2FloatOpenHashMap(); - private static final int BLOCK_STATE_VERSION = 17760256; @@ -83,9 +81,7 @@ public class BlockTranslator { } catch (Exception e) { throw new AssertionError("Unable to load Java block mappings", e); } - - Object2IntMap addedStatesMap = new Object2IntOpenHashMap<>(); - + TObjectIntMap addedStatesMap = new TObjectIntHashMap<>(512, 0.5f, -1); List paletteList = new ArrayList<>(); int waterRuntimeId = -1; @@ -98,11 +94,6 @@ public class BlockTranslator { String javaId = entry.getKey(); BlockState javaBlockState = new BlockState(javaRuntimeId); CompoundTag blockTag = buildBedrockState(entry.getValue()); - // TODO fix this, (no block should have a null hardness) - JsonNode hardnessNode = entry.getValue().get("block_hardness"); - if (hardnessNode != null) { - JAVA_RUNTIME_ID_TO_HARDNESS.put(javaRuntimeId, hardnessNode.floatValue()); - } JAVA_ID_BLOCK_MAP.put(javaId, javaBlockState); @@ -127,7 +118,7 @@ public class BlockTranslator { addedStatesMap.put(blockTag, bedrockRuntimeId); paletteList.add(runtimeTag); } else { - int duplicateRuntimeId = addedStatesMap.getOrDefault(blockTag, -1); + int duplicateRuntimeId = addedStatesMap.get(blockTag); if (duplicateRuntimeId == -1) { GeyserConnector.getInstance().getLogger().debug("Mapping " + javaId + " was not found for bedrock edition!"); } else { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BaseInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BaseInventoryTranslator.java index bf4d19fc..5deb0370 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BaseInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BaseInventoryTranslator.java @@ -49,17 +49,11 @@ public abstract class BaseInventoryTranslator extends InventoryTranslator{ if (action.getSource().getContainerId() == ContainerId.INVENTORY) { //hotbar if (slotnum >= 9) { - // TODO REMOVE - System.out.println(slotnum); return slotnum + this.size - 9; } else { - // TODO REMOVE - System.out.println(slotnum); return slotnum + this.size + 27; } } - // TODO REMOVE - System.out.println(slotnum); return slotnum; } @@ -68,17 +62,11 @@ public abstract class BaseInventoryTranslator extends InventoryTranslator{ if (slot >= this.size) { final int tmp = slot - this.size; if (tmp < 27) { - // TODO REMOVE - System.out.println(slot); return tmp + 9; } else { - // TODO REMOVE - System.out.println(slot); return tmp - 27; } } - // TODO REMOVE - System.out.println(slot); return slot; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java index b9d515e9..fd4f0b02 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java @@ -32,7 +32,7 @@ import lombok.Getter; @AllArgsConstructor public class ItemEntry { - public static ItemEntry AIR = new ItemEntry("minecraft:air", 0, 0, 0/*, "none", "none"*/); + public static ItemEntry AIR = new ItemEntry("minecraft:air", 0, 0, 0); private String javaIdentifier; private int javaId; @@ -40,9 +40,6 @@ public class ItemEntry { private int bedrockId; private int bedrockData; - //private String toolType; - //private String toolTier; - @Override public boolean equals(Object obj) { return obj == this || (obj instanceof ItemEntry && ((ItemEntry) obj).getBedrockId() == this.getBedrockId() && ((ItemEntry) obj).getJavaIdentifier().equals(this.getJavaIdentifier())); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java index 1f048256..451081a1 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java @@ -25,22 +25,10 @@ package org.geysermc.connector.network.translators.java.entity.player; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerActionAckPacket; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.LevelEventType; -import com.nukkitx.protocol.bedrock.packet.LevelEventPacket; -import org.geysermc.connector.inventory.Inventory; -import org.geysermc.connector.inventory.PlayerInventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; -import org.geysermc.connector.network.translators.block.BlockTranslator; -import org.geysermc.connector.network.translators.item.ItemEntry; import org.geysermc.connector.utils.ChunkUtils; -import org.geysermc.connector.utils.Toolbox; - -import java.util.Arrays; public class JavaPlayerActionAckTranslator extends PacketTranslator { @@ -50,137 +38,6 @@ public class JavaPlayerActionAckTranslator extends PacketTranslator l >= 1).orElse(false); - //boolean outOfWaterButNotOnGround = (!player.isInsideOfWater()) && (!player.isOnGround()); - //return breakTime0(blockHardness, correctTool, canHarvestWithHand, blockId, itemToolType, itemTier, - // efficiencyLoreLevel, hasteEffectLevel, insideOfWaterWithoutAquaAffinity, outOfWaterButNotOnGround); - return breakTime0(blockHardness/*, item.getToolTier()*/); - } - } diff --git a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java index 4c1c2158..9601b581 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java +++ b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java @@ -52,7 +52,7 @@ public class Toolbox { public static final CompoundTag BIOMES; public static final ItemData[] CREATIVE_ITEMS; - public static final List ITEMS = new ArrayList<>(); + public static final Collection ITEMS = new ArrayList<>(); public static final Int2ObjectMap ITEM_ENTRIES = new Int2ObjectOpenHashMap<>(); @@ -103,12 +103,8 @@ public class Toolbox { Iterator> iterator = items.fields(); while (iterator.hasNext()) { Map.Entry entry = iterator.next(); - ITEM_ENTRIES.put(itemIndex, new ItemEntry( - entry.getKey(), itemIndex, - entry.getValue().get("bedrock_id").intValue(), - entry.getValue().get("bedrock_data").intValue()/*, - entry.getValue().get("tool_type").textValue(), - entry.getValue().get("tool_tier").textValue()*/)); + ITEM_ENTRIES.put(itemIndex, new ItemEntry(entry.getKey(), itemIndex, + entry.getValue().get("bedrock_id").intValue(), entry.getValue().get("bedrock_data").intValue())); itemIndex++; } From 09cdcbdf94e871f052b4998e578c3546d7ea3acc Mon Sep 17 00:00:00 2001 From: William Johnstone Date: Sat, 21 Mar 2020 20:14:09 +0000 Subject: [PATCH 044/109] Add block breaking animations that actually work (still incomplete, doesn't take enchantments or player effects into account, also doesn't account for being in the air or underwater) --- connector/pom.xml | 12 ++ .../connector/inventory/PlayerInventory.java | 2 +- .../translators/block/BlockTranslator.java | 35 +++++ .../network/translators/item/ItemEntry.java | 5 +- .../player/JavaPlayerActionAckTranslator.java | 144 ++++++++++++++++++ .../org/geysermc/connector/utils/Toolbox.java | 8 +- 6 files changed, 202 insertions(+), 4 deletions(-) diff --git a/connector/pom.xml b/connector/pom.xml index 6d56fbca..a5cf6f29 100644 --- a/connector/pom.xml +++ b/connector/pom.xml @@ -48,6 +48,18 @@ 8.1.1 compile + + com.nukkitx.fastutil + fastutil-int-double-maps + 8.3.1 + compile + + + com.nukkitx.fastutil + fastutil-int-boolean-maps + 8.3.1 + compile + com.github.steveice10 opennbt diff --git a/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java b/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java index a11ce856..52fb786b 100644 --- a/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java +++ b/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java @@ -50,6 +50,6 @@ public class PlayerInventory extends Inventory { } public ItemStack getItemInHand() { - return items[heldItemSlot]; + return items[36 + heldItemSlot]; } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java index 18ac3e6d..33098761 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java @@ -52,6 +52,13 @@ public class BlockTranslator { private static final IntSet WATERLOGGED = new IntOpenHashSet(); private static final Map JAVA_ID_TO_BLOCK_ENTITY_MAP = new HashMap<>(); + public static final Int2DoubleMap JAVA_RUNTIME_ID_TO_HARDNESS = new Int2DoubleOpenHashMap(); + public static final Int2BooleanMap JAVA_RUNTIME_ID_TO_CAN_BREAK_WITH_HAND = new Int2BooleanOpenHashMap(); + public static final Int2ObjectMap JAVA_RUNTIME_ID_TO_TOOL_TYPE = new Int2ObjectOpenHashMap<>(); + + // For block breaking animation math + public static final List JAVA_RUNTIME_WOOL_IDS = new ArrayList<>(); + public static final int JAVA_RUNTIME_COBWEB_ID; private static final int BLOCK_STATE_VERSION = 17760256; @@ -87,6 +94,7 @@ public class BlockTranslator { int waterRuntimeId = -1; int javaRuntimeId = -1; int bedrockRuntimeId = 0; + int cobwebRuntimeId = -1; Iterator> blocksIterator = blocks.fields(); while (blocksIterator.hasNext()) { javaRuntimeId++; @@ -95,6 +103,28 @@ public class BlockTranslator { BlockState javaBlockState = new BlockState(javaRuntimeId); CompoundTag blockTag = buildBedrockState(entry.getValue()); + // TODO fix this, (no block should have a null hardness) + JsonNode hardnessNode = entry.getValue().get("block_hardness"); + if (hardnessNode != null) { + JAVA_RUNTIME_ID_TO_HARDNESS.put(javaRuntimeId, hardnessNode.doubleValue()); + } + + JAVA_RUNTIME_ID_TO_CAN_BREAK_WITH_HAND.put(javaRuntimeId, entry.getValue().get("can_break_with_hand").booleanValue()); + + JsonNode toolTypeNode = entry.getValue().get("tool_type"); + if (toolTypeNode != null) { + JAVA_RUNTIME_ID_TO_TOOL_TYPE.put(javaRuntimeId, toolTypeNode.textValue()); + } + + if (javaId.contains("wool")) { + JAVA_RUNTIME_WOOL_IDS.add(javaRuntimeId); + } + + + if (javaId.contains("cobweb")) { + cobwebRuntimeId = javaRuntimeId; + } + JAVA_ID_BLOCK_MAP.put(javaId, javaBlockState); if (javaId.contains("sign[")) { @@ -131,6 +161,11 @@ public class BlockTranslator { bedrockRuntimeId++; } + if (cobwebRuntimeId == -1) { + throw new AssertionError("Unable to find cobwebs in palette"); + } + JAVA_RUNTIME_COBWEB_ID = cobwebRuntimeId; + if (waterRuntimeId == -1) { throw new AssertionError("Unable to find water in palette"); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java index fd4f0b02..b5a9eb42 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java @@ -32,7 +32,7 @@ import lombok.Getter; @AllArgsConstructor public class ItemEntry { - public static ItemEntry AIR = new ItemEntry("minecraft:air", 0, 0, 0); + public static ItemEntry AIR = new ItemEntry("minecraft:air", 0, 0, 0, "none", "none"); private String javaIdentifier; private int javaId; @@ -40,6 +40,9 @@ public class ItemEntry { private int bedrockId; private int bedrockData; + private String toolType; + private String toolTier; + @Override public boolean equals(Object obj) { return obj == this || (obj instanceof ItemEntry && ((ItemEntry) obj).getBedrockId() == this.getBedrockId() && ((ItemEntry) obj).getJavaIdentifier().equals(this.getJavaIdentifier())); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java index 451081a1..34b1646a 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java @@ -25,9 +25,17 @@ package org.geysermc.connector.network.translators.java.entity.player; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerActionAckPacket; +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.LevelEventType; +import com.nukkitx.protocol.bedrock.packet.LevelEventPacket; +import org.geysermc.connector.inventory.PlayerInventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.network.translators.TranslatorsInit; +import org.geysermc.connector.network.translators.block.BlockTranslator; +import org.geysermc.connector.network.translators.item.ItemEntry; import org.geysermc.connector.utils.ChunkUtils; public class JavaPlayerActionAckTranslator extends PacketTranslator { @@ -38,6 +46,142 @@ public class JavaPlayerActionAckTranslator extends PacketTranslator Date: Sat, 21 Mar 2020 21:37:55 +0000 Subject: [PATCH 045/109] Refactor code and improve sword breaking --- .../translators/block/BlockTranslator.java | 5 +-- .../network/translators/item/ItemEntry.java | 13 +++--- .../translators/item/ToolItemEntry.java | 15 +++++++ .../player/JavaPlayerActionAckTranslator.java | 43 +++++++++++-------- .../org/geysermc/connector/utils/Toolbox.java | 29 ++++++++++--- 5 files changed, 69 insertions(+), 36 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/item/ToolItemEntry.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java index 33098761..5132e90d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java @@ -53,7 +53,7 @@ public class BlockTranslator { private static final Map JAVA_ID_TO_BLOCK_ENTITY_MAP = new HashMap<>(); public static final Int2DoubleMap JAVA_RUNTIME_ID_TO_HARDNESS = new Int2DoubleOpenHashMap(); - public static final Int2BooleanMap JAVA_RUNTIME_ID_TO_CAN_BREAK_WITH_HAND = new Int2BooleanOpenHashMap(); + public static final Int2BooleanMap JAVA_RUNTIME_ID_TO_CAN_HARVEST_WITH_HAND = new Int2BooleanOpenHashMap(); public static final Int2ObjectMap JAVA_RUNTIME_ID_TO_TOOL_TYPE = new Int2ObjectOpenHashMap<>(); // For block breaking animation math @@ -109,7 +109,7 @@ public class BlockTranslator { JAVA_RUNTIME_ID_TO_HARDNESS.put(javaRuntimeId, hardnessNode.doubleValue()); } - JAVA_RUNTIME_ID_TO_CAN_BREAK_WITH_HAND.put(javaRuntimeId, entry.getValue().get("can_break_with_hand").booleanValue()); + JAVA_RUNTIME_ID_TO_CAN_HARVEST_WITH_HAND.put(javaRuntimeId, entry.getValue().get("can_break_with_hand").booleanValue()); JsonNode toolTypeNode = entry.getValue().get("tool_type"); if (toolTypeNode != null) { @@ -120,7 +120,6 @@ public class BlockTranslator { JAVA_RUNTIME_WOOL_IDS.add(javaRuntimeId); } - if (javaId.contains("cobweb")) { cobwebRuntimeId = javaRuntimeId; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java index b5a9eb42..e579c20e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java @@ -32,16 +32,13 @@ import lombok.Getter; @AllArgsConstructor public class ItemEntry { - public static ItemEntry AIR = new ItemEntry("minecraft:air", 0, 0, 0, "none", "none"); + public static ItemEntry AIR = new ItemEntry("minecraft:air", 0, 0, 0); - private String javaIdentifier; - private int javaId; + private final String javaIdentifier; + private final int javaId; - private int bedrockId; - private int bedrockData; - - private String toolType; - private String toolTier; + private final int bedrockId; + private final int bedrockData; @Override public boolean equals(Object obj) { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ToolItemEntry.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ToolItemEntry.java new file mode 100644 index 00000000..5d1ddd26 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ToolItemEntry.java @@ -0,0 +1,15 @@ +package org.geysermc.connector.network.translators.item; + +import lombok.Getter; + +@Getter +public class ToolItemEntry extends ItemEntry { + private final String toolType; + private final String toolTier; + + public ToolItemEntry(String javaIdentifier, int javaId, int bedrockId, int bedrockData, String toolType, String toolTier) { + super(javaIdentifier, javaId, bedrockId, bedrockData); + this.toolType = toolType; + this.toolTier = toolTier; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java index 34b1646a..2e28584e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java @@ -36,6 +36,7 @@ import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.TranslatorsInit; import org.geysermc.connector.network.translators.block.BlockTranslator; import org.geysermc.connector.network.translators.item.ItemEntry; +import org.geysermc.connector.network.translators.item.ToolItemEntry; import org.geysermc.connector.utils.ChunkUtils; public class JavaPlayerActionAckTranslator extends PacketTranslator { @@ -59,6 +60,8 @@ public class JavaPlayerActionAckTranslator extends PacketTranslator Date: Sat, 21 Mar 2020 22:59:16 +0000 Subject: [PATCH 046/109] Fix issue with players being able to update their own gamemode --- .../org/geysermc/connector/network/session/GeyserSession.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index acad78ea..57543952 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -395,7 +395,7 @@ public class GeyserSession implements CommandSender { startGamePacket.setBonusChestEnabled(false); startGamePacket.setStartingWithMap(false); startGamePacket.setTrustingPlayers(true); - startGamePacket.setDefaultPlayerPermission(PlayerPermission.OPERATOR); + startGamePacket.setDefaultPlayerPermission(PlayerPermission.MEMBER); startGamePacket.setServerChunkTickRange(4); startGamePacket.setBehaviorPackLocked(false); startGamePacket.setResourcePackLocked(false); From 60662ae06c37813eaec054c36653f22eb8ec95b2 Mon Sep 17 00:00:00 2001 From: William Johnstone Date: Sun, 22 Mar 2020 22:59:34 +0000 Subject: [PATCH 047/109] Moved break time checks to BlockUtils class, Created ItemUtils and added helper function to get enchantment levels on items, implemented a entity effect cache, added haste and mining fatigue check for block breaking animations, fixed block breaking animations for blocks with speeds that are not affected by tools. --- connector/pom.xml | 6 + .../connector/entity/PlayerEntity.java | 3 + .../network/session/GeyserSession.java | 2 +- .../session/cache/EntityEffectCache.java | 54 +++++++ .../entity/JavaEntityEffectTranslator.java | 2 + .../JavaEntityRemoveEffectTranslator.java | 2 + .../player/JavaPlayerActionAckTranslator.java | 109 +-------------- .../geysermc/connector/utils/BlockUtils.java | 132 ++++++++++++++++++ .../geysermc/connector/utils/ItemUtils.java | 47 +++++++ 9 files changed, 253 insertions(+), 104 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/session/cache/EntityEffectCache.java create mode 100644 connector/src/main/java/org/geysermc/connector/utils/BlockUtils.java create mode 100644 connector/src/main/java/org/geysermc/connector/utils/ItemUtils.java diff --git a/connector/pom.xml b/connector/pom.xml index a5cf6f29..112e104b 100644 --- a/connector/pom.xml +++ b/connector/pom.xml @@ -60,6 +60,12 @@ 8.3.1 compile + + com.nukkitx.fastutil + fastutil-object-int-maps + 8.3.1 + compile + com.github.steveice10 opennbt diff --git a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java index 56d59ec3..c7a0f96c 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java @@ -39,6 +39,7 @@ import lombok.Setter; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.session.cache.EntityEffectCache; import org.geysermc.connector.utils.SkinUtils; import java.util.UUID; @@ -50,6 +51,7 @@ public class PlayerEntity extends LivingEntity { private String username; private long lastSkinUpdate = -1; private boolean playerList = true; + private final EntityEffectCache effectCache; public PlayerEntity(GameProfile gameProfile, long entityId, long geyserId, Vector3f position, Vector3f motion, Vector3f rotation) { super(entityId, geyserId, EntityType.PLAYER, position, motion, rotation); @@ -57,6 +59,7 @@ public class PlayerEntity extends LivingEntity { profile = gameProfile; uuid = gameProfile.getId(); username = gameProfile.getName(); + effectCache = new EntityEffectCache(); if (geyserId == 1) valid = true; } diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index acad78ea..57543952 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -395,7 +395,7 @@ public class GeyserSession implements CommandSender { startGamePacket.setBonusChestEnabled(false); startGamePacket.setStartingWithMap(false); startGamePacket.setTrustingPlayers(true); - startGamePacket.setDefaultPlayerPermission(PlayerPermission.OPERATOR); + startGamePacket.setDefaultPlayerPermission(PlayerPermission.MEMBER); startGamePacket.setServerChunkTickRange(4); startGamePacket.setBehaviorPackLocked(false); startGamePacket.setResourcePackLocked(false); diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/EntityEffectCache.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/EntityEffectCache.java new file mode 100644 index 00000000..a16ef690 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/EntityEffectCache.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.session.cache; + +import com.github.steveice10.mc.protocol.data.game.entity.Effect; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import lombok.Getter; + +public class EntityEffectCache { + + @Getter + private final Object2IntMap entityEffects = new Object2IntOpenHashMap<>(); + + public void addEffect(Effect effect, int effectAmplifier) { + if (effect != null) { + entityEffects.putIfAbsent(effect, effectAmplifier + 1); + } + } + + public void removeEffect(Effect effect) { + if (entityEffects.containsKey(effect)) { + int effectLevel = entityEffects.getInt(effect); + entityEffects.remove(effect, effectLevel); + } + } + + public int getEffectLevel(Effect effect) { + return entityEffects.getOrDefault(effect, 0); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityEffectTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityEffectTranslator.java index 9716d959..590afbd0 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityEffectTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityEffectTranslator.java @@ -28,6 +28,7 @@ package org.geysermc.connector.network.translators.java.entity; import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityEffectPacket; import com.nukkitx.protocol.bedrock.packet.MobEffectPacket; import org.geysermc.connector.entity.Entity; +import org.geysermc.connector.entity.PlayerEntity; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.utils.EntityUtils; @@ -39,6 +40,7 @@ public class JavaEntityEffectTranslator extends PacketTranslator { @@ -57,16 +58,16 @@ public class JavaPlayerActionAckTranslator extends PacketTranslator l >= 1).orElse(false); + //boolean outOfWaterButNotOnGround = (!player.isInsideOfWater()) && (!player.isOnGround()); + return calculateBreakTime(blockHardness, toolTier, canHarvestWithHand, correctTool, toolType, isWoolBlock, isCobweb, toolEfficiencyLevel, hasteLevel, miningFatigueLevel); + } + +} diff --git a/connector/src/main/java/org/geysermc/connector/utils/ItemUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ItemUtils.java new file mode 100644 index 00000000..bb3cf0ed --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/utils/ItemUtils.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.utils; + +import com.github.steveice10.opennbt.tag.builtin.*; + +public class ItemUtils { + + public static int getEnchantmentLevel(CompoundTag itemNBTData, String enchantmentId) { + ListTag enchantments = (itemNBTData == null ? null : itemNBTData.get("Enchantments")); + if (enchantments != null) { + int enchantmentLevel = 0; + for (Tag tag : enchantments) { + CompoundTag enchantment = (CompoundTag) tag; + StringTag enchantId = enchantment.get("id"); + if (enchantId.getValue().equals(enchantmentId)) { + enchantmentLevel = (int) ((ShortTag) enchantment.get("lvl")).getValue(); + } + } + return enchantmentLevel; + } + return 0; + } +} From 5301c8c3f670a7a2132077a70582f96ee1ad36b5 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Wed, 25 Mar 2020 22:03:46 -0400 Subject: [PATCH 048/109] Implement bed colors Java Edition includes the bed color in the namespaced ID; in Bedrock edition it's one of the tag values as a block entity. This code involves creating a table between block states and bed color numbers and looking that up on chunk load or block update. --- .../translators/block/BlockTranslator.java | 52 +++++++++++++++++++ .../java/world/JavaChunkDataTranslator.java | 9 ++++ .../geysermc/connector/utils/ChunkUtils.java | 34 ++++++++++++ 3 files changed, 95 insertions(+) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java index 18ac3e6d..f0c47410 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java @@ -50,6 +50,7 @@ public class BlockTranslator { private static final Int2ObjectMap BEDROCK_TO_JAVA_BLOCK_MAP = new Int2ObjectOpenHashMap<>(); private static final Map JAVA_ID_BLOCK_MAP = new HashMap<>(); private static final IntSet WATERLOGGED = new IntOpenHashSet(); + private static final Map BEDCOLORS = new HashMap<>(); private static final Map JAVA_ID_TO_BLOCK_ENTITY_MAP = new HashMap<>(); @@ -101,6 +102,50 @@ public class BlockTranslator { JAVA_ID_TO_BLOCK_ENTITY_MAP.put(javaBlockState, javaId); } + // If the Java ID is bed, signal that it needs a tag to show color + // The color is in the namespace ID in Java Edition but it's a tag in Bedrock. + byte bedcolor = -1; + if (javaId.contains("_bed[")) { + if (javaId.contains("minecraft:white")) { + bedcolor = 0; + } else if (javaId.contains("minecraft:orange")) { + bedcolor = 1; + } else if (javaId.contains("minecraft:magenta")) { + bedcolor = 2; + } else if (javaId.contains("minecraft:light_blue")) { + bedcolor = 3; + } else if (javaId.contains("minecraft:yellow")) { + bedcolor = 4; + } else if (javaId.contains("minecraft:lime")) { + bedcolor = 5; + } else if (javaId.contains("minecraft:pink")) { + bedcolor = 6; + } else if (javaId.contains("minecraft:gray")) { + bedcolor = 7; + } else if (javaId.contains("minecraft:light_gray")) { + bedcolor = 8; + } else if (javaId.contains("minecraft:cyan")) { + bedcolor = 9; + } else if (javaId.contains("minecraft:purple")) { + bedcolor = 10; + } else if (javaId.contains("minecraft:blue")) { + bedcolor = 11; + } else if (javaId.contains("minecraft:brown")) { + bedcolor = 12; + } else if (javaId.contains("minecraft:green")) { + bedcolor = 13; + } else if (javaId.contains("minecraft:red")) { + bedcolor = 14; + } else if (javaId.contains("minecraft:black")) { + bedcolor = 15; + } + + } + // -1 is used throughout the code to indicate no bed color. + if (bedcolor > -1) { + BEDCOLORS.put(javaBlockState, bedcolor); + } + if ("minecraft:water[level=0]".equals(javaId)) { waterRuntimeId = bedrockRuntimeId; } @@ -197,6 +242,13 @@ public class BlockTranslator { return WATERLOGGED.contains(state.getId()); } + public static byte getBedColor(BlockState state) { + if (BEDCOLORS.containsKey(state)) { + return BEDCOLORS.get(state); + } + return -1; + } + public static BlockState getJavaWaterloggedState(int bedrockId) { return BEDROCK_TO_JAVA_BLOCK_MAP.get(1 << 31 | bedrockId); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java index b9fca124..029a6f6f 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java @@ -105,7 +105,16 @@ public class JavaChunkDataTranslator extends PacketTranslator blockEntityEntry: chunkData.beds.int2ObjectEntrySet()) { + int x = blockEntityEntry.getValue().getInt("x"); + int y = blockEntityEntry.getValue().getInt("y"); + int z = blockEntityEntry.getValue().getInt("z"); + + ChunkUtils.updateBlock(session, new BlockState(blockEntityEntry.getIntKey()), new Position(x, y, z)); + } chunkData.signs.clear(); + chunkData.beds.clear(); } else { final int xOffset = packet.getColumn().getX() << 4; final int zOffset = packet.getColumn().getZ() << 4; diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java index 8da00fa3..66238263 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -31,6 +31,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.nbt.CompoundTagBuilder; import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; @@ -45,6 +46,8 @@ import org.geysermc.connector.world.chunk.ChunkPosition; import org.geysermc.connector.network.translators.block.BlockTranslator; import org.geysermc.connector.world.chunk.ChunkSection; +import java.util.concurrent.TimeUnit; + import static org.geysermc.connector.network.translators.block.BlockTranslator.BEDROCK_WATER_ID; public class ChunkUtils { @@ -72,6 +75,9 @@ public class ChunkUtils { if (BlockTranslator.getBlockEntityString(blockState) != null && BlockTranslator.getBlockEntityString(blockState).contains("sign[")) { Position pos = new ChunkPosition(column.getX(), column.getZ()).getBlock(x, (chunkY << 4) + y, z); chunkData.signs.put(blockState.getId(), TranslatorsInit.getBlockEntityTranslators().get("Sign").getDefaultBedrockTag("Sign", pos.getX(), pos.getY(), pos.getZ())); + } else if (BlockTranslator.getBedColor(blockState) > -1) { + Position pos = new ChunkPosition(column.getX(), column.getZ()).getBlock(x, (chunkY << 4) + y, z); + chunkData.beds.put(blockState.getId(), getBedTag(BlockTranslator.getBedColor(blockState), pos)); } else { section.getBlockStorageArray()[0].setFullBlock(ChunkSection.blockPosition(x, y, z), id); } @@ -79,6 +85,7 @@ public class ChunkUtils { if (BlockTranslator.isWaterlogged(blockState)) { section.getBlockStorageArray()[1].setFullBlock(ChunkSection.blockPosition(x, y, z), BEDROCK_WATER_ID); } + } } } @@ -128,6 +135,23 @@ public class ChunkUtils { waterPacket.setRuntimeId(0); } session.getUpstream().sendPacket(waterPacket); + + // Since Java stores bed colors as part of the namespaced ID and Bedrock stores it as a tag + // This is the only place I could find that interacts with the Java block state and block updates + byte bedcolor = BlockTranslator.getBedColor(blockState); + // If Bed Color is not -1 then it is indeed a bed with a color. + if (bedcolor > -1) { + Position pos = new Position(position.getX(), position.getY(), position.getZ()); + com.nukkitx.nbt.tag.CompoundTag finalbedTag = getBedTag(bedcolor, pos); + // Delay needed, otherwise newly placed beds will not get their color + // Delay is not needed for beds already placed on login + session.getConnector().getGeneralThreadPool().schedule(() -> + BlockEntityUtils.updateBlockEntity(session, finalbedTag, pos), + 500, + TimeUnit.MILLISECONDS + ); + } + } public static void sendEmptyChunks(GeyserSession session, Vector3i position, int radius, boolean forceUpdate) { @@ -160,5 +184,15 @@ public class ChunkUtils { public com.nukkitx.nbt.tag.CompoundTag[] blockEntities = new com.nukkitx.nbt.tag.CompoundTag[0]; public Int2ObjectMap signs = new Int2ObjectOpenHashMap<>(); + public Int2ObjectMap beds = new Int2ObjectOpenHashMap<>(); + } + public static com.nukkitx.nbt.tag.CompoundTag getBedTag(byte bedcolor, Position pos) { + CompoundTagBuilder tagBuilder = CompoundTagBuilder.builder() + .intTag("x", pos.getX()) + .intTag("y", pos.getY()) + .intTag("z", pos.getZ()) + .stringTag("id", "Bed"); + tagBuilder.byteTag("color", bedcolor); + return tagBuilder.buildRootTag(); } } From 545ab0f26894e6ea8c6cf5ece6405eba6b5a8f05 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Thu, 26 Mar 2020 10:22:44 -0400 Subject: [PATCH 049/109] Move bed-specific code to BedBlockEntityTranslator.java --- .../entity/BedBlockEntityTranslator.java | 41 +++++++++++++++++++ .../geysermc/connector/utils/ChunkUtils.java | 29 ++----------- 2 files changed, 44 insertions(+), 26 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BedBlockEntityTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BedBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BedBlockEntityTranslator.java new file mode 100644 index 00000000..42865918 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BedBlockEntityTranslator.java @@ -0,0 +1,41 @@ +package org.geysermc.connector.network.translators.block.entity; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; +import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.nbt.CompoundTagBuilder; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.block.BlockTranslator; +import org.geysermc.connector.utils.BlockEntityUtils; + +import java.util.concurrent.TimeUnit; + +public class BedBlockEntityTranslator { + + public static void checkForBedColor(GeyserSession session, BlockState blockState, Vector3i position) { + byte bedcolor = BlockTranslator.getBedColor(blockState); + // If Bed Color is not -1 then it is indeed a bed with a color. + if (bedcolor > -1) { + Position pos = new Position(position.getX(), position.getY(), position.getZ()); + com.nukkitx.nbt.tag.CompoundTag finalbedTag = getBedTag(bedcolor, pos); + // Delay needed, otherwise newly placed beds will not get their color + // Delay is not needed for beds already placed on login + session.getConnector().getGeneralThreadPool().schedule(() -> + BlockEntityUtils.updateBlockEntity(session, finalbedTag, pos), + 500, + TimeUnit.MILLISECONDS + ); + } + } + + public static com.nukkitx.nbt.tag.CompoundTag getBedTag(byte bedcolor, Position pos) { + CompoundTagBuilder tagBuilder = CompoundTagBuilder.builder() + .intTag("x", pos.getX()) + .intTag("y", pos.getY()) + .intTag("z", pos.getZ()) + .stringTag("id", "Bed"); + tagBuilder.byteTag("color", bedcolor); + return tagBuilder.buildRootTag(); + } + +} diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java index 66238263..0a3e3863 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -31,7 +31,6 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.nukkitx.math.vector.Vector3i; -import com.nukkitx.nbt.CompoundTagBuilder; import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; @@ -45,8 +44,7 @@ import org.geysermc.connector.network.translators.block.entity.BlockEntityTransl import org.geysermc.connector.world.chunk.ChunkPosition; import org.geysermc.connector.network.translators.block.BlockTranslator; import org.geysermc.connector.world.chunk.ChunkSection; - -import java.util.concurrent.TimeUnit; +import org.geysermc.connector.network.translators.block.entity.BedBlockEntityTranslator; import static org.geysermc.connector.network.translators.block.BlockTranslator.BEDROCK_WATER_ID; @@ -77,7 +75,7 @@ public class ChunkUtils { chunkData.signs.put(blockState.getId(), TranslatorsInit.getBlockEntityTranslators().get("Sign").getDefaultBedrockTag("Sign", pos.getX(), pos.getY(), pos.getZ())); } else if (BlockTranslator.getBedColor(blockState) > -1) { Position pos = new ChunkPosition(column.getX(), column.getZ()).getBlock(x, (chunkY << 4) + y, z); - chunkData.beds.put(blockState.getId(), getBedTag(BlockTranslator.getBedColor(blockState), pos)); + chunkData.beds.put(blockState.getId(), BedBlockEntityTranslator.getBedTag(BlockTranslator.getBedColor(blockState), pos)); } else { section.getBlockStorageArray()[0].setFullBlock(ChunkSection.blockPosition(x, y, z), id); } @@ -138,19 +136,7 @@ public class ChunkUtils { // Since Java stores bed colors as part of the namespaced ID and Bedrock stores it as a tag // This is the only place I could find that interacts with the Java block state and block updates - byte bedcolor = BlockTranslator.getBedColor(blockState); - // If Bed Color is not -1 then it is indeed a bed with a color. - if (bedcolor > -1) { - Position pos = new Position(position.getX(), position.getY(), position.getZ()); - com.nukkitx.nbt.tag.CompoundTag finalbedTag = getBedTag(bedcolor, pos); - // Delay needed, otherwise newly placed beds will not get their color - // Delay is not needed for beds already placed on login - session.getConnector().getGeneralThreadPool().schedule(() -> - BlockEntityUtils.updateBlockEntity(session, finalbedTag, pos), - 500, - TimeUnit.MILLISECONDS - ); - } + BedBlockEntityTranslator.checkForBedColor(session, blockState, position); } @@ -186,13 +172,4 @@ public class ChunkUtils { public Int2ObjectMap signs = new Int2ObjectOpenHashMap<>(); public Int2ObjectMap beds = new Int2ObjectOpenHashMap<>(); } - public static com.nukkitx.nbt.tag.CompoundTag getBedTag(byte bedcolor, Position pos) { - CompoundTagBuilder tagBuilder = CompoundTagBuilder.builder() - .intTag("x", pos.getX()) - .intTag("y", pos.getY()) - .intTag("z", pos.getZ()) - .stringTag("id", "Bed"); - tagBuilder.byteTag("color", bedcolor); - return tagBuilder.buildRootTag(); - } } From 22908c4de73e7f428e4ffd143bf217526eb0b81f Mon Sep 17 00:00:00 2001 From: BuildTools Date: Thu, 26 Mar 2020 10:31:57 -0400 Subject: [PATCH 050/109] Remove whitespace --- .../src/main/java/org/geysermc/connector/utils/ChunkUtils.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java index 0a3e3863..340edd01 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -83,7 +83,6 @@ public class ChunkUtils { if (BlockTranslator.isWaterlogged(blockState)) { section.getBlockStorageArray()[1].setFullBlock(ChunkSection.blockPosition(x, y, z), BEDROCK_WATER_ID); } - } } } @@ -137,7 +136,6 @@ public class ChunkUtils { // Since Java stores bed colors as part of the namespaced ID and Bedrock stores it as a tag // This is the only place I could find that interacts with the Java block state and block updates BedBlockEntityTranslator.checkForBedColor(session, blockState, position); - } public static void sendEmptyChunks(GeyserSession session, Vector3i position, int radius, boolean forceUpdate) { From e5766ef96a8197045fe03a9e611517ca83bfc482 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Thu, 26 Mar 2020 18:34:54 -0400 Subject: [PATCH 051/109] Store bed colors in Object2ByteOpenHashMap --- connector/pom.xml | 6 ++++++ .../network/translators/block/BlockTranslator.java | 5 +++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/connector/pom.xml b/connector/pom.xml index 6d56fbca..0258e9a3 100644 --- a/connector/pom.xml +++ b/connector/pom.xml @@ -48,6 +48,12 @@ 8.1.1 compile + + com.nukkitx.fastutil + fastutil-object-byte-maps + 8.3.1 + compile + com.github.steveice10 opennbt diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java index f0c47410..d3821154 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java @@ -35,6 +35,7 @@ import com.nukkitx.nbt.tag.ListTag; import gnu.trove.map.TObjectIntMap; import gnu.trove.map.hash.TObjectIntHashMap; import it.unimi.dsi.fastutil.ints.*; +import it.unimi.dsi.fastutil.objects.*; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.utils.Toolbox; @@ -50,7 +51,7 @@ public class BlockTranslator { private static final Int2ObjectMap BEDROCK_TO_JAVA_BLOCK_MAP = new Int2ObjectOpenHashMap<>(); private static final Map JAVA_ID_BLOCK_MAP = new HashMap<>(); private static final IntSet WATERLOGGED = new IntOpenHashSet(); - private static final Map BEDCOLORS = new HashMap<>(); + private static final Object2ByteOpenHashMap BEDCOLORS = new Object2ByteOpenHashMap<>(); private static final Map JAVA_ID_TO_BLOCK_ENTITY_MAP = new HashMap<>(); @@ -244,7 +245,7 @@ public class BlockTranslator { public static byte getBedColor(BlockState state) { if (BEDCOLORS.containsKey(state)) { - return BEDCOLORS.get(state); + return BEDCOLORS.getByte(state); } return -1; } From 7a402c40b334d8d32247c7f5e96aa5aa87865a68 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Fri, 27 Mar 2020 13:08:21 -0400 Subject: [PATCH 052/109] Use mappings to generate bed colors --- .../translators/block/BlockTranslator.java | 45 +++---------------- 1 file changed, 5 insertions(+), 40 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java index d3821154..6597b9b3 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java @@ -105,46 +105,11 @@ public class BlockTranslator { // If the Java ID is bed, signal that it needs a tag to show color // The color is in the namespace ID in Java Edition but it's a tag in Bedrock. - byte bedcolor = -1; - if (javaId.contains("_bed[")) { - if (javaId.contains("minecraft:white")) { - bedcolor = 0; - } else if (javaId.contains("minecraft:orange")) { - bedcolor = 1; - } else if (javaId.contains("minecraft:magenta")) { - bedcolor = 2; - } else if (javaId.contains("minecraft:light_blue")) { - bedcolor = 3; - } else if (javaId.contains("minecraft:yellow")) { - bedcolor = 4; - } else if (javaId.contains("minecraft:lime")) { - bedcolor = 5; - } else if (javaId.contains("minecraft:pink")) { - bedcolor = 6; - } else if (javaId.contains("minecraft:gray")) { - bedcolor = 7; - } else if (javaId.contains("minecraft:light_gray")) { - bedcolor = 8; - } else if (javaId.contains("minecraft:cyan")) { - bedcolor = 9; - } else if (javaId.contains("minecraft:purple")) { - bedcolor = 10; - } else if (javaId.contains("minecraft:blue")) { - bedcolor = 11; - } else if (javaId.contains("minecraft:brown")) { - bedcolor = 12; - } else if (javaId.contains("minecraft:green")) { - bedcolor = 13; - } else if (javaId.contains("minecraft:red")) { - bedcolor = 14; - } else if (javaId.contains("minecraft:black")) { - bedcolor = 15; - } - - } - // -1 is used throughout the code to indicate no bed color. - if (bedcolor > -1) { - BEDCOLORS.put(javaBlockState, bedcolor); + JsonNode bedColor = entry.getValue().get("bed_color"); + if (bedColor != null) { + System.out.println(bedColor.intValue()); + // Converting to byte because the final tag value is a byte. bedColor.binaryValue() returns an array + BEDCOLORS.put(javaBlockState, (byte) bedColor.intValue()); } if ("minecraft:water[level=0]".equals(javaId)) { From 17258dcaf6b56e3a4a9ed9cb8395d6537526e6c6 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Fri, 27 Mar 2020 13:09:40 -0400 Subject: [PATCH 053/109] Remove debugging code --- .../connector/network/translators/block/BlockTranslator.java | 1 - 1 file changed, 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java index 6597b9b3..45ac1e82 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java @@ -107,7 +107,6 @@ public class BlockTranslator { // The color is in the namespace ID in Java Edition but it's a tag in Bedrock. JsonNode bedColor = entry.getValue().get("bed_color"); if (bedColor != null) { - System.out.println(bedColor.intValue()); // Converting to byte because the final tag value is a byte. bedColor.binaryValue() returns an array BEDCOLORS.put(javaBlockState, (byte) bedColor.intValue()); } From 7b5bb22321dddb020d9a0a36855b0dc6c7f1effa Mon Sep 17 00:00:00 2001 From: BuildTools Date: Fri, 27 Mar 2020 14:21:34 -0400 Subject: [PATCH 054/109] Rename BEDCOLORS to BED_COLORS --- .../network/translators/block/BlockTranslator.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java index 45ac1e82..908b88a8 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java @@ -51,7 +51,7 @@ public class BlockTranslator { private static final Int2ObjectMap BEDROCK_TO_JAVA_BLOCK_MAP = new Int2ObjectOpenHashMap<>(); private static final Map JAVA_ID_BLOCK_MAP = new HashMap<>(); private static final IntSet WATERLOGGED = new IntOpenHashSet(); - private static final Object2ByteOpenHashMap BEDCOLORS = new Object2ByteOpenHashMap<>(); + private static final Object2ByteOpenHashMap BED_COLORS = new Object2ByteOpenHashMap<>(); private static final Map JAVA_ID_TO_BLOCK_ENTITY_MAP = new HashMap<>(); @@ -108,7 +108,7 @@ public class BlockTranslator { JsonNode bedColor = entry.getValue().get("bed_color"); if (bedColor != null) { // Converting to byte because the final tag value is a byte. bedColor.binaryValue() returns an array - BEDCOLORS.put(javaBlockState, (byte) bedColor.intValue()); + BED_COLORS.put(javaBlockState, (byte) bedColor.intValue()); } if ("minecraft:water[level=0]".equals(javaId)) { @@ -208,8 +208,8 @@ public class BlockTranslator { } public static byte getBedColor(BlockState state) { - if (BEDCOLORS.containsKey(state)) { - return BEDCOLORS.getByte(state); + if (BED_COLORS.containsKey(state)) { + return BED_COLORS.getByte(state); } return -1; } From 7cbb0388e2b8cfbba3ccabdf2bab3bf16c9a0581 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Fri, 27 Mar 2020 16:16:33 -0400 Subject: [PATCH 055/109] Update mappings submodule --- connector/src/main/resources/mappings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connector/src/main/resources/mappings b/connector/src/main/resources/mappings index 278c7344..efc9db6b 160000 --- a/connector/src/main/resources/mappings +++ b/connector/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 278c73449aeeb4064c7513a68f98a49a5f463f0a +Subproject commit efc9db6b7d51bdf145230933ac23b321ac1c132d From a00cf75bc7ecffb5c3648e29a16f819b5624bfc7 Mon Sep 17 00:00:00 2001 From: William Johnstone Date: Fri, 27 Mar 2020 23:23:26 +0000 Subject: [PATCH 056/109] Fix waterlogged blocks --- .../connector/network/translators/block/BlockTranslator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java index 18ac3e6d..43a3d349 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java @@ -104,7 +104,8 @@ public class BlockTranslator { if ("minecraft:water[level=0]".equals(javaId)) { waterRuntimeId = bedrockRuntimeId; } - boolean waterlogged = entry.getValue().has("waterlogged") && entry.getValue().get("waterlogged").booleanValue(); + boolean waterlogged = entry.getKey().contains("waterlogged=true") + || javaId.contains("minecraft:bubble_column") || javaId.contains("minecraft:kelp") || javaId.contains("seagrass"); if (waterlogged) { BEDROCK_TO_JAVA_BLOCK_MAP.putIfAbsent(bedrockRuntimeId | 1 << 31, javaBlockState); From 0caee67e43480ec07ef9ca5f4e70cd3409ba5cd4 Mon Sep 17 00:00:00 2001 From: William Johnstone Date: Fri, 27 Mar 2020 23:39:53 +0000 Subject: [PATCH 057/109] Finalise block breaking, (water calculations omitted because of no access to server api) --- .../org/geysermc/connector/entity/PlayerEntity.java | 1 + .../connector/network/translators/Registry.java | 3 +++ .../entity/player/JavaPlayerActionAckTranslator.java | 3 --- .../java/org/geysermc/connector/utils/BlockUtils.java | 10 +++------- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java index c7a0f96c..ec849ec2 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java @@ -53,6 +53,7 @@ public class PlayerEntity extends LivingEntity { private boolean playerList = true; private final EntityEffectCache effectCache; + public PlayerEntity(GameProfile gameProfile, long entityId, long geyserId, Vector3f position, Vector3f motion, Vector3f rotation) { super(entityId, geyserId, EntityType.PLAYER, position, motion, rotation); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/Registry.java b/connector/src/main/java/org/geysermc/connector/network/translators/Registry.java index f32fe4b6..866a454f 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/Registry.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/Registry.java @@ -47,12 +47,15 @@ public class Registry { BEDROCK.MAP.put(clazz, translator); } + @SuppressWarnings("unchecked") public

boolean translate(Class clazz, P packet, GeyserSession session) { if (!session.getUpstream().isClosed() && !session.isClosed()) { try { if (MAP.containsKey(clazz)) { ((PacketTranslator

) MAP.get(clazz)).translate(packet, session); return true; + } else { + GeyserConnector.getInstance().getLogger().debug("Could not find packet for " + (packet.toString().length() > 25 ? packet.getClass().getSimpleName() : packet)); } } catch (Throwable ex) { GeyserConnector.getInstance().getLogger().error("Could not translate packet " + packet.getClass().getSimpleName(), ex); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java index a338650d..fe72b669 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java @@ -65,12 +65,9 @@ public class JavaPlayerActionAckTranslator extends PacketTranslator Date: Sat, 28 Mar 2020 16:03:09 +0000 Subject: [PATCH 058/109] Add requested changes --- .../org/geysermc/connector/entity/PlayerEntity.java | 1 - .../entity/player/JavaPlayerActionAckTranslator.java | 10 +++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java index ec849ec2..c7a0f96c 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java @@ -53,7 +53,6 @@ public class PlayerEntity extends LivingEntity { private boolean playerList = true; private final EntityEffectCache effectCache; - public PlayerEntity(GameProfile gameProfile, long entityId, long geyserId, Vector3f position, Vector3f motion, Vector3f rotation) { super(entityId, geyserId, EntityType.PLAYER, position, motion, rotation); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java index fe72b669..ba39e706 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java @@ -44,13 +44,13 @@ public class JavaPlayerActionAckTranslator extends PacketTranslator Date: Thu, 2 Apr 2020 18:09:09 -0500 Subject: [PATCH 059/109] Use IntSet for JAVA_RUNTIME_WOOL_IDS --- .../connector/network/translators/block/BlockTranslator.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java index 8fc7788c..14725a8d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java @@ -61,15 +61,16 @@ public class BlockTranslator { private static final Int2ObjectMap BEDROCK_TO_JAVA_BLOCK_MAP = new Int2ObjectOpenHashMap<>(); private static final Map JAVA_ID_BLOCK_MAP = new HashMap<>(); private static final IntSet WATERLOGGED = new IntOpenHashSet(); - private static final Object2ByteMap BED_COLORS = new Object2ByteOpenHashMap<>(); private static final Map JAVA_ID_TO_BLOCK_ENTITY_MAP = new HashMap<>(); + private static final Object2ByteMap BED_COLORS = new Object2ByteOpenHashMap<>(); + public static final Int2DoubleMap JAVA_RUNTIME_ID_TO_HARDNESS = new Int2DoubleOpenHashMap(); public static final Int2BooleanMap JAVA_RUNTIME_ID_TO_CAN_HARVEST_WITH_HAND = new Int2BooleanOpenHashMap(); public static final Int2ObjectMap JAVA_RUNTIME_ID_TO_TOOL_TYPE = new Int2ObjectOpenHashMap<>(); // For block breaking animation math - public static final List JAVA_RUNTIME_WOOL_IDS = new ArrayList<>(); + public static final IntSet JAVA_RUNTIME_WOOL_IDS = new IntOpenHashSet(); public static final int JAVA_RUNTIME_COBWEB_ID; private static final int BLOCK_STATE_VERSION = 17760256; From 79906fae0ad21558e03a74559a5cb3647c2c65c3 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sat, 4 Apr 2020 02:45:51 -0500 Subject: [PATCH 060/109] Fix NPE if banner had no patterns --- .../block/entity/BannerBlockEntityTranslator.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BannerBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BannerBlockEntityTranslator.java index a5ed5994..d0d43107 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BannerBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BannerBlockEntityTranslator.java @@ -41,13 +41,14 @@ public class BannerBlockEntityTranslator extends BlockEntityTranslator { List> tags = new ArrayList<>(); ListTag patterns = tag.get("Patterns"); List tagsList = new ArrayList<>(); - for (com.github.steveice10.opennbt.tag.builtin.Tag patternTag : patterns.getValue()) { - tagsList.add(getPattern((CompoundTag) patternTag)); + if (tag.contains("Patterns")) { + for (com.github.steveice10.opennbt.tag.builtin.Tag patternTag : patterns.getValue()) { + tagsList.add(getPattern((CompoundTag) patternTag)); + } + com.nukkitx.nbt.tag.ListTag bedrockPatterns = + new com.nukkitx.nbt.tag.ListTag<>("Patterns", com.nukkitx.nbt.tag.CompoundTag.class, tagsList); + tags.add(bedrockPatterns); } - com.nukkitx.nbt.tag.ListTag bedrockPatterns = - new com.nukkitx.nbt.tag.ListTag<>("Patterns", com.nukkitx.nbt.tag.CompoundTag.class, tagsList); - tags.add(bedrockPatterns); - if (tag.contains("CustomName")) { tags.add(new StringTag("CustomName", (String) tag.get("CustomName").getValue())); } From c13bbcda857ced9b1031d4dee16fcfaa1d1cec63 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sat, 4 Apr 2020 17:22:54 -0500 Subject: [PATCH 061/109] Fix null block entity console spam, which caused the world to be invisible This was a rare bug that only happened on very few servers, and from what I gathered, only 1.8 servers using ViaVersion. --- .../translators/block/entity/BlockEntityTranslator.java | 5 ++--- .../java/world/JavaUpdateTileEntityTranslator.java | 4 ++-- .../main/java/org/geysermc/connector/utils/ChunkUtils.java | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java index 71b83d59..07962089 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java @@ -44,13 +44,12 @@ public abstract class BlockEntityTranslator { public abstract com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z); - public com.nukkitx.nbt.tag.CompoundTag getBlockEntityTag(CompoundTag tag) { + public com.nukkitx.nbt.tag.CompoundTag getBlockEntityTag(String id, CompoundTag tag) { int x = Integer.parseInt(String.valueOf(tag.getValue().get("x").getValue())); int y = Integer.parseInt(String.valueOf(tag.getValue().get("y").getValue())); int z = Integer.parseInt(String.valueOf(tag.getValue().get("z").getValue())); - CompoundTagBuilder tagBuilder = getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId( - String.valueOf(tag.get("id").getValue())), x, y, z).toBuilder(); + CompoundTagBuilder tagBuilder = getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId(id), x, y, z).toBuilder(); translateTag(tag).forEach(tagBuilder::tag); return tagBuilder.buildRootTag(); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java index 8d21a315..7fa42d90 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java @@ -45,12 +45,12 @@ public class JavaUpdateTileEntityTranslator extends PacketTranslator - BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag(packet.getNbt()), packet.getPosition()), + BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag("Sign", packet.getNbt()), packet.getPosition()), 5, TimeUnit.SECONDS ); } else { - BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag(packet.getNbt()), packet.getPosition()); + BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag(id, packet.getNbt()), packet.getPosition()); } } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java index e5abb887..bb1df240 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -103,7 +103,7 @@ public class ChunkUtils { String id = BlockEntityUtils.getBedrockBlockEntityId(tagName); BlockEntityTranslator blockEntityTranslator = BlockEntityUtils.getBlockEntityTranslator(id); - bedrockBlockEntities[i] = blockEntityTranslator.getBlockEntityTag(tag); + bedrockBlockEntities[i] = blockEntityTranslator.getBlockEntityTag(tagName, tag); } chunkData.blockEntities = bedrockBlockEntities; From 933453517bbeb4e1fc4dde15d144992a4e9d8ada Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sat, 4 Apr 2020 18:00:30 -0500 Subject: [PATCH 062/109] Don't minimize the jar for plugin versions (Actually fixes #265) --- bootstrap/bukkit/pom.xml | 1 - bootstrap/bungeecord/pom.xml | 1 - bootstrap/sponge/pom.xml | 1 - bootstrap/velocity/pom.xml | 3 --- 4 files changed, 6 deletions(-) diff --git a/bootstrap/bukkit/pom.xml b/bootstrap/bukkit/pom.xml index 0e5dd3df..fd2ecbf0 100644 --- a/bootstrap/bukkit/pom.xml +++ b/bootstrap/bukkit/pom.xml @@ -54,7 +54,6 @@ org.geysermc.platform.bukkit.shaded.fastutil - true diff --git a/bootstrap/bungeecord/pom.xml b/bootstrap/bungeecord/pom.xml index 317e80cb..0f6de3fa 100644 --- a/bootstrap/bungeecord/pom.xml +++ b/bootstrap/bungeecord/pom.xml @@ -54,7 +54,6 @@ org.geysermc.platform.bungeecord.shaded.netty - true diff --git a/bootstrap/sponge/pom.xml b/bootstrap/sponge/pom.xml index 83c070ae..696721d2 100644 --- a/bootstrap/sponge/pom.xml +++ b/bootstrap/sponge/pom.xml @@ -58,7 +58,6 @@ org.geysermc.platform.sponge.shaded.fastutil - true diff --git a/bootstrap/velocity/pom.xml b/bootstrap/velocity/pom.xml index 22fe9211..74d42e00 100644 --- a/bootstrap/velocity/pom.xml +++ b/bootstrap/velocity/pom.xml @@ -43,9 +43,6 @@ shade - - true - From d635939c5b82b7a7191866c65170979632eee3e8 Mon Sep 17 00:00:00 2001 From: MrPowerGamerBR Date: Sat, 4 Apr 2020 17:23:02 -0300 Subject: [PATCH 063/109] Add map item translators --- .../bedrock/BedrockMapInfoRequestPacket.java | 37 +++ .../translators/item/ItemTranslator.java | 11 +- .../java/world/JavaMapDataTranslator.java | 68 +++++ .../geysermc/connector/utils/MapColor.java | 244 ++++++++++++++++++ 4 files changed, 359 insertions(+), 1 deletion(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMapInfoRequestPacket.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaMapDataTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/utils/MapColor.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMapInfoRequestPacket.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMapInfoRequestPacket.java new file mode 100644 index 00000000..67db2017 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMapInfoRequestPacket.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.bedrock; + +import com.nukkitx.protocol.bedrock.packet.MapInfoRequestPacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.network.translators.Translator; + +@Translator(packet = MapInfoRequestPacket.class) +public class BedrockMapInfoRequestPacket extends PacketTranslator { + @Override + public void translate(MapInfoRequestPacket packet, GeyserSession session) {} +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java index 196eee85..a2f66409 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java @@ -94,7 +94,16 @@ public class ItemTranslator { GeyserConnector.getInstance().getLogger().debug("Unknown java potion: " + potionTag.getValue()); } } - return ItemData.of(bedrockItem.getBedrockId(), (short) bedrockItem.getBedrockData(), stack.getAmount(), translateToBedrockNBT(stack.getNbt())); + + // TODO: Create proper transformers instead of shoving everything here + CompoundTag tag = stack.getNbt(); + IntTag mapId = tag.get("map"); + + if (mapId != null) + tag.put(new StringTag("map_uuid", mapId.getValue().toString())); + + + return ItemData.of(bedrockItem.getBedrockId(), (short) bedrockItem.getBedrockData(), stack.getAmount(), translateToBedrockNBT(tag)); } public ItemEntry getItem(ItemStack stack) { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaMapDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaMapDataTranslator.java new file mode 100644 index 00000000..ccf3e209 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaMapDataTranslator.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.java.world; + +import com.github.steveice10.mc.protocol.data.game.world.map.MapData; +import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerMapDataPacket; +import com.nukkitx.protocol.bedrock.packet.ClientboundMapItemDataPacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.network.translators.Translator; +import org.geysermc.connector.utils.MapColor; + +@Translator(packet = ServerMapDataPacket.class) +public class JavaMapDataTranslator extends PacketTranslator { + @Override + public void translate(ServerMapDataPacket packet, GeyserSession session) { + ClientboundMapItemDataPacket mapItemDataPacket = new ClientboundMapItemDataPacket(); + + mapItemDataPacket.setUniqueMapId(packet.getMapId()); + mapItemDataPacket.setDimensionId(session.getLastDimPacket().getDimension()); + mapItemDataPacket.setLocked(packet.isLocked()); + mapItemDataPacket.setScale(packet.getScale()); + + MapData data = packet.getData(); + if (data != null) { + mapItemDataPacket.setXOffset(data.getX()); + mapItemDataPacket.setYOffset(data.getY()); + mapItemDataPacket.setWidth(data.getColumns()); + mapItemDataPacket.setHeight(data.getRows()); + + // Every int entry is an ARGB color + int[] colors = new int[data.getData().length]; + + int idx = 0; + for (byte colorId : data.getData()) { + colors[idx] = MapColor.fromId(colorId).toARGB(); + idx++; + } + + mapItemDataPacket.setColors(colors); + } + + session.getUpstream().getSession().sendPacket(mapItemDataPacket); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/utils/MapColor.java b/connector/src/main/java/org/geysermc/connector/utils/MapColor.java new file mode 100644 index 00000000..2c4a13b9 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/utils/MapColor.java @@ -0,0 +1,244 @@ +package org.geysermc.connector.utils; + +import java.util.Arrays; + +public enum MapColor { + COLOR_0(-1, -1, -1), + COLOR_1(-1, -1, -1), + COLOR_2(-1, -1, -1), + COLOR_3(-1, -1, -1), + COLOR_4(89, 125, 39), + COLOR_5(109, 153, 48), + COLOR_6(127, 178, 56), + COLOR_7(67, 94, 29), + COLOR_8(174, 164, 115), + COLOR_9(213, 201, 140), + COLOR_10(247, 233, 163), + COLOR_11(130, 123, 86), + COLOR_12(140, 140, 140), + COLOR_13(171, 171, 171), + COLOR_14(199, 199, 199), + COLOR_15(105, 105, 105), + COLOR_16(180, 0, 0), + COLOR_17(220, 0, 0), + COLOR_18(255, 0, 0), + COLOR_19(135, 0, 0), + COLOR_20(112, 112, 180), + COLOR_21(138, 138, 220), + COLOR_22(160, 160, 255), + COLOR_23(84, 84, 135), + COLOR_24(117, 117, 117), + COLOR_25(144, 144, 144), + COLOR_26(167, 167, 167), + COLOR_27(88, 88, 88), + COLOR_28(0, 87, 0), + COLOR_29(0, 106, 0), + COLOR_30(0, 124, 0), + COLOR_31(0, 65, 0), + COLOR_32(180, 180, 180), + COLOR_33(220, 220, 220), + COLOR_34(255, 255, 255), + COLOR_35(135, 135, 135), + COLOR_36(115, 118, 129), + COLOR_37(141, 144, 158), + COLOR_38(164, 168, 184), + COLOR_39(86, 88, 97), + COLOR_40(106, 76, 54), + COLOR_41(130, 94, 66), + COLOR_42(151, 109, 77), + COLOR_43(79, 57, 40), + COLOR_44(79, 79, 79), + COLOR_45(96, 96, 96), + COLOR_46(112, 112, 112), + COLOR_47(59, 59, 59), + COLOR_48(45, 45, 180), + COLOR_49(55, 55, 220), + COLOR_50(64, 64, 255), + COLOR_51(33, 33, 135), + COLOR_52(100, 84, 50), + COLOR_53(123, 102, 62), + COLOR_54(143, 119, 72), + COLOR_55(75, 63, 38), + COLOR_56(180, 177, 172), + COLOR_57(220, 217, 211), + COLOR_58(255, 252, 245), + COLOR_59(135, 133, 129), + COLOR_60(152, 89, 36), + COLOR_61(186, 109, 44), + COLOR_62(216, 127, 51), + COLOR_63(114, 67, 27), + COLOR_64(125, 53, 152), + COLOR_65(153, 65, 186), + COLOR_66(178, 76, 216), + COLOR_67(94, 40, 114), + COLOR_68(72, 108, 152), + COLOR_69(88, 132, 186), + COLOR_70(102, 153, 216), + COLOR_71(54, 81, 114), + COLOR_72(161, 161, 36), + COLOR_73(197, 197, 44), + COLOR_74(229, 229, 51), + COLOR_75(121, 121, 27), + COLOR_76(89, 144, 17), + COLOR_77(109, 176, 21), + COLOR_78(127, 204, 25), + COLOR_79(67, 108, 13), + COLOR_80(170, 89, 116), + COLOR_81(208, 109, 142), + COLOR_82(242, 127, 165), + COLOR_83(128, 67, 87), + COLOR_84(53, 53, 53), + COLOR_85(65, 65, 65), + COLOR_86(76, 76, 76), + COLOR_87(40, 40, 40), + COLOR_88(108, 108, 108), + COLOR_89(132, 132, 132), + COLOR_90(153, 153, 153), + COLOR_91(81, 81, 81), + COLOR_92(53, 89, 108), + COLOR_93(65, 109, 132), + COLOR_94(76, 127, 153), + COLOR_95(40, 67, 81), + COLOR_96(89, 44, 125), + COLOR_97(109, 54, 153), + COLOR_98(127, 63, 178), + COLOR_99(67, 33, 94), + COLOR_100(36, 53, 125), + COLOR_101(44, 65, 153), + COLOR_102(51, 76, 178), + COLOR_103(27, 40, 94), + COLOR_104(72, 53, 36), + COLOR_105(88, 65, 44), + COLOR_106(102, 76, 51), + COLOR_107(54, 40, 27), + COLOR_108(72, 89, 36), + COLOR_109(88, 109, 44), + COLOR_110(102, 127, 51), + COLOR_111(54, 67, 27), + COLOR_112(108, 36, 36), + COLOR_113(132, 44, 44), + COLOR_114(153, 51, 51), + COLOR_115(81, 27, 27), + COLOR_116(17, 17, 17), + COLOR_117(21, 21, 21), + COLOR_118(25, 25, 25), + COLOR_119(13, 13, 13), + COLOR_120(176, 168, 54), + COLOR_121(215, 205, 66), + COLOR_122(250, 238, 77), + COLOR_123(132, 126, 40), + COLOR_124(64, 154, 150), + COLOR_125(79, 188, 183), + COLOR_126(92, 219, 213), + COLOR_127(48, 115, 112), + COLOR_128(52, 90, 180), + COLOR_129(63, 110, 220), + COLOR_130(74, 128, 255), + COLOR_131(39, 67, 135), + COLOR_132(0, 153, 40), + COLOR_133(0, 187, 50), + COLOR_134(0, 217, 58), + COLOR_135(0, 114, 30), + COLOR_136(91, 60, 34), + COLOR_137(111, 74, 42), + COLOR_138(129, 86, 49), + COLOR_139(68, 45, 25), + COLOR_140(79, 1, 0), + COLOR_141(96, 1, 0), + COLOR_142(112, 2, 0), + COLOR_143(59, 1, 0), + COLOR_144(147, 124, 113), + COLOR_145(180, 152, 138), + COLOR_146(209, 177, 161), + COLOR_147(110, 93, 85), + COLOR_148(112, 57, 25), + COLOR_149(137, 70, 31), + COLOR_150(159, 82, 36), + COLOR_151(84, 43, 19), + COLOR_152(105, 61, 76), + COLOR_153(128, 75, 93), + COLOR_154(149, 87, 108), + COLOR_155(78, 46, 57), + COLOR_156(79, 76, 97), + COLOR_157(96, 93, 119), + COLOR_158(112, 108, 138), + COLOR_159(59, 57, 73), + COLOR_160(131, 93, 25), + COLOR_161(160, 114, 31), + COLOR_162(186, 133, 36), + COLOR_163(98, 70, 19), + COLOR_164(72, 82, 37), + COLOR_165(88, 100, 45), + COLOR_166(103, 117, 53), + COLOR_167(54, 61, 28), + COLOR_168(112, 54, 55), + COLOR_169(138, 66, 67), + COLOR_170(160, 77, 78), + COLOR_171(84, 40, 41), + COLOR_172(40, 28, 24), + COLOR_173(49, 35, 30), + COLOR_174(57, 41, 35), + COLOR_175(30, 21, 18), + COLOR_176(95, 75, 69), + COLOR_177(116, 92, 84), + COLOR_178(135, 107, 98), + COLOR_179(71, 56, 51), + COLOR_180(61, 64, 64), + COLOR_181(75, 79, 79), + COLOR_182(87, 92, 92), + COLOR_183(46, 48, 48), + COLOR_184(86, 51, 62), + COLOR_185(105, 62, 75), + COLOR_186(122, 73, 88), + COLOR_187(64, 38, 46), + COLOR_188(53, 43, 64), + COLOR_189(65, 53, 79), + COLOR_190(76, 62, 92), + COLOR_191(40, 32, 48), + COLOR_192(53, 35, 24), + COLOR_193(65, 43, 30), + COLOR_194(76, 50, 35), + COLOR_195(40, 26, 18), + COLOR_196(53, 57, 29), + COLOR_197(65, 70, 36), + COLOR_198(76, 82, 42), + COLOR_199(40, 43, 22), + COLOR_200(100, 42, 32), + COLOR_201(122, 51, 39), + COLOR_202(142, 60, 46), + COLOR_203(75, 31, 24), + COLOR_204(26, 15, 11), + COLOR_205(31, 18, 13), + COLOR_206(37, 22, 16), + COLOR_207(19, 11, 8); + + private final int red; + private final int green; + private final int blue; + + MapColor(int red, int green, int blue) { + this.red = red; + this.green = green; + this.blue = blue; + } + + int getId() { + return ordinal(); + } + + public static MapColor fromId(int id) { + return Arrays.stream(values()).filter(color -> color.getId() == id).findFirst().get(); + } + + public int toARGB() { + int alpha = 255; + if (red == -1 && green == -1 && blue == -1) + alpha = 0; // transparent + + long result = red & 0xff; + result |= (green & 0xff) << 8; + result |= (blue & 0xff) << 16; + result |= (alpha & 0xff) << 24; + return (int) (result & 0xFFFFFFFFL); + } +} \ No newline at end of file From b92f36e2e34351f9628f4ba00613ac0cc4937e55 Mon Sep 17 00:00:00 2001 From: MrPowerGamerBR Date: Sat, 4 Apr 2020 17:28:59 -0300 Subject: [PATCH 064/109] Remove unused map info request translator This was used for debugging purposes, to check if the map was correctly remapped to the client because, if it wasn't, it would've returned -1 as the map ID --- .../bedrock/BedrockMapInfoRequestPacket.java | 37 ------------------- 1 file changed, 37 deletions(-) delete mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMapInfoRequestPacket.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMapInfoRequestPacket.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMapInfoRequestPacket.java deleted file mode 100644 index 67db2017..00000000 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMapInfoRequestPacket.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * @author GeyserMC - * @link https://github.com/GeyserMC/Geyser - */ - -package org.geysermc.connector.network.translators.bedrock; - -import com.nukkitx.protocol.bedrock.packet.MapInfoRequestPacket; -import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.PacketTranslator; -import org.geysermc.connector.network.translators.Translator; - -@Translator(packet = MapInfoRequestPacket.class) -public class BedrockMapInfoRequestPacket extends PacketTranslator { - @Override - public void translate(MapInfoRequestPacket packet, GeyserSession session) {} -} From af1c6d69916ac3111436dc7847566c0706cefc47 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sun, 5 Apr 2020 00:44:23 -0500 Subject: [PATCH 065/109] Relocate fastutil for velocity version to fix NoClassDefFoundError --- bootstrap/velocity/pom.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/bootstrap/velocity/pom.xml b/bootstrap/velocity/pom.xml index 74d42e00..075aedc3 100644 --- a/bootstrap/velocity/pom.xml +++ b/bootstrap/velocity/pom.xml @@ -43,6 +43,14 @@ shade + + + + it.unimi.dsi.fastutil + org.geysermc.platform.velocity.shaded.fastutil + + + From b4cd6bacca37185642de2bf7d5bf166ec7471232 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sun, 5 Apr 2020 00:47:04 -0500 Subject: [PATCH 066/109] Fix improperly named bedrock packet translator --- ...r.java => BedrockSetLocalPlayerAsInitializedTranslator.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename connector/src/main/java/org/geysermc/connector/network/translators/bedrock/{BedrockPlayerInitializedTranslator.java => BedrockSetLocalPlayerAsInitializedTranslator.java} (95%) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockPlayerInitializedTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockSetLocalPlayerAsInitializedTranslator.java similarity index 95% rename from connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockPlayerInitializedTranslator.java rename to connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockSetLocalPlayerAsInitializedTranslator.java index fda2cade..54a5112d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockPlayerInitializedTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockSetLocalPlayerAsInitializedTranslator.java @@ -34,7 +34,7 @@ import org.geysermc.connector.utils.SkinUtils; import com.nukkitx.protocol.bedrock.packet.SetLocalPlayerAsInitializedPacket; @Translator(packet = SetLocalPlayerAsInitializedPacket.class) -public class BedrockPlayerInitializedTranslator extends PacketTranslator { +public class BedrockSetLocalPlayerAsInitializedTranslator extends PacketTranslator { @Override public void translate(SetLocalPlayerAsInitializedPacket packet, GeyserSession session) { if (session.getPlayerEntity().getGeyserId() == packet.getRuntimeEntityId()) { From 81c9e4f165d20895db2a68694704d03885bc8dc4 Mon Sep 17 00:00:00 2001 From: DoctorMacc Date: Mon, 6 Apr 2020 11:16:16 -0400 Subject: [PATCH 067/109] Fix beds and signs --- .../java/world/JavaChunkDataTranslator.java | 22 +++++++++---------- .../geysermc/connector/utils/ChunkUtils.java | 17 ++++++++++---- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java index 8c5bd0a2..010eb980 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java @@ -39,6 +39,7 @@ import io.netty.buffer.ByteBufOutputStream; import io.netty.buffer.Unpooled; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.objects.Object2IntMap; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.BiomeTranslator; @@ -47,6 +48,8 @@ import org.geysermc.connector.network.translators.Translator; import org.geysermc.connector.utils.ChunkUtils; import org.geysermc.connector.world.chunk.ChunkSection; +import java.util.HashMap; + @Translator(packet = ServerChunkDataPacket.class) public class JavaChunkDataTranslator extends PacketTranslator { @@ -102,20 +105,15 @@ public class JavaChunkDataTranslator extends PacketTranslator blockEntityEntry : chunkData.signs.int2ObjectEntrySet()) { - int x = blockEntityEntry.getValue().getInt("x"); - int y = blockEntityEntry.getValue().getInt("y"); - int z = blockEntityEntry.getValue().getInt("z"); - - ChunkUtils.updateBlock(session, new BlockState(blockEntityEntry.getIntKey()), new Position(x, y, z)); + for (Object2IntMap.Entry blockEntityEntry : chunkData.signs.object2IntEntrySet()) { + int x = blockEntityEntry.getKey().getInt("x"); + int y = blockEntityEntry.getKey().getInt("y"); + int z = blockEntityEntry.getKey().getInt("z"); + ChunkUtils.updateBlock(session, new BlockState(blockEntityEntry.getIntValue()), new Position(x, y, z)); } - for (Int2ObjectMap.Entry blockEntityEntry: chunkData.beds.int2ObjectEntrySet()) { - int x = blockEntityEntry.getValue().getInt("x"); - int y = blockEntityEntry.getValue().getInt("y"); - int z = blockEntityEntry.getValue().getInt("z"); - - ChunkUtils.updateBlock(session, new BlockState(blockEntityEntry.getIntKey()), new Position(x, y, z)); + for (HashMap.Entry blockEntityEntry: chunkData.beds.entrySet()) { + ChunkUtils.updateBlock(session, blockEntityEntry.getValue(), blockEntityEntry.getKey()); } chunkData.signs.clear(); chunkData.beds.clear(); diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java index bb1df240..5a4cc2bc 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -39,6 +39,9 @@ import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; + import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.block.entity.BlockEntityTranslator; @@ -48,6 +51,9 @@ import org.geysermc.connector.network.translators.block.BlockTranslator; import org.geysermc.connector.network.translators.block.entity.BedBlockEntityTranslator; import org.geysermc.connector.world.chunk.ChunkSection; +import java.util.HashMap; +import java.util.Map; + import static org.geysermc.connector.network.translators.block.BlockTranslator.BEDROCK_WATER_ID; public class ChunkUtils { @@ -74,10 +80,13 @@ public class ChunkUtils { if (BlockTranslator.getBlockEntityString(blockState) != null && BlockTranslator.getBlockEntityString(blockState).contains("sign[")) { Position pos = new ChunkPosition(column.getX(), column.getZ()).getBlock(x, (chunkY << 4) + y, z); - chunkData.signs.put(blockState.getId(), Translators.getBlockEntityTranslators().get("Sign").getDefaultBedrockTag("Sign", pos.getX(), pos.getY(), pos.getZ())); + System.out.println("Sign! " + pos.toString()); + chunkData.signs.put(Translators.getBlockEntityTranslators().get("Sign").getDefaultBedrockTag("Sign", pos.getX(), pos.getY(), pos.getZ()), blockState.getId()); } else if (BlockTranslator.getBedColor(blockState) > -1) { Position pos = new ChunkPosition(column.getX(), column.getZ()).getBlock(x, (chunkY << 4) + y, z); - chunkData.beds.put(blockState.getId(), BedBlockEntityTranslator.getBedTag(BlockTranslator.getBedColor(blockState), pos)); + // Beds need to be updated separately to add the bed color tag + // Previously this was done by matching block state but this resulted in only one bed per color+orientation showing + chunkData.beds.put(pos, blockState); } else { section.getBlockStorageArray()[0].setFullBlock(ChunkSection.blockPosition(x, y, z), id); } @@ -183,7 +192,7 @@ public class ChunkUtils { public ChunkSection[] sections; public com.nukkitx.nbt.tag.CompoundTag[] blockEntities = new com.nukkitx.nbt.tag.CompoundTag[0]; - public Int2ObjectMap signs = new Int2ObjectOpenHashMap<>(); - public Int2ObjectMap beds = new Int2ObjectOpenHashMap<>(); + public Object2IntMap signs = new Object2IntOpenHashMap<>(); + public Map beds = new HashMap<>(); } } From 44a46d18720a9281971f50ebb157422408326ba6 Mon Sep 17 00:00:00 2001 From: DoctorMacc Date: Mon, 6 Apr 2020 11:18:16 -0400 Subject: [PATCH 068/109] Remove unnecessary code --- .../main/java/org/geysermc/connector/utils/ChunkUtils.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java index 5a4cc2bc..b7bcb719 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -36,9 +36,6 @@ import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket; import com.nukkitx.protocol.bedrock.packet.NetworkChunkPublisherUpdatePacket; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; @@ -80,7 +77,6 @@ public class ChunkUtils { if (BlockTranslator.getBlockEntityString(blockState) != null && BlockTranslator.getBlockEntityString(blockState).contains("sign[")) { Position pos = new ChunkPosition(column.getX(), column.getZ()).getBlock(x, (chunkY << 4) + y, z); - System.out.println("Sign! " + pos.toString()); chunkData.signs.put(Translators.getBlockEntityTranslators().get("Sign").getDefaultBedrockTag("Sign", pos.getX(), pos.getY(), pos.getZ()), blockState.getId()); } else if (BlockTranslator.getBedColor(blockState) > -1) { Position pos = new ChunkPosition(column.getX(), column.getZ()).getBlock(x, (chunkY << 4) + y, z); From a392e544473497481a62c39c5dbfc3cfe66bf51e Mon Sep 17 00:00:00 2001 From: DoctorMacc Date: Mon, 6 Apr 2020 16:27:09 -0400 Subject: [PATCH 069/109] Fix requested changes --- .../translators/java/world/JavaChunkDataTranslator.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java index 010eb980..5d17e0e0 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java @@ -37,8 +37,6 @@ import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufOutputStream; import io.netty.buffer.Unpooled; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; - import it.unimi.dsi.fastutil.objects.Object2IntMap; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.network.session.GeyserSession; @@ -48,7 +46,7 @@ import org.geysermc.connector.network.translators.Translator; import org.geysermc.connector.utils.ChunkUtils; import org.geysermc.connector.world.chunk.ChunkSection; -import java.util.HashMap; +import java.util.Map; @Translator(packet = ServerChunkDataPacket.class) public class JavaChunkDataTranslator extends PacketTranslator { @@ -112,7 +110,7 @@ public class JavaChunkDataTranslator extends PacketTranslator blockEntityEntry: chunkData.beds.entrySet()) { + for (Map.Entry blockEntityEntry: chunkData.beds.entrySet()) { ChunkUtils.updateBlock(session, blockEntityEntry.getValue(), blockEntityEntry.getKey()); } chunkData.signs.clear(); From 050098a49883c225d131f270b1f9e286365e31c8 Mon Sep 17 00:00:00 2001 From: DoctorMacc Date: Mon, 6 Apr 2020 16:33:30 -0400 Subject: [PATCH 070/109] Add legal message to BedBlockEntityTranslator.java --- .../entity/BedBlockEntityTranslator.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BedBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BedBlockEntityTranslator.java index 42865918..7522506a 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BedBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BedBlockEntityTranslator.java @@ -1,3 +1,28 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + package org.geysermc.connector.network.translators.block.entity; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; From 6ea0fcabc304c601563a7cc9c904fb5373954b4e Mon Sep 17 00:00:00 2001 From: DoctorMacc Date: Wed, 8 Apr 2020 17:42:36 -0400 Subject: [PATCH 071/109] Sign editing --- .../BedrockBlockEntityDataTranslator.java | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockEntityDataTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockEntityDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockEntityDataTranslator.java new file mode 100644 index 00000000..4aeaafa5 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockEntityDataTranslator.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.bedrock; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; +import com.github.steveice10.mc.protocol.data.message.Message; +import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientUpdateSignPacket; +import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.tag.CompoundTag; +import com.nukkitx.nbt.tag.StringTag; +import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; + +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.network.translators.Translator; +import org.geysermc.connector.network.translators.Translators; +import org.geysermc.connector.network.translators.block.entity.SignBlockEntityTranslator; +import org.geysermc.connector.utils.BlockEntityUtils; +import org.geysermc.connector.utils.MessageUtils; + +import java.util.HashMap; +import java.util.concurrent.TimeUnit; + +@Translator(packet = BlockEntityDataPacket.class) +public class BedrockBlockEntityDataTranslator extends PacketTranslator { + + // In case two people are editing signs at the same time this array holds the temporary messages to be sent + // Position -> Message being held + protected static HashMap lastMessages = new HashMap<>(); + + @Override + public void translate(BlockEntityDataPacket packet, GeyserSession session) { + if (packet.getData() instanceof CompoundTag) { + CompoundTag tag = (CompoundTag) packet.getData(); + if (tag.getString("id").equals("Sign")) { + // This is the reason why this all works - Bedrock sends packets every time you update the sign, Java only wants the final packet + // But Bedrock sends one final packet when you're done editing the sign, which should be equal to the last message since there's no edits + // So if the latest update does not match the last cached update then it's still being edited + Position pos = new Position(tag.getInt("x"), tag.getInt("y"), tag.getInt("z")); + if (!tag.getString("Text").equals(lastMessages.get(pos))) { + lastMessages.put(pos, tag.getString("Text")); + return; + } + // Otherwise the two messages are identical and we can get to work deconstructing + StringBuilder newMessage = new StringBuilder(); + // While Bedrock's sign lines are one string, Java's is an array of each line + // (Initialized all with empty strings because it complains about null) + String[] lines = new String[] {"", "", "", ""}; + int iterator = 0; + // This converts the message into the array'd message Java wants + for (char character : tag.getString("Text").toCharArray()) { + // If we get a return in Bedrock, that signals to use the next line. + if (character == '\n') { + lines[iterator] = newMessage.toString(); + iterator++; + // Bedrock, for whatever reason, can hold a message out of bounds + // We don't care about that so we discard that + if (iterator > lines.length - 1) { + break; + } + newMessage = new StringBuilder(); + } else newMessage.append(character); + } + // Put the final line on since it isn't done in the for loop + if (iterator < lines.length) lines[iterator] = newMessage.toString(); + ClientUpdateSignPacket clientUpdateSignPacket = new ClientUpdateSignPacket(pos, lines); + session.getDownstream().getSession().send(clientUpdateSignPacket); + //TODO (potentionally): originally I was going to update the sign blocks so Bedrock and Java users would match visually + // However Java can still store a lot per-line and visuals are still messed up so that doesn't work + + // We remove the sign position from map to indicate there is no work-in-progress sign + lastMessages.remove(pos); + } + } + + } +} From 962d987274bcb2e80fe6abcd81027eb092bd8f88 Mon Sep 17 00:00:00 2001 From: DoctorMacc Date: Wed, 8 Apr 2020 17:44:34 -0400 Subject: [PATCH 072/109] Remove unused imports --- .../bedrock/BedrockBlockEntityDataTranslator.java | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockEntityDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockEntityDataTranslator.java index 4aeaafa5..ad3a48d1 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockEntityDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockEntityDataTranslator.java @@ -26,24 +26,15 @@ package org.geysermc.connector.network.translators.bedrock; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; -import com.github.steveice10.mc.protocol.data.message.Message; import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientUpdateSignPacket; -import com.nukkitx.math.vector.Vector3i; -import com.nukkitx.nbt.CompoundTagBuilder; import com.nukkitx.nbt.tag.CompoundTag; -import com.nukkitx.nbt.tag.StringTag; import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; - import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.Translator; -import org.geysermc.connector.network.translators.Translators; -import org.geysermc.connector.network.translators.block.entity.SignBlockEntityTranslator; -import org.geysermc.connector.utils.BlockEntityUtils; -import org.geysermc.connector.utils.MessageUtils; import java.util.HashMap; -import java.util.concurrent.TimeUnit; + @Translator(packet = BlockEntityDataPacket.class) public class BedrockBlockEntityDataTranslator extends PacketTranslator { From aff33bd8b3749abe29228936a5db55a04128ef47 Mon Sep 17 00:00:00 2001 From: DoctorMacc Date: Wed, 8 Apr 2020 17:44:51 -0400 Subject: [PATCH 073/109] Whitespace --- .../translators/bedrock/BedrockBlockEntityDataTranslator.java | 1 - 1 file changed, 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockEntityDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockEntityDataTranslator.java index ad3a48d1..3ab4b5ba 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockEntityDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockEntityDataTranslator.java @@ -35,7 +35,6 @@ import org.geysermc.connector.network.translators.Translator; import java.util.HashMap; - @Translator(packet = BlockEntityDataPacket.class) public class BedrockBlockEntityDataTranslator extends PacketTranslator { From a1c0ec6c124a6612e0af1dca9b0289cb8ba718e0 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Wed, 8 Apr 2020 19:14:34 -0400 Subject: [PATCH 074/109] Update copyright --- .../translators/bedrock/BedrockBlockEntityDataTranslator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockEntityDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockEntityDataTranslator.java index 3ab4b5ba..e47b82d1 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockEntityDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockEntityDataTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal From d518d5ef63453de4568769a805bf4f114722fdec Mon Sep 17 00:00:00 2001 From: DoctorMacc Date: Wed, 8 Apr 2020 21:33:07 -0400 Subject: [PATCH 075/109] One More Thing:tm: --- .../bedrock/BedrockBlockEntityDataTranslator.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockEntityDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockEntityDataTranslator.java index 3ab4b5ba..759af4c3 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockEntityDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockEntityDataTranslator.java @@ -34,13 +34,14 @@ import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.Translator; import java.util.HashMap; +import java.util.Map; @Translator(packet = BlockEntityDataPacket.class) public class BedrockBlockEntityDataTranslator extends PacketTranslator { // In case two people are editing signs at the same time this array holds the temporary messages to be sent // Position -> Message being held - protected static HashMap lastMessages = new HashMap<>(); + protected static Map lastMessages = new HashMap<>(); @Override public void translate(BlockEntityDataPacket packet, GeyserSession session) { @@ -79,7 +80,7 @@ public class BedrockBlockEntityDataTranslator extends PacketTranslator Date: Fri, 10 Apr 2020 16:07:36 -0400 Subject: [PATCH 076/109] Fixed --- .../network/translators/Translators.java | 7 +-- .../EndGatewayBlockEntityTranslator.java | 53 +++++++++++++++++++ 2 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EndGatewayBlockEntityTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java b/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java index 0df96107..70a73be3 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java @@ -34,11 +34,7 @@ import com.github.steveice10.mc.protocol.data.game.window.WindowType; import com.nukkitx.protocol.bedrock.data.ContainerType; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.network.translators.block.BlockTranslator; -import org.geysermc.connector.network.translators.block.entity.BannerBlockEntityTranslator; -import org.geysermc.connector.network.translators.block.entity.BlockEntityTranslator; -import org.geysermc.connector.network.translators.block.entity.CampfireBlockEntityTranslator; -import org.geysermc.connector.network.translators.block.entity.EmptyBlockEntityTranslator; -import org.geysermc.connector.network.translators.block.entity.SignBlockEntityTranslator; +import org.geysermc.connector.network.translators.block.entity.*; import org.geysermc.connector.network.translators.inventory.AnvilInventoryTranslator; import org.geysermc.connector.network.translators.inventory.BlockInventoryTranslator; import org.geysermc.connector.network.translators.inventory.BrewingInventoryTranslator; @@ -132,6 +128,7 @@ public class Translators { blockEntityTranslators.put("Sign", new SignBlockEntityTranslator()); blockEntityTranslators.put("Campfire", new CampfireBlockEntityTranslator()); blockEntityTranslators.put("Banner", new BannerBlockEntityTranslator()); + blockEntityTranslators.put("EndGateway", new EndGatewayBlockEntityTranslator()); } private static void registerInventoryTranslators() { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EndGatewayBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EndGatewayBlockEntityTranslator.java new file mode 100644 index 00000000..756664ee --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EndGatewayBlockEntityTranslator.java @@ -0,0 +1,53 @@ +package org.geysermc.connector.network.translators.block.entity; + +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.LongTag; +import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.tag.IntTag; +import com.nukkitx.nbt.tag.Tag; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; + +public class EndGatewayBlockEntityTranslator extends BlockEntityTranslator { + @Override + public List> translateTag(CompoundTag tag) { + System.out.println(tag); + List> tags = new ArrayList<>(); + tags.add(new IntTag("Age", (int) (long) tag.get("Age").getValue())); + // Java sometimes does not provide this tag, but Bedrock crashes if it doesn't exist + // Linked coordinates + List tagsList = new ArrayList<>(); + tagsList.add(new IntTag("", getExitPortalCoordinate(tag, "X"))); + tagsList.add(new IntTag("", getExitPortalCoordinate(tag, "Y"))); + tagsList.add(new IntTag("", getExitPortalCoordinate(tag, "Z"))); + com.nukkitx.nbt.tag.ListTag exitPortal = + new com.nukkitx.nbt.tag.ListTag<>("ExitPortal", com.nukkitx.nbt.tag.IntTag.class, tagsList); + tags.add(exitPortal); + return tags; + } + + @Override + public CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) { + CompoundTag tag = getConstantJavaTag(javaId, x, y, z); + tag.put(new LongTag("Age")); + return tag; + } + + @Override + public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { + System.out.println("Default Bedrock tag being created"); + CompoundTagBuilder tagBuilder = getConstantBedrockTag(bedrockId, x, y, z).toBuilder(); + tagBuilder.listTag("ExitPortal", IntTag.class, new ArrayList<>()); + return tagBuilder.buildRootTag(); + } + + private int getExitPortalCoordinate(CompoundTag tag, String axis) { + if (tag.get("ExitPortal").getValue() != null) { + LinkedHashMap compoundTag = (LinkedHashMap) tag.get("ExitPortal").getValue(); + com.github.steveice10.opennbt.tag.builtin.IntTag intTag = (com.github.steveice10.opennbt.tag.builtin.IntTag) compoundTag.get(axis); + return intTag.getValue(); + } return 0; + } +} From d547b31b38ecafd9fe6e48526922667235fb057c Mon Sep 17 00:00:00 2001 From: DoctorMacc Date: Fri, 10 Apr 2020 16:36:41 -0400 Subject: [PATCH 077/109] Fix first load crashing; fix NPE --- .../block/entity/EndGatewayBlockEntityTranslator.java | 11 +++++++---- .../java/world/JavaChunkDataTranslator.java | 8 ++++++++ .../java/org/geysermc/connector/utils/ChunkUtils.java | 4 ++++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EndGatewayBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EndGatewayBlockEntityTranslator.java index 756664ee..0ed07bf5 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EndGatewayBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EndGatewayBlockEntityTranslator.java @@ -13,7 +13,6 @@ import java.util.List; public class EndGatewayBlockEntityTranslator extends BlockEntityTranslator { @Override public List> translateTag(CompoundTag tag) { - System.out.println(tag); List> tags = new ArrayList<>(); tags.add(new IntTag("Age", (int) (long) tag.get("Age").getValue())); // Java sometimes does not provide this tag, but Bedrock crashes if it doesn't exist @@ -37,14 +36,18 @@ public class EndGatewayBlockEntityTranslator extends BlockEntityTranslator { @Override public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { - System.out.println("Default Bedrock tag being created"); CompoundTagBuilder tagBuilder = getConstantBedrockTag(bedrockId, x, y, z).toBuilder(); - tagBuilder.listTag("ExitPortal", IntTag.class, new ArrayList<>()); + List tagsList = new ArrayList<>(); + tagsList.add(new IntTag("", 0)); + tagsList.add(new IntTag("", 0)); + tagsList.add(new IntTag("", 0)); + tagBuilder.listTag("ExitPortal", IntTag.class, tagsList); return tagBuilder.buildRootTag(); } private int getExitPortalCoordinate(CompoundTag tag, String axis) { - if (tag.get("ExitPortal").getValue() != null) { + // Return 0 if it doesn't exist, otherwise give proper value + if (tag.get("ExitPortal") != null) { LinkedHashMap compoundTag = (LinkedHashMap) tag.get("ExitPortal").getValue(); com.github.steveice10.opennbt.tag.builtin.IntTag intTag = (com.github.steveice10.opennbt.tag.builtin.IntTag) compoundTag.get(axis); return intTag.getValue(); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java index 5d17e0e0..4f6d1bc6 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java @@ -110,10 +110,18 @@ public class JavaChunkDataTranslator extends PacketTranslator blockEntityEntry : chunkData.gateways.object2IntEntrySet()) { + int x = blockEntityEntry.getKey().getInt("x"); + int y = blockEntityEntry.getKey().getInt("y"); + int z = blockEntityEntry.getKey().getInt("z"); + ChunkUtils.updateBlock(session, new BlockState(blockEntityEntry.getIntValue()), new Position(x, y, z)); + } + for (Map.Entry blockEntityEntry: chunkData.beds.entrySet()) { ChunkUtils.updateBlock(session, blockEntityEntry.getValue(), blockEntityEntry.getKey()); } chunkData.signs.clear(); + chunkData.gateways.clear(); chunkData.beds.clear(); } catch (Exception ex) { ex.printStackTrace(); diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java index b7bcb719..c6851770 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -78,6 +78,9 @@ public class ChunkUtils { if (BlockTranslator.getBlockEntityString(blockState) != null && BlockTranslator.getBlockEntityString(blockState).contains("sign[")) { Position pos = new ChunkPosition(column.getX(), column.getZ()).getBlock(x, (chunkY << 4) + y, z); chunkData.signs.put(Translators.getBlockEntityTranslators().get("Sign").getDefaultBedrockTag("Sign", pos.getX(), pos.getY(), pos.getZ()), blockState.getId()); + } else if (BlockTranslator.getBlockEntityString(blockState) != null && BlockTranslator.getBlockEntityString(blockState).contains("end_gateway")) { + Position pos = new ChunkPosition(column.getX(), column.getZ()).getBlock(x, (chunkY << 4) + y, z); + chunkData.gateways.put(Translators.getBlockEntityTranslators().get("EndGateway").getDefaultBedrockTag("EndGateway", pos.getX(), pos.getY(), pos.getZ()), blockState.getId()); } else if (BlockTranslator.getBedColor(blockState) > -1) { Position pos = new ChunkPosition(column.getX(), column.getZ()).getBlock(x, (chunkY << 4) + y, z); // Beds need to be updated separately to add the bed color tag @@ -189,6 +192,7 @@ public class ChunkUtils { public com.nukkitx.nbt.tag.CompoundTag[] blockEntities = new com.nukkitx.nbt.tag.CompoundTag[0]; public Object2IntMap signs = new Object2IntOpenHashMap<>(); + public Object2IntMap gateways = new Object2IntOpenHashMap<>(); public Map beds = new HashMap<>(); } } From f046ef52f1efccad9bf2b11dd55a69a13e92270e Mon Sep 17 00:00:00 2001 From: DoctorMacc Date: Fri, 10 Apr 2020 18:06:35 -0400 Subject: [PATCH 078/109] Add license --- .../EndGatewayBlockEntityTranslator.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EndGatewayBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EndGatewayBlockEntityTranslator.java index 0ed07bf5..f0008cfe 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EndGatewayBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EndGatewayBlockEntityTranslator.java @@ -1,3 +1,28 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + package org.geysermc.connector.network.translators.block.entity; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; From e2e4fb2b3c4c44b52fd0c24d613ace9beb789c34 Mon Sep 17 00:00:00 2001 From: DoctorMacc Date: Fri, 10 Apr 2020 18:11:16 -0400 Subject: [PATCH 079/109] Some final touches --- .../block/entity/EndGatewayBlockEntityTranslator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EndGatewayBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EndGatewayBlockEntityTranslator.java index f0008cfe..e66a0bcd 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EndGatewayBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EndGatewayBlockEntityTranslator.java @@ -43,11 +43,12 @@ public class EndGatewayBlockEntityTranslator extends BlockEntityTranslator { // Java sometimes does not provide this tag, but Bedrock crashes if it doesn't exist // Linked coordinates List tagsList = new ArrayList<>(); + // Yes, the axis letters are capitalized tagsList.add(new IntTag("", getExitPortalCoordinate(tag, "X"))); tagsList.add(new IntTag("", getExitPortalCoordinate(tag, "Y"))); tagsList.add(new IntTag("", getExitPortalCoordinate(tag, "Z"))); com.nukkitx.nbt.tag.ListTag exitPortal = - new com.nukkitx.nbt.tag.ListTag<>("ExitPortal", com.nukkitx.nbt.tag.IntTag.class, tagsList); + new com.nukkitx.nbt.tag.ListTag<>("ExitPortal", IntTag.class, tagsList); tags.add(exitPortal); return tags; } From 2c75415dc87515c32ba4e787d4e8d4b94ad1bb66 Mon Sep 17 00:00:00 2001 From: DoctorMacc Date: Sun, 12 Apr 2020 14:38:47 -0400 Subject: [PATCH 080/109] Update Protocol to 2.5.5-SNAPSHOT --- connector/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connector/pom.xml b/connector/pom.xml index 2cc6139f..0bf64f15 100644 --- a/connector/pom.xml +++ b/connector/pom.xml @@ -39,7 +39,7 @@ com.nukkitx.protocol bedrock-v389 - 2.5.4 + 2.5.5-SNAPSHOT compile From fc988dfd70ea976a285e4d4ddb63f4acb4dca00e Mon Sep 17 00:00:00 2001 From: DoctorMacc Date: Sun, 12 Apr 2020 18:31:58 -0400 Subject: [PATCH 081/109] Implement grindstone --- .../network/translators/Translators.java | 11 +-- .../GrindstoneInventoryTranslator.java | 68 +++++++++++++++++++ 2 files changed, 70 insertions(+), 9 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/GrindstoneInventoryTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java b/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java index 70a73be3..f0098f3c 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java @@ -35,15 +35,7 @@ import com.nukkitx.protocol.bedrock.data.ContainerType; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.network.translators.block.BlockTranslator; import org.geysermc.connector.network.translators.block.entity.*; -import org.geysermc.connector.network.translators.inventory.AnvilInventoryTranslator; -import org.geysermc.connector.network.translators.inventory.BlockInventoryTranslator; -import org.geysermc.connector.network.translators.inventory.BrewingInventoryTranslator; -import org.geysermc.connector.network.translators.inventory.CraftingInventoryTranslator; -import org.geysermc.connector.network.translators.inventory.DoubleChestInventoryTranslator; -import org.geysermc.connector.network.translators.inventory.FurnaceInventoryTranslator; -import org.geysermc.connector.network.translators.inventory.InventoryTranslator; -import org.geysermc.connector.network.translators.inventory.PlayerInventoryTranslator; -import org.geysermc.connector.network.translators.inventory.SingleChestInventoryTranslator; +import org.geysermc.connector.network.translators.inventory.*; import org.geysermc.connector.network.translators.inventory.updater.ContainerInventoryUpdater; import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater; import org.geysermc.connector.network.translators.item.ItemTranslator; @@ -142,6 +134,7 @@ public class Translators { inventoryTranslators.put(WindowType.BREWING_STAND, new BrewingInventoryTranslator()); inventoryTranslators.put(WindowType.ANVIL, new AnvilInventoryTranslator()); inventoryTranslators.put(WindowType.CRAFTING, new CraftingInventoryTranslator()); + inventoryTranslators.put(WindowType.GRINDSTONE, new GrindstoneInventoryTranslator()); //inventoryTranslators.put(WindowType.ENCHANTMENT, new EnchantmentInventoryTranslator()); //TODO InventoryTranslator furnace = new FurnaceInventoryTranslator(); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/GrindstoneInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/GrindstoneInventoryTranslator.java new file mode 100644 index 00000000..174cfbc1 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/GrindstoneInventoryTranslator.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.inventory; + +import com.nukkitx.protocol.bedrock.data.ContainerType; +import com.nukkitx.protocol.bedrock.data.InventoryActionData; +import org.geysermc.connector.network.translators.inventory.updater.CursorInventoryUpdater; + +public class GrindstoneInventoryTranslator extends BlockInventoryTranslator { + + public GrindstoneInventoryTranslator() { + super(3, "minecraft:grindstone[face=floor,facing=north]", ContainerType.GRINDSTONE, new CursorInventoryUpdater()); + } + + @Override + public int bedrockSlotToJava(InventoryActionData action) { + final int slot = super.bedrockSlotToJava(action); + if (action.getSource().getContainerId() == 124) { + switch (slot) { + case 16: + return 0; + case 17: + return 1; + case 50: + return 2; + default: + return slot; + } + } return slot; + } + + @Override + public int javaSlotToBedrock(int slot) { + switch (slot) { + case 0: + return 16; + case 1: + return 17; + case 2: + return 50; + } + return super.javaSlotToBedrock(slot); + } + +} From 08eb99fa9492b455e8286c804b3d31383b50ad2a Mon Sep 17 00:00:00 2001 From: OnlyBMan <27742182+OnlyBMan@users.noreply.github.com> Date: Tue, 14 Apr 2020 18:33:55 -0400 Subject: [PATCH 082/109] Implement skulls and heads --- .../translators/block/BlockTranslator.java | 180 ++++++++++++++++++ .../entity/SkullBlockEntityTranslator.java | 49 +++++ .../java/world/JavaChunkDataTranslator.java | 4 + .../geysermc/connector/utils/ChunkUtils.java | 8 + 4 files changed, 241 insertions(+) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java index 1ffaa3bd..14a821c0 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java @@ -67,6 +67,8 @@ public class BlockTranslator { private static final Map JAVA_ID_TO_BLOCK_ENTITY_MAP = new HashMap<>(); private static final Object2ByteMap BED_COLORS = new Object2ByteOpenHashMap<>(); + private static final Object2ByteMap SKULL_VARIANTS = new Object2ByteOpenHashMap<>(); + private static final Object2ByteMap SKULL_ROTATIONS = new Object2ByteOpenHashMap<>(); public static final Int2DoubleMap JAVA_RUNTIME_ID_TO_HARDNESS = new Int2DoubleOpenHashMap(); public static final Int2BooleanMap JAVA_RUNTIME_ID_TO_CAN_HARVEST_WITH_HAND = new Int2BooleanOpenHashMap(); @@ -147,6 +149,170 @@ public class BlockTranslator { JAVA_ID_TO_BLOCK_ENTITY_MAP.put(javaBlockState, javaId); } + int lastIndex = javaId.length() -1; + byte rotation = 0; + if (javaId.contains("skeleton_skull[")) { + if (javaId.indexOf("=") == lastIndex - 2) { + rotation = Byte.parseByte(javaId.substring(lastIndex -1, lastIndex)); + } + else { + rotation = Byte.parseByte(javaId.substring(lastIndex -2, lastIndex)); + } + SKULL_VARIANTS.put(javaBlockState, (byte) 0); + SKULL_ROTATIONS.put(javaBlockState, rotation); + } + else if (javaId.contains("skeleton_wall")) { + if (javaId.contains("north")) { + rotation = 0; + } + else if (javaId.contains("east")) { + rotation = 4; + } + else if (javaId.contains("south")) { + rotation = 8; + } + else if(javaId.contains("west")) { + rotation = 12; + } + SKULL_VARIANTS.put(javaBlockState, (byte) 0); + SKULL_ROTATIONS.put(javaBlockState, rotation); + } + + if (javaId.contains("wither_skeleton_skull[")) { + if (javaId.indexOf("=") == lastIndex - 2) { + rotation = Byte.parseByte(javaId.substring(lastIndex -1, lastIndex)); + } + else { + rotation = Byte.parseByte(javaId.substring(lastIndex -2, lastIndex)); + } + SKULL_VARIANTS.put(javaBlockState, (byte) 1); + SKULL_ROTATIONS.put(javaBlockState, rotation); + } + else if (javaId.contains("wither_skeleton_wall")) { + if (javaId.contains("north")) { + rotation = 0; + } + else if (javaId.contains("east")) { + rotation = 4; + } + else if (javaId.contains("south")) { + rotation = 8; + } + else if(javaId.contains("west")) { + rotation = 12; + } + SKULL_VARIANTS.put(javaBlockState, (byte) 1); + SKULL_ROTATIONS.put(javaBlockState, rotation); + } + + if (javaId.contains("zombie_head[")) { + if (javaId.indexOf("=") == lastIndex - 2) { + rotation = Byte.parseByte(javaId.substring(lastIndex -1, lastIndex)); + } + else { + rotation = Byte.parseByte(javaId.substring(lastIndex -2, lastIndex)); + } + SKULL_VARIANTS.put(javaBlockState, (byte) 2); + SKULL_ROTATIONS.put(javaBlockState, rotation); + } + else if (javaId.contains("zombie_wall")) { + if (javaId.contains("north")) { + rotation = 0; + } + else if (javaId.contains("east")) { + rotation = 4; + } + else if (javaId.contains("south")) { + rotation = 8; + } + else if(javaId.contains("west")) { + rotation = 12; + } + SKULL_VARIANTS.put(javaBlockState, (byte) 2); + SKULL_ROTATIONS.put(javaBlockState, rotation); + } + + if (javaId.contains("player_head[")) { + if (javaId.indexOf("=") == lastIndex - 2) { + rotation = Byte.parseByte(javaId.substring(lastIndex -1, lastIndex)); + } + else { + rotation = Byte.parseByte(javaId.substring(lastIndex -2, lastIndex)); + } + SKULL_VARIANTS.put(javaBlockState, (byte) 3); + SKULL_ROTATIONS.put(javaBlockState, rotation); + } + else if (javaId.contains("player_wall")) { + if (javaId.contains("north")) { + rotation = 0; + } + else if (javaId.contains("east")) { + rotation = 4; + } + else if (javaId.contains("south")) { + rotation = 8; + } + else if(javaId.contains("west")) { + rotation = 12; + } + SKULL_VARIANTS.put(javaBlockState, (byte) 3); + SKULL_ROTATIONS.put(javaBlockState, rotation); + } + + if (javaId.contains("creeper_head[")) { + if (javaId.indexOf("=") == lastIndex - 2) { + rotation = Byte.parseByte(javaId.substring(lastIndex -1, lastIndex)); + } + else { + rotation = Byte.parseByte(javaId.substring(lastIndex -2, lastIndex)); + } + SKULL_VARIANTS.put(javaBlockState, (byte) 4); + SKULL_ROTATIONS.put(javaBlockState, rotation); + } + else if (javaId.contains("creeper_wall")) { + if (javaId.contains("north")) { + rotation = 0; + } + else if (javaId.contains("east")) { + rotation = 4; + } + else if (javaId.contains("south")) { + rotation = 8; + } + else if(javaId.contains("west")) { + rotation = 12; + } + SKULL_VARIANTS.put(javaBlockState, (byte) 4); + SKULL_ROTATIONS.put(javaBlockState, rotation); + } + + if (javaId.contains("dragon_head[")) { + if (javaId.indexOf("=") == lastIndex - 2) { + rotation = Byte.parseByte(javaId.substring(lastIndex -1, lastIndex)); + } + else { + rotation = Byte.parseByte(javaId.substring(lastIndex -2, lastIndex)); + } + SKULL_VARIANTS.put(javaBlockState, (byte) 5); + SKULL_ROTATIONS.put(javaBlockState, rotation); + } + else if (javaId.contains("dragon_wall")) { + if (javaId.contains("north")) { + rotation = 0; + } + else if (javaId.contains("east")) { + rotation = 4; + } + else if (javaId.contains("south")) { + rotation = 8; + } + else if(javaId.contains("west")) { + rotation = 12; + } + SKULL_VARIANTS.put(javaBlockState, (byte) 5); + SKULL_ROTATIONS.put(javaBlockState, rotation); + } + // If the Java ID is bed, signal that it needs a tag to show color // The color is in the namespace ID in Java Edition but it's a tag in Bedrock. JsonNode bedColor = entry.getValue().get("bed_color"); @@ -268,6 +434,20 @@ public class BlockTranslator { return -1; } + public static byte getSkullVariant(BlockState state) { + if (SKULL_VARIANTS.containsKey(state)) { + return SKULL_VARIANTS.getByte(state); + } + return 0; + } + + public static byte getSkullRotation(BlockState state) { + if (SKULL_ROTATIONS.containsKey(state)) { + return SKULL_ROTATIONS.getByte(state); + } + return 0; + } + public static BlockState getJavaWaterloggedState(int bedrockId) { return BEDROCK_TO_JAVA_BLOCK_MAP.get(1 << 31 | bedrockId); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java new file mode 100644 index 00000000..e4ace6e3 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java @@ -0,0 +1,49 @@ +package org.geysermc.connector.network.translators.block.entity; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; +import com.github.steveice10.mc.protocol.data.message.Message; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.tag.StringTag; +import com.nukkitx.nbt.tag.Tag; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.block.BlockTranslator; +import org.geysermc.connector.utils.BlockEntityUtils; +import org.geysermc.connector.utils.MessageUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +public class SkullBlockEntityTranslator { + + public static void checkForSkullVariant(GeyserSession session, BlockState blockState, Vector3i position) { + byte skullVariant = BlockTranslator.getSkullVariant(blockState); + byte rotation = BlockTranslator.getSkullRotation(blockState); + // If Bed Color is not -1 then it is indeed a bed with a color. + if (skullVariant > 0) { + Position pos = new Position(position.getX(), position.getY(), position.getZ()); + com.nukkitx.nbt.tag.CompoundTag finalSkullTag = getSkullTag(skullVariant, pos, rotation); + // Delay needed, otherwise newly placed beds will not get their color + // Delay is not needed for beds already placed on login + session.getConnector().getGeneralThreadPool().schedule(() -> + BlockEntityUtils.updateBlockEntity(session, finalSkullTag, pos), + 500, + TimeUnit.MILLISECONDS + ); + } + } + + public static com.nukkitx.nbt.tag.CompoundTag getSkullTag(byte skullvariant, Position pos, byte rotation) { + CompoundTagBuilder tagBuilder = CompoundTagBuilder.builder() + .intTag("x", pos.getX()) + .intTag("y", pos.getY()) + .intTag("z", pos.getZ()) + .stringTag("id", "Skull") + .floatTag("Rotation", rotation * 22.5f); + tagBuilder.byteTag("SkullType", skullvariant); + return tagBuilder.buildRootTag(); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java index 4f6d1bc6..9309ca75 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java @@ -120,9 +120,13 @@ public class JavaChunkDataTranslator extends PacketTranslator blockEntityEntry: chunkData.beds.entrySet()) { ChunkUtils.updateBlock(session, blockEntityEntry.getValue(), blockEntityEntry.getKey()); } + for (Map.Entry blockEntityEntry: chunkData.skulls.entrySet()) { + ChunkUtils.updateBlock(session, blockEntityEntry.getValue(), blockEntityEntry.getKey()); + } chunkData.signs.clear(); chunkData.gateways.clear(); chunkData.beds.clear(); + chunkData.skulls.clear(); } catch (Exception ex) { ex.printStackTrace(); } diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java index c6851770..737dfd73 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -42,6 +42,7 @@ import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.block.entity.BlockEntityTranslator; +import org.geysermc.connector.network.translators.block.entity.SkullBlockEntityTranslator; import org.geysermc.connector.world.chunk.ChunkPosition; import org.geysermc.connector.network.translators.Translators; import org.geysermc.connector.network.translators.block.BlockTranslator; @@ -86,6 +87,11 @@ public class ChunkUtils { // Beds need to be updated separately to add the bed color tag // Previously this was done by matching block state but this resulted in only one bed per color+orientation showing chunkData.beds.put(pos, blockState); + } else if (BlockTranslator.getSkullVariant(blockState) > 0) { + Position pos = new ChunkPosition(column.getX(), column.getZ()).getBlock(x, (chunkY << 4) + y, z); + // Beds need to be updated separately to add the bed color tag + // Previously this was done by matching block state but this resulted in only one bed per color+orientation showing + chunkData.skulls.put(pos, blockState); } else { section.getBlockStorageArray()[0].setFullBlock(ChunkSection.blockPosition(x, y, z), id); } @@ -160,6 +166,7 @@ public class ChunkUtils { // Since Java stores bed colors as part of the namespaced ID and Bedrock stores it as a tag // This is the only place I could find that interacts with the Java block state and block updates BedBlockEntityTranslator.checkForBedColor(session, blockState, position); + SkullBlockEntityTranslator.checkForSkullVariant(session, blockState, position); } public static void sendEmptyChunks(GeyserSession session, Vector3i position, int radius, boolean forceUpdate) { @@ -194,5 +201,6 @@ public class ChunkUtils { public Object2IntMap signs = new Object2IntOpenHashMap<>(); public Object2IntMap gateways = new Object2IntOpenHashMap<>(); public Map beds = new HashMap<>(); + public Map skulls = new HashMap<>(); } } From 3972cc7f873358958fdfb632ae6b9bcb70f64e9e Mon Sep 17 00:00:00 2001 From: OnlyBMan <27742182+OnlyBMan@users.noreply.github.com> Date: Tue, 14 Apr 2020 18:40:05 -0400 Subject: [PATCH 083/109] Fix comments --- .../block/entity/SkullBlockEntityTranslator.java | 7 +++---- .../main/java/org/geysermc/connector/utils/ChunkUtils.java | 3 +-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java index e4ace6e3..e7fd3a3d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java @@ -22,12 +22,11 @@ public class SkullBlockEntityTranslator { public static void checkForSkullVariant(GeyserSession session, BlockState blockState, Vector3i position) { byte skullVariant = BlockTranslator.getSkullVariant(blockState); byte rotation = BlockTranslator.getSkullRotation(blockState); - // If Bed Color is not -1 then it is indeed a bed with a color. - if (skullVariant > 0) { + if (skullVariant > -1) { Position pos = new Position(position.getX(), position.getY(), position.getZ()); com.nukkitx.nbt.tag.CompoundTag finalSkullTag = getSkullTag(skullVariant, pos, rotation); - // Delay needed, otherwise newly placed beds will not get their color - // Delay is not needed for beds already placed on login + // Delay needed, otherwise newly placed skulls will not appear + // Delay is not needed for skulls already placed on login session.getConnector().getGeneralThreadPool().schedule(() -> BlockEntityUtils.updateBlockEntity(session, finalSkullTag, pos), 500, diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java index 737dfd73..c75664b8 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -89,8 +89,7 @@ public class ChunkUtils { chunkData.beds.put(pos, blockState); } else if (BlockTranslator.getSkullVariant(blockState) > 0) { Position pos = new ChunkPosition(column.getX(), column.getZ()).getBlock(x, (chunkY << 4) + y, z); - // Beds need to be updated separately to add the bed color tag - // Previously this was done by matching block state but this resulted in only one bed per color+orientation showing + //Doing the same stuff as beds chunkData.skulls.put(pos, blockState); } else { section.getBlockStorageArray()[0].setFullBlock(ChunkSection.blockPosition(x, y, z), id); From 87e372ce217c2b595f03503a8cc74512e11db480 Mon Sep 17 00:00:00 2001 From: OnlyBMan <27742182+OnlyBMan@users.noreply.github.com> Date: Tue, 14 Apr 2020 19:34:11 -0400 Subject: [PATCH 084/109] Put everything into bedrock mapping --- .../translators/block/BlockTranslator.java | 165 +----------------- 1 file changed, 6 insertions(+), 159 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java index 14a821c0..a495a822 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java @@ -149,168 +149,15 @@ public class BlockTranslator { JAVA_ID_TO_BLOCK_ENTITY_MAP.put(javaBlockState, javaId); } - int lastIndex = javaId.length() -1; - byte rotation = 0; - if (javaId.contains("skeleton_skull[")) { - if (javaId.indexOf("=") == lastIndex - 2) { - rotation = Byte.parseByte(javaId.substring(lastIndex -1, lastIndex)); - } - else { - rotation = Byte.parseByte(javaId.substring(lastIndex -2, lastIndex)); - } - SKULL_VARIANTS.put(javaBlockState, (byte) 0); - SKULL_ROTATIONS.put(javaBlockState, rotation); - } - else if (javaId.contains("skeleton_wall")) { - if (javaId.contains("north")) { - rotation = 0; - } - else if (javaId.contains("east")) { - rotation = 4; - } - else if (javaId.contains("south")) { - rotation = 8; - } - else if(javaId.contains("west")) { - rotation = 12; - } - SKULL_VARIANTS.put(javaBlockState, (byte) 0); - SKULL_ROTATIONS.put(javaBlockState, rotation); - } - if (javaId.contains("wither_skeleton_skull[")) { - if (javaId.indexOf("=") == lastIndex - 2) { - rotation = Byte.parseByte(javaId.substring(lastIndex -1, lastIndex)); + JsonNode skullVariation = entry.getValue().get("variation"); + if(skullVariation != null) { + SKULL_VARIANTS.put(javaBlockState, (byte) skullVariation.intValue()); } - else { - rotation = Byte.parseByte(javaId.substring(lastIndex -2, lastIndex)); - } - SKULL_VARIANTS.put(javaBlockState, (byte) 1); - SKULL_ROTATIONS.put(javaBlockState, rotation); - } - else if (javaId.contains("wither_skeleton_wall")) { - if (javaId.contains("north")) { - rotation = 0; - } - else if (javaId.contains("east")) { - rotation = 4; - } - else if (javaId.contains("south")) { - rotation = 8; - } - else if(javaId.contains("west")) { - rotation = 12; - } - SKULL_VARIANTS.put(javaBlockState, (byte) 1); - SKULL_ROTATIONS.put(javaBlockState, rotation); - } - if (javaId.contains("zombie_head[")) { - if (javaId.indexOf("=") == lastIndex - 2) { - rotation = Byte.parseByte(javaId.substring(lastIndex -1, lastIndex)); - } - else { - rotation = Byte.parseByte(javaId.substring(lastIndex -2, lastIndex)); - } - SKULL_VARIANTS.put(javaBlockState, (byte) 2); - SKULL_ROTATIONS.put(javaBlockState, rotation); - } - else if (javaId.contains("zombie_wall")) { - if (javaId.contains("north")) { - rotation = 0; - } - else if (javaId.contains("east")) { - rotation = 4; - } - else if (javaId.contains("south")) { - rotation = 8; - } - else if(javaId.contains("west")) { - rotation = 12; - } - SKULL_VARIANTS.put(javaBlockState, (byte) 2); - SKULL_ROTATIONS.put(javaBlockState, rotation); - } - - if (javaId.contains("player_head[")) { - if (javaId.indexOf("=") == lastIndex - 2) { - rotation = Byte.parseByte(javaId.substring(lastIndex -1, lastIndex)); - } - else { - rotation = Byte.parseByte(javaId.substring(lastIndex -2, lastIndex)); - } - SKULL_VARIANTS.put(javaBlockState, (byte) 3); - SKULL_ROTATIONS.put(javaBlockState, rotation); - } - else if (javaId.contains("player_wall")) { - if (javaId.contains("north")) { - rotation = 0; - } - else if (javaId.contains("east")) { - rotation = 4; - } - else if (javaId.contains("south")) { - rotation = 8; - } - else if(javaId.contains("west")) { - rotation = 12; - } - SKULL_VARIANTS.put(javaBlockState, (byte) 3); - SKULL_ROTATIONS.put(javaBlockState, rotation); - } - - if (javaId.contains("creeper_head[")) { - if (javaId.indexOf("=") == lastIndex - 2) { - rotation = Byte.parseByte(javaId.substring(lastIndex -1, lastIndex)); - } - else { - rotation = Byte.parseByte(javaId.substring(lastIndex -2, lastIndex)); - } - SKULL_VARIANTS.put(javaBlockState, (byte) 4); - SKULL_ROTATIONS.put(javaBlockState, rotation); - } - else if (javaId.contains("creeper_wall")) { - if (javaId.contains("north")) { - rotation = 0; - } - else if (javaId.contains("east")) { - rotation = 4; - } - else if (javaId.contains("south")) { - rotation = 8; - } - else if(javaId.contains("west")) { - rotation = 12; - } - SKULL_VARIANTS.put(javaBlockState, (byte) 4); - SKULL_ROTATIONS.put(javaBlockState, rotation); - } - - if (javaId.contains("dragon_head[")) { - if (javaId.indexOf("=") == lastIndex - 2) { - rotation = Byte.parseByte(javaId.substring(lastIndex -1, lastIndex)); - } - else { - rotation = Byte.parseByte(javaId.substring(lastIndex -2, lastIndex)); - } - SKULL_VARIANTS.put(javaBlockState, (byte) 5); - SKULL_ROTATIONS.put(javaBlockState, rotation); - } - else if (javaId.contains("dragon_wall")) { - if (javaId.contains("north")) { - rotation = 0; - } - else if (javaId.contains("east")) { - rotation = 4; - } - else if (javaId.contains("south")) { - rotation = 8; - } - else if(javaId.contains("west")) { - rotation = 12; - } - SKULL_VARIANTS.put(javaBlockState, (byte) 5); - SKULL_ROTATIONS.put(javaBlockState, rotation); + JsonNode skullRotation = entry.getValue().get("skull_rotation"); + if (skullRotation != null) { + SKULL_ROTATIONS.put(javaBlockState, (byte) skullRotation.intValue()); } // If the Java ID is bed, signal that it needs a tag to show color From 9bd1c0fc702bb4f2b0fbdcfb2b6a6123c78a27da Mon Sep 17 00:00:00 2001 From: OnlyBMan <27742182+OnlyBMan@users.noreply.github.com> Date: Tue, 14 Apr 2020 20:08:48 -0400 Subject: [PATCH 085/109] Cleanup some code --- .../network/translators/block/BlockTranslator.java | 10 +++++----- .../block/entity/SkullBlockEntityTranslator.java | 12 +++--------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java index a495a822..2a6b3c98 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java @@ -151,13 +151,13 @@ public class BlockTranslator { JsonNode skullVariation = entry.getValue().get("variation"); - if(skullVariation != null) { - SKULL_VARIANTS.put(javaBlockState, (byte) skullVariation.intValue()); - } + if(skullVariation != null) { + SKULL_VARIANTS.put(javaBlockState, (byte) skullVariation.intValue()); + } JsonNode skullRotation = entry.getValue().get("skull_rotation"); - if (skullRotation != null) { - SKULL_ROTATIONS.put(javaBlockState, (byte) skullRotation.intValue()); + if (skullRotation != null) { + SKULL_ROTATIONS.put(javaBlockState, (byte) skullRotation.intValue()); } // If the Java ID is bed, signal that it needs a tag to show color diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java index e7fd3a3d..67bcdddd 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java @@ -2,19 +2,13 @@ package org.geysermc.connector.network.translators.block.entity; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; -import com.github.steveice10.mc.protocol.data.message.Message; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.nukkitx.math.vector.Vector3i; import com.nukkitx.nbt.CompoundTagBuilder; -import com.nukkitx.nbt.tag.StringTag; -import com.nukkitx.nbt.tag.Tag; +import com.nukkitx.nbt.tag.CompoundTag; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.block.BlockTranslator; import org.geysermc.connector.utils.BlockEntityUtils; -import org.geysermc.connector.utils.MessageUtils; -import java.util.ArrayList; -import java.util.List; import java.util.concurrent.TimeUnit; public class SkullBlockEntityTranslator { @@ -24,7 +18,7 @@ public class SkullBlockEntityTranslator { byte rotation = BlockTranslator.getSkullRotation(blockState); if (skullVariant > -1) { Position pos = new Position(position.getX(), position.getY(), position.getZ()); - com.nukkitx.nbt.tag.CompoundTag finalSkullTag = getSkullTag(skullVariant, pos, rotation); + CompoundTag finalSkullTag = getSkullTag(skullVariant, pos, rotation); // Delay needed, otherwise newly placed skulls will not appear // Delay is not needed for skulls already placed on login session.getConnector().getGeneralThreadPool().schedule(() -> @@ -35,7 +29,7 @@ public class SkullBlockEntityTranslator { } } - public static com.nukkitx.nbt.tag.CompoundTag getSkullTag(byte skullvariant, Position pos, byte rotation) { + public static CompoundTag getSkullTag(byte skullvariant, Position pos, byte rotation) { CompoundTagBuilder tagBuilder = CompoundTagBuilder.builder() .intTag("x", pos.getX()) .intTag("y", pos.getY()) From 0152107a066fc9977cb512574dfc31577a99c7df Mon Sep 17 00:00:00 2001 From: Marco Date: Wed, 15 Apr 2020 13:13:46 +0200 Subject: [PATCH 086/109] Send rename item packet on update slot --- .../inventory/AnvilInventoryTranslator.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java index 60700ba2..8804f1e0 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java @@ -25,7 +25,10 @@ package org.geysermc.connector.network.translators.inventory; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.message.Message; import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientRenameItemPacket; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.nukkitx.protocol.bedrock.data.ContainerId; import com.nukkitx.protocol.bedrock.data.ContainerType; import com.nukkitx.protocol.bedrock.data.InventoryActionData; @@ -114,4 +117,30 @@ public class AnvilInventoryTranslator extends BlockInventoryTranslator { super.translateActions(session, inventory, actions); } + + @Override + public void updateSlot(GeyserSession session, Inventory inventory, int slot) { + if(slot >= 0 && slot <= 2){ + ItemStack item = inventory.getItem(slot); + if(item != null){ + String rename; + CompoundTag tag = item.getNbt(); + if (tag != null) { + CompoundTag displayTag = tag.get("display"); + if(displayTag != null){ + String itemName = displayTag.get("Name").getValue().toString(); + Message message = Message.fromString(itemName); + rename = message.getText(); + } else { + rename = ""; + } + } else { + rename = ""; + } + ClientRenameItemPacket renameItemPacket = new ClientRenameItemPacket(rename); + session.getDownstream().getSession().send(renameItemPacket); + } + } + super.updateSlot(session, inventory, slot); + } } From 60b65e4be6b45d3a7f5e79f93eef229be912844f Mon Sep 17 00:00:00 2001 From: OnlyBMan <27742182+OnlyBMan@users.noreply.github.com> Date: Wed, 15 Apr 2020 10:11:32 -0400 Subject: [PATCH 087/109] Add copyright notice --- .../entity/SkullBlockEntityTranslator.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java index 67bcdddd..0d792288 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java @@ -1,3 +1,28 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + package org.geysermc.connector.network.translators.block.entity; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; From d7b8f088990fcfdc9748eadbce47766b21fb6aaa Mon Sep 17 00:00:00 2001 From: DoctorMacc Date: Wed, 15 Apr 2020 15:24:57 -0400 Subject: [PATCH 088/109] Fix piston/sticky piston (among others) not being able to be retrieved in creative --- .../connector/network/translators/item/ItemTranslator.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java index 8ca95159..0bcbf4b7 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java @@ -118,6 +118,13 @@ public class ItemTranslator { return itemEntry; } } + // If item find was unsuccessful first time, we try again while ignoring damage + // Fixes piston, sticky pistons, dispensers and droppers turning into air from creative inventory + for (ItemEntry itemEntry : Toolbox.ITEM_ENTRIES.values()) { + if (itemEntry.getBedrockId() == data.getId()) { + return itemEntry; + } + } GeyserConnector.getInstance().getLogger().debug("Missing mapping for bedrock item " + data.getId() + ":" + data.getDamage()); return ItemEntry.AIR; From 0a9470acb8b3f028438cbc8b895ac325cb9e6ab7 Mon Sep 17 00:00:00 2001 From: Marco Date: Wed, 15 Apr 2020 21:37:12 +0200 Subject: [PATCH 089/109] formatting code --- .../translators/inventory/AnvilInventoryTranslator.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java index 8804f1e0..8df72d36 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java @@ -120,14 +120,14 @@ public class AnvilInventoryTranslator extends BlockInventoryTranslator { @Override public void updateSlot(GeyserSession session, Inventory inventory, int slot) { - if(slot >= 0 && slot <= 2){ + if (slot >= 0 && slot <= 2) { ItemStack item = inventory.getItem(slot); - if(item != null){ + if (item != null) { String rename; CompoundTag tag = item.getNbt(); if (tag != null) { CompoundTag displayTag = tag.get("display"); - if(displayTag != null){ + if (displayTag != null) { String itemName = displayTag.get("Name").getValue().toString(); Message message = Message.fromString(itemName); rename = message.getText(); From e8a441d667ff95cb892dace1bf89231191e0e2c1 Mon Sep 17 00:00:00 2001 From: DoctorMacc Date: Wed, 15 Apr 2020 15:37:53 -0400 Subject: [PATCH 090/109] Update various copyright dates --- .../main/java/org/geysermc/connector/inventory/Inventory.java | 2 +- .../java/org/geysermc/connector/inventory/PlayerInventory.java | 2 +- .../translators/bedrock/BedrockContainerCloseTranslator.java | 2 +- .../translators/block/entity/BannerBlockEntityTranslator.java | 2 +- .../network/translators/block/entity/BlockEntityTranslator.java | 2 +- .../translators/block/entity/CampfireBlockEntityTranslator.java | 2 +- .../block/entity/ContainerBlockEntityTranslator.java | 2 +- .../translators/block/entity/EmptyBlockEntityTranslator.java | 2 +- .../translators/block/entity/SignBlockEntityTranslator.java | 2 +- .../translators/java/world/JavaBlockValueTranslator.java | 2 +- .../translators/java/world/JavaUpdateTileEntityTranslator.java | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java b/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java index 24ec4a3c..539fe1e2 100644 --- a/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java +++ b/connector/src/main/java/org/geysermc/connector/inventory/Inventory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java b/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java index 52fb786b..432ca827 100644 --- a/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java +++ b/connector/src/main/java/org/geysermc/connector/inventory/PlayerInventory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockContainerCloseTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockContainerCloseTranslator.java index 0bcf6cd1..8d036bfa 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockContainerCloseTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockContainerCloseTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BannerBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BannerBlockEntityTranslator.java index d0d43107..cf868fa3 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BannerBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BannerBlockEntityTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java index 07962089..d7683c4a 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/CampfireBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/CampfireBlockEntityTranslator.java index 962a9f4f..ead43b06 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/CampfireBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/CampfireBlockEntityTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ContainerBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ContainerBlockEntityTranslator.java index 6d838457..7eb3b1a7 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ContainerBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ContainerBlockEntityTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java index 16bc4d7a..a523eab2 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java index 3d9a4a7a..658f665b 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockValueTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockValueTranslator.java index 0721ea64..f4a4d9ef 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockValueTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockValueTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java index 7fa42d90..e6b5a335 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal From 80a7f3a57889f22671f78b20568e174b3fcc5049 Mon Sep 17 00:00:00 2001 From: OnlyBMan <27742182+OnlyBMan@users.noreply.github.com> Date: Wed, 15 Apr 2020 15:38:17 -0400 Subject: [PATCH 091/109] It's not 2019 anymore? --- .../translators/block/entity/SkullBlockEntityTranslator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java index 0d792288..12526d8e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 GeyserMC. http://geysermc.org + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal From 0a5312fff2493cc02080146876a82759dd6b8d37 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Wed, 15 Apr 2020 15:02:12 -0500 Subject: [PATCH 092/109] Update mappings submodule --- connector/src/main/resources/mappings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connector/src/main/resources/mappings b/connector/src/main/resources/mappings index efc9db6b..a6a790d9 160000 --- a/connector/src/main/resources/mappings +++ b/connector/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit efc9db6b7d51bdf145230933ac23b321ac1c132d +Subproject commit a6a790d944eb153c93d0c414813d8a0880fd5d26 From 03f8074619f99584cf4a631c610839b3bc76f4cd Mon Sep 17 00:00:00 2001 From: rtm516 Date: Fri, 17 Apr 2020 17:38:18 +0100 Subject: [PATCH 093/109] Update Protocol to v390 --- connector/pom.xml | 2 +- .../java/org/geysermc/connector/GeyserConnector.java | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/connector/pom.xml b/connector/pom.xml index 0bf64f15..d8c23210 100644 --- a/connector/pom.xml +++ b/connector/pom.xml @@ -38,7 +38,7 @@ com.nukkitx.protocol - bedrock-v389 + bedrock-v390 2.5.5-SNAPSHOT compile diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java index 35f9085d..81f3ea53 100644 --- a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java +++ b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java @@ -27,11 +27,10 @@ package org.geysermc.connector; import com.nukkitx.protocol.bedrock.BedrockPacketCodec; import com.nukkitx.protocol.bedrock.BedrockServer; -import com.nukkitx.protocol.bedrock.v389.Bedrock_v389; - +import com.nukkitx.protocol.bedrock.v390.Bedrock_v390; import lombok.Getter; - import org.geysermc.common.AuthType; +import org.geysermc.common.IGeyserConfiguration; import org.geysermc.common.PlatformType; import org.geysermc.common.bootstrap.IGeyserBootstrap; import org.geysermc.common.logger.IGeyserLogger; @@ -43,14 +42,12 @@ import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.Translators; import org.geysermc.connector.thread.PingPassthroughThread; import org.geysermc.connector.utils.Toolbox; -import org.geysermc.common.IGeyserConfiguration; import java.net.InetSocketAddress; import java.text.DecimalFormat; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CompletableFuture; -import java.util.UUID; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -58,7 +55,7 @@ import java.util.concurrent.TimeUnit; @Getter public class GeyserConnector { - public static final BedrockPacketCodec BEDROCK_PACKET_CODEC = Bedrock_v389.V389_CODEC; + public static final BedrockPacketCodec BEDROCK_PACKET_CODEC = Bedrock_v390.V390_CODEC; public static final String NAME = "Geyser"; public static final String VERSION = "1.0-SNAPSHOT"; From 6880507469db7a79541810769037f05c626bd1b8 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Sat, 18 Apr 2020 17:50:14 +0100 Subject: [PATCH 094/109] Fix all block entities being updated as Skulls --- .../connector/network/translators/block/BlockTranslator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java index 2a6b3c98..d48b9a30 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java @@ -285,14 +285,14 @@ public class BlockTranslator { if (SKULL_VARIANTS.containsKey(state)) { return SKULL_VARIANTS.getByte(state); } - return 0; + return -1; } public static byte getSkullRotation(BlockState state) { if (SKULL_ROTATIONS.containsKey(state)) { return SKULL_ROTATIONS.getByte(state); } - return 0; + return -1; } public static BlockState getJavaWaterloggedState(int bedrockId) { From 46989fb6b5ab68b158f4d9da010016560f5273d6 Mon Sep 17 00:00:00 2001 From: Marco Date: Sun, 19 Apr 2020 10:57:37 +0200 Subject: [PATCH 095/109] Reset wolf color, if not tamed Fix baby metadata --- .../connector/entity/living/AgeableEntity.java | 6 ++---- .../entity/living/animal/tameable/WolfEntity.java | 14 +++++++++++++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/AgeableEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/AgeableEntity.java index a9c60e45..f205c060 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/AgeableEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/AgeableEntity.java @@ -43,10 +43,8 @@ public class AgeableEntity extends CreatureEntity { public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { if (entityMetadata.getId() == 15) { boolean isBaby = (boolean) entityMetadata.getValue(); - if (isBaby) { - metadata.put(EntityData.SCALE, .55f); - metadata.getFlags().setFlag(EntityFlag.BABY, true); - } + metadata.put(EntityData.SCALE, isBaby ? .55f : 1f); + metadata.getFlags().setFlag(EntityFlag.BABY, isBaby); } super.updateBedrockMetadata(entityMetadata, session); diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/WolfEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/WolfEntity.java index 0ac49d55..fafb0d21 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/WolfEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/WolfEntity.java @@ -44,9 +44,21 @@ public class WolfEntity extends TameableEntity { if (entityMetadata.getId() == 18) { metadata.getFlags().setFlag(EntityFlag.INTERESTED, (boolean) entityMetadata.getValue()); } + + //Reset wolf color + if (entityMetadata.getId() == 16) { + byte xd = (byte) entityMetadata.getValue(); + boolean angry = (xd & 0x02) == 0x02; + boolean tamed = (xd & 0x04) == 0x04; + if (angry || !tamed) { + metadata.put(EntityData.COLOR, (byte) 0); + } + } + // Wolf collar color // Relies on EntityData.OWNER_EID being set in TameableEntity.java - if (entityMetadata.getId() == 19) { + boolean tamed = !metadata.getFlags().getFlag(EntityFlag.ANGRY) && metadata.getFlags().getFlag(EntityFlag.TAMED); + if (entityMetadata.getId() == 19 && tamed) { metadata.put(EntityData.COLOR, (byte) (int) entityMetadata.getValue()); } super.updateBedrockMetadata(entityMetadata, session); From 36b549be39aba017daf363322b23d6cc05f8a30a Mon Sep 17 00:00:00 2001 From: Marco Date: Sun, 19 Apr 2020 11:06:11 +0200 Subject: [PATCH 096/109] Reset wolf color --- .../connector/entity/living/animal/tameable/WolfEntity.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/WolfEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/WolfEntity.java index fafb0d21..118262dc 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/WolfEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/WolfEntity.java @@ -49,16 +49,14 @@ public class WolfEntity extends TameableEntity { if (entityMetadata.getId() == 16) { byte xd = (byte) entityMetadata.getValue(); boolean angry = (xd & 0x02) == 0x02; - boolean tamed = (xd & 0x04) == 0x04; - if (angry || !tamed) { + if (angry) { metadata.put(EntityData.COLOR, (byte) 0); } } // Wolf collar color // Relies on EntityData.OWNER_EID being set in TameableEntity.java - boolean tamed = !metadata.getFlags().getFlag(EntityFlag.ANGRY) && metadata.getFlags().getFlag(EntityFlag.TAMED); - if (entityMetadata.getId() == 19 && tamed) { + if (entityMetadata.getId() == 19 && !metadata.getFlags().getFlag(EntityFlag.ANGRY)) { metadata.put(EntityData.COLOR, (byte) (int) entityMetadata.getValue()); } super.updateBedrockMetadata(entityMetadata, session); From 60abdbac3c6786a186410bc1a2f298ac83ad57b6 Mon Sep 17 00:00:00 2001 From: Marco Date: Sun, 19 Apr 2020 11:17:40 +0200 Subject: [PATCH 097/109] Fix NullPointerException with invalid scoreboard teams --- .../java/scoreboard/JavaTeamTranslator.java | 35 +++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/scoreboard/JavaTeamTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/scoreboard/JavaTeamTranslator.java index c9d1ccfe..d3bc6b4e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/scoreboard/JavaTeamTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/scoreboard/JavaTeamTranslator.java @@ -33,6 +33,7 @@ import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.Translator; import org.geysermc.connector.scoreboard.Scoreboard; +import org.geysermc.connector.scoreboard.Team; import org.geysermc.connector.scoreboard.UpdateType; import org.geysermc.connector.utils.MessageUtils; @@ -45,9 +46,10 @@ public class JavaTeamTranslator extends PacketTranslator { @Override public void translate(ServerTeamPacket packet, GeyserSession session) { - GeyserConnector.getInstance().getLogger().debug("Team packet " + packet.getTeamName() + " " + packet.getAction()+" "+ Arrays.toString(packet.getPlayers())); + GeyserConnector.getInstance().getLogger().debug("Team packet " + packet.getTeamName() + " " + packet.getAction() + " " + Arrays.toString(packet.getPlayers())); Scoreboard scoreboard = session.getScoreboardCache().getScoreboard(); + Team team = scoreboard.getTeam(packet.getTeamName()); switch (packet.getAction()) { case CREATE: scoreboard.registerNewTeam(packet.getTeamName(), toPlayerSet(packet.getPlayers())) @@ -57,22 +59,33 @@ public class JavaTeamTranslator extends PacketTranslator { .setSuffix(MessageUtils.getBedrockMessage(packet.getSuffix())); break; case UPDATE: - scoreboard.getTeam(packet.getTeamName()) - .setName(MessageUtils.getBedrockMessage(packet.getDisplayName())) - .setColor(packet.getColor()) - .setPrefix(MessageUtils.getBedrockMessage(packet.getPrefix())) - .setSuffix(MessageUtils.getBedrockMessage(packet.getSuffix())) - .setUpdateType(UpdateType.UPDATE); + if (team != null) { + team.setName(MessageUtils.getBedrockMessage(packet.getDisplayName())) + .setColor(packet.getColor()) + .setPrefix(MessageUtils.getBedrockMessage(packet.getPrefix())) + .setSuffix(MessageUtils.getBedrockMessage(packet.getSuffix())) + .setUpdateType(UpdateType.UPDATE); + } else { + GeyserConnector.getInstance().getLogger().error("Error while translating Team Packet " + packet.getAction() + "! Scoreboard Team " + packet.getTeamName() + " is not registered."); + } break; case ADD_PLAYER: - scoreboard.getTeam(packet.getTeamName()).addEntities(packet.getPlayers()); + if(team != null){ + team.addEntities(packet.getPlayers()); + } else { + GeyserConnector.getInstance().getLogger().error("Error while translating Team Packet " + packet.getAction() + "! Scoreboard Team " + packet.getTeamName() + " is not registered."); + } break; case REMOVE_PLAYER: - scoreboard.getTeam(packet.getTeamName()).removeEntities(packet.getPlayers()); + if(team != null){ + team.removeEntities(packet.getPlayers()); + } else { + GeyserConnector.getInstance().getLogger().error("Error while translating Team Packet " + packet.getAction() + "! Scoreboard Team " + packet.getTeamName() + " is not registered."); + } break; case REMOVE: - scoreboard.removeTeam(packet.getTeamName()); - break; + scoreboard.removeTeam(packet.getTeamName()); + break; } scoreboard.onUpdate(); } From bab2b4a420ff71c32395feda775a3a6655e0073c Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sun, 19 Apr 2020 18:08:14 -0500 Subject: [PATCH 098/109] Pull command descriptions from Bukkit and Sponge versions when listing commands This allows the description of the commands to display when listing the commands in bedrock by tab-completing. This is currently only available on Sponge and Bukkit versions as there is no support in BungeeCord and Velocity to get these values. This data is also not sent in any packet, so we cannot retrieve that from standalone either. --- .../platform/bukkit/GeyserBukkitPlugin.java | 11 ++++ .../command/GeyserBukkitCommandExecutor.java | 2 +- .../command/GeyserBukkitCommandManager.java | 64 +++++++++++++++++++ .../bungeecord/GeyserBungeePlugin.java | 10 +++ .../command/GeyserBungeeCommandExecutor.java | 2 +- .../command/GeyserBungeeCommandManager.java | 41 ++++++++++++ .../platform/sponge/GeyserSpongePlugin.java | 10 +++ .../command/GeyserSpongeCommandExecutor.java | 2 +- .../command/GeyserSpongeCommandManager.java | 48 ++++++++++++++ .../platform/standalone/GeyserBootstrap.java | 13 +++- .../command/GeyserCommandManager.java | 41 ++++++++++++ .../standalone/console/GeyserLogger.java | 2 +- .../velocity/GeyserVelocityPlugin.java | 8 +++ .../GeyserVelocityCommandExecutor.java | 2 +- .../command/GeyserVelocityCommandManager.java | 41 ++++++++++++ .../common/bootstrap/IGeyserBootstrap.java | 3 + .../common/command/ICommandManager.java | 31 +++++++++ .../geysermc/connector/GeyserConnector.java | 13 ++-- ...serCommandMap.java => CommandManager.java} | 5 +- .../command/defaults/HelpCommand.java | 4 +- .../BedrockCommandRequestTranslator.java | 8 +-- .../JavaServerDeclareCommandsTranslator.java | 2 +- 22 files changed, 340 insertions(+), 23 deletions(-) create mode 100644 bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/GeyserBukkitCommandManager.java create mode 100644 bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/command/GeyserBungeeCommandManager.java create mode 100644 bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/command/GeyserSpongeCommandManager.java create mode 100644 bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/command/GeyserCommandManager.java create mode 100644 bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/command/GeyserVelocityCommandManager.java create mode 100644 common/src/main/java/org/geysermc/common/command/ICommandManager.java rename connector/src/main/java/org/geysermc/connector/command/{GeyserCommandMap.java => CommandManager.java} (95%) diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java index 8b0883ef..c2662695 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java @@ -27,14 +27,18 @@ package org.geysermc.platform.bukkit; import org.bukkit.plugin.java.JavaPlugin; import org.geysermc.common.PlatformType; +import org.geysermc.common.command.ICommandManager; import org.geysermc.connector.GeyserConnector; import org.geysermc.common.bootstrap.IGeyserBootstrap; +import org.geysermc.connector.command.CommandManager; import org.geysermc.platform.bukkit.command.GeyserBukkitCommandExecutor; +import org.geysermc.platform.bukkit.command.GeyserBukkitCommandManager; import java.util.UUID; public class GeyserBukkitPlugin extends JavaPlugin implements IGeyserBootstrap { + private GeyserBukkitCommandManager geyserCommandManager; private GeyserBukkitConfiguration geyserConfig; private GeyserBukkitLogger geyserLogger; @@ -53,6 +57,8 @@ public class GeyserBukkitPlugin extends JavaPlugin implements IGeyserBootstrap { this.geyserLogger = new GeyserBukkitLogger(getLogger(), geyserConfig.isDebugMode()); this.connector = GeyserConnector.start(PlatformType.BUKKIT, this); + this.geyserCommandManager = new GeyserBukkitCommandManager(this, connector); + this.getCommand("geyser").setExecutor(new GeyserBukkitCommandExecutor(connector)); } @@ -70,4 +76,9 @@ public class GeyserBukkitPlugin extends JavaPlugin implements IGeyserBootstrap { public GeyserBukkitLogger getGeyserLogger() { return geyserLogger; } + + @Override + public CommandManager getGeyserCommandManager() { + return this.geyserCommandManager; + } } diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/GeyserBukkitCommandExecutor.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/GeyserBukkitCommandExecutor.java index 84920db7..d2603f7c 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/GeyserBukkitCommandExecutor.java +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/GeyserBukkitCommandExecutor.java @@ -70,6 +70,6 @@ public class GeyserBukkitCommandExecutor implements TabExecutor { } private GeyserCommand getCommand(String label) { - return connector.getCommandMap().getCommands().get(label); + return connector.getCommandManager().getCommands().get(label); } } diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/GeyserBukkitCommandManager.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/GeyserBukkitCommandManager.java new file mode 100644 index 00000000..b826ab1f --- /dev/null +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/GeyserBukkitCommandManager.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.platform.bukkit.command; + +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandMap; +import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.command.CommandManager; +import org.geysermc.platform.bukkit.GeyserBukkitPlugin; + +import java.lang.reflect.Field; + +public class GeyserBukkitCommandManager extends CommandManager { + + private static CommandMap COMMAND_MAP; + + static { + try { + Field cmdMapField = Bukkit.getServer().getClass().getDeclaredField("commandMap"); + cmdMapField.setAccessible(true); + COMMAND_MAP = (CommandMap) cmdMapField.get(Bukkit.getServer()); + } catch (NoSuchFieldException | IllegalAccessException ex) { + ex.printStackTrace(); + } + } + + private GeyserBukkitPlugin plugin; + + public GeyserBukkitCommandManager(GeyserBukkitPlugin plugin, GeyserConnector connector) { + super(connector); + + this.plugin = plugin; + } + + @Override + public String getDescription(String command) { + Command cmd = COMMAND_MAP.getCommand(command.replace("/", "")); + return cmd != null ? cmd.getDescription() : ""; + } +} diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java index 959c78d9..9c3934cf 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java @@ -33,7 +33,9 @@ import net.md_5.bungee.config.YamlConfiguration; import org.geysermc.common.PlatformType; import org.geysermc.connector.GeyserConnector; import org.geysermc.common.bootstrap.IGeyserBootstrap; +import org.geysermc.connector.command.CommandManager; import org.geysermc.platform.bungeecord.command.GeyserBungeeCommandExecutor; +import org.geysermc.platform.bungeecord.command.GeyserBungeeCommandManager; import java.io.File; import java.io.IOException; @@ -44,6 +46,7 @@ import java.util.logging.Level; public class GeyserBungeePlugin extends Plugin implements IGeyserBootstrap { + private GeyserBungeeCommandManager geyserCommandManager; private GeyserBungeeConfiguration geyserConfig; private GeyserBungeeLogger geyserLogger; @@ -91,6 +94,8 @@ public class GeyserBungeePlugin extends Plugin implements IGeyserBootstrap { this.geyserLogger = new GeyserBungeeLogger(getLogger(), geyserConfig.isDebugMode()); this.connector = GeyserConnector.start(PlatformType.BUNGEECORD, this); + this.geyserCommandManager = new GeyserBungeeCommandManager(connector); + this.getProxy().getPluginManager().registerCommand(this, new GeyserBungeeCommandExecutor(connector)); } @@ -108,4 +113,9 @@ public class GeyserBungeePlugin extends Plugin implements IGeyserBootstrap { public GeyserBungeeLogger getGeyserLogger() { return geyserLogger; } + + @Override + public CommandManager getGeyserCommandManager() { + return this.geyserCommandManager; + } } diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/command/GeyserBungeeCommandExecutor.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/command/GeyserBungeeCommandExecutor.java index 8149d291..d1c8473b 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/command/GeyserBungeeCommandExecutor.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/command/GeyserBungeeCommandExecutor.java @@ -71,6 +71,6 @@ public class GeyserBungeeCommandExecutor extends Command implements TabExecutor } private GeyserCommand getCommand(String label) { - return connector.getCommandMap().getCommands().get(label); + return connector.getCommandManager().getCommands().get(label); } } diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/command/GeyserBungeeCommandManager.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/command/GeyserBungeeCommandManager.java new file mode 100644 index 00000000..bb79c577 --- /dev/null +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/command/GeyserBungeeCommandManager.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.platform.bungeecord.command; + +import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.command.CommandManager; + +public class GeyserBungeeCommandManager extends CommandManager { + + public GeyserBungeeCommandManager(GeyserConnector connector) { + super(connector); + } + + @Override + public String getDescription(String command) { + return ""; // no support for command descriptions in bungee + } +} diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java index bc264589..88996fd2 100644 --- a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java +++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java @@ -32,9 +32,12 @@ import ninja.leaping.configurate.yaml.YAMLConfigurationLoader; import org.geysermc.common.PlatformType; import org.geysermc.common.bootstrap.IGeyserBootstrap; +import org.geysermc.common.command.ICommandManager; import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.command.CommandManager; import org.geysermc.connector.utils.FileUtils; import org.geysermc.platform.sponge.command.GeyserSpongeCommandExecutor; +import org.geysermc.platform.sponge.command.GeyserSpongeCommandManager; import org.slf4j.Logger; import org.spongepowered.api.Sponge; import org.spongepowered.api.config.ConfigDir; @@ -57,6 +60,7 @@ public class GeyserSpongePlugin implements IGeyserBootstrap { @ConfigDir(sharedRoot = false) private File configDir; + private GeyserSpongeCommandManager geyserCommandManager; private GeyserSpongeConfiguration geyserConfig; private GeyserSpongeLogger geyserLogger; @@ -86,6 +90,7 @@ public class GeyserSpongePlugin implements IGeyserBootstrap { this.geyserLogger = new GeyserSpongeLogger(logger, geyserConfig.isDebugMode()); this.connector = GeyserConnector.start(PlatformType.SPONGE, this); + this.geyserCommandManager = new GeyserSpongeCommandManager(Sponge.getCommandManager(), connector); Sponge.getCommandManager().register(this, new GeyserSpongeCommandExecutor(connector), "geyser"); } @@ -105,6 +110,11 @@ public class GeyserSpongePlugin implements IGeyserBootstrap { return geyserLogger; } + @Override + public CommandManager getGeyserCommandManager() { + return this.geyserCommandManager; + } + @Listener public void onServerStart(GameStartedServerEvent event) { onEnable(); diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/command/GeyserSpongeCommandExecutor.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/command/GeyserSpongeCommandExecutor.java index c68ff4e4..91cb59b0 100644 --- a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/command/GeyserSpongeCommandExecutor.java +++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/command/GeyserSpongeCommandExecutor.java @@ -95,6 +95,6 @@ public class GeyserSpongeCommandExecutor implements CommandCallable { } private GeyserCommand getCommand(String label) { - return connector.getCommandMap().getCommands().get(label); + return connector.getCommandManager().getCommands().get(label); } } diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/command/GeyserSpongeCommandManager.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/command/GeyserSpongeCommandManager.java new file mode 100644 index 00000000..c36511a4 --- /dev/null +++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/command/GeyserSpongeCommandManager.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.platform.sponge.command; + +import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.command.CommandManager; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.command.CommandMapping; +import org.spongepowered.api.text.Text; + +public class GeyserSpongeCommandManager extends CommandManager { + + private org.spongepowered.api.command.CommandManager handle; + + public GeyserSpongeCommandManager(org.spongepowered.api.command.CommandManager handle, GeyserConnector connector) { + super(connector); + + this.handle = handle; + } + + @Override + public String getDescription(String command) { + return handle.get(command).map(CommandMapping::getCallable).map(callable -> callable.getShortDescription(Sponge.getServer().getConsole()).orElse(Text.EMPTY)).orElse(Text.EMPTY).toPlain(); + } +} diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserBootstrap.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserBootstrap.java index 1bdce0bd..b9c60d0f 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserBootstrap.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserBootstrap.java @@ -32,11 +32,14 @@ import java.util.UUID; import org.geysermc.common.PlatformType; import org.geysermc.common.bootstrap.IGeyserBootstrap; import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.command.CommandManager; import org.geysermc.connector.utils.FileUtils; +import org.geysermc.platform.standalone.command.GeyserCommandManager; import org.geysermc.platform.standalone.console.GeyserLogger; public class GeyserBootstrap implements IGeyserBootstrap { - + + private GeyserCommandManager geyserCommandManager; private GeyserConfiguration geyserConfig; private GeyserLogger geyserLogger; @@ -49,7 +52,7 @@ public class GeyserBootstrap implements IGeyserBootstrap { @Override public void onEnable() { geyserLogger = new GeyserLogger(); - + LoopbackUtil.checkLoopback(geyserLogger); try { @@ -62,6 +65,7 @@ public class GeyserBootstrap implements IGeyserBootstrap { connector = GeyserConnector.start(PlatformType.STANDALONE, this); geyserLogger.start(); + geyserCommandManager = new GeyserCommandManager(connector); } @Override @@ -79,4 +83,9 @@ public class GeyserBootstrap implements IGeyserBootstrap { public GeyserLogger getGeyserLogger() { return geyserLogger; } + + @Override + public CommandManager getGeyserCommandManager() { + return geyserCommandManager; + } } diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/command/GeyserCommandManager.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/command/GeyserCommandManager.java new file mode 100644 index 00000000..41bf61c1 --- /dev/null +++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/command/GeyserCommandManager.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.platform.standalone.command; + +import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.command.CommandManager; + +public class GeyserCommandManager extends CommandManager { + + public GeyserCommandManager(GeyserConnector connector) { + super(connector); + } + + @Override + public String getDescription(String command) { + return ""; // this is not sent over the protocol, so we return none + } +} diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/console/GeyserLogger.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/console/GeyserLogger.java index ac21215c..631de905 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/console/GeyserLogger.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/console/GeyserLogger.java @@ -47,7 +47,7 @@ public class GeyserLogger extends SimpleTerminalConsole implements IGeyserLogger @Override protected void runCommand(String line) { - GeyserConnector.getInstance().getCommandMap().runCommand(this, line); + GeyserConnector.getInstance().getCommandManager().runCommand(this, line); } @Override diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java index 5ab411f3..160c2d52 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java @@ -38,6 +38,7 @@ import org.geysermc.common.bootstrap.IGeyserBootstrap; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.utils.FileUtils; import org.geysermc.platform.velocity.command.GeyserVelocityCommandExecutor; +import org.geysermc.platform.velocity.command.GeyserVelocityCommandManager; import org.slf4j.Logger; import java.io.File; @@ -53,6 +54,7 @@ public class GeyserVelocityPlugin implements IGeyserBootstrap { @Inject private CommandManager commandManager; + private GeyserVelocityCommandManager geyserCommandManager; private GeyserVelocityConfiguration geyserConfig; private GeyserVelocityLogger geyserLogger; @@ -74,6 +76,7 @@ public class GeyserVelocityPlugin implements IGeyserBootstrap { this.geyserLogger = new GeyserVelocityLogger(logger, geyserConfig.isDebugMode()); this.connector = GeyserConnector.start(PlatformType.VELOCITY, this); + this.geyserCommandManager = new GeyserVelocityCommandManager(connector); this.commandManager.register(new GeyserVelocityCommandExecutor(connector), "geyser"); } @@ -92,6 +95,11 @@ public class GeyserVelocityPlugin implements IGeyserBootstrap { return geyserLogger; } + @Override + public org.geysermc.connector.command.CommandManager getGeyserCommandManager() { + return this.geyserCommandManager; + } + @Subscribe public void onInit(ProxyInitializeEvent event) { onEnable(); diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/command/GeyserVelocityCommandExecutor.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/command/GeyserVelocityCommandExecutor.java index 39a0af97..940c5224 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/command/GeyserVelocityCommandExecutor.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/command/GeyserVelocityCommandExecutor.java @@ -57,6 +57,6 @@ public class GeyserVelocityCommandExecutor implements Command { } private GeyserCommand getCommand(String label) { - return connector.getCommandMap().getCommands().get(label); + return connector.getCommandManager().getCommands().get(label); } } diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/command/GeyserVelocityCommandManager.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/command/GeyserVelocityCommandManager.java new file mode 100644 index 00000000..76655d0a --- /dev/null +++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/command/GeyserVelocityCommandManager.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.platform.velocity.command; + +import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.command.CommandManager; + +public class GeyserVelocityCommandManager extends CommandManager { + + public GeyserVelocityCommandManager(GeyserConnector connector) { + super(connector); + } + + @Override + public String getDescription(String command) { + return ""; // no support for command descriptions in velocity + } +} diff --git a/common/src/main/java/org/geysermc/common/bootstrap/IGeyserBootstrap.java b/common/src/main/java/org/geysermc/common/bootstrap/IGeyserBootstrap.java index 9a9d9c2b..280723aa 100644 --- a/common/src/main/java/org/geysermc/common/bootstrap/IGeyserBootstrap.java +++ b/common/src/main/java/org/geysermc/common/bootstrap/IGeyserBootstrap.java @@ -26,6 +26,7 @@ package org.geysermc.common.bootstrap; import org.geysermc.common.IGeyserConfiguration; +import org.geysermc.common.command.ICommandManager; import org.geysermc.common.logger.IGeyserLogger; public interface IGeyserBootstrap { @@ -37,4 +38,6 @@ public interface IGeyserBootstrap { IGeyserConfiguration getGeyserConfig(); IGeyserLogger getGeyserLogger(); + + ICommandManager getGeyserCommandManager(); } diff --git a/common/src/main/java/org/geysermc/common/command/ICommandManager.java b/common/src/main/java/org/geysermc/common/command/ICommandManager.java new file mode 100644 index 00000000..53e85fc7 --- /dev/null +++ b/common/src/main/java/org/geysermc/common/command/ICommandManager.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.common.command; + +public interface ICommandManager { + + String getDescription(String command); +} diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java index 9cea6257..278e4859 100644 --- a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java +++ b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java @@ -35,7 +35,7 @@ import org.geysermc.common.AuthType; import org.geysermc.common.PlatformType; import org.geysermc.common.bootstrap.IGeyserBootstrap; import org.geysermc.common.logger.IGeyserLogger; -import org.geysermc.connector.command.GeyserCommandMap; +import org.geysermc.connector.command.CommandManager; import org.geysermc.connector.metrics.Metrics; import org.geysermc.connector.network.ConnectorServerEventHandler; import org.geysermc.connector.network.remote.RemoteServer; @@ -50,7 +50,6 @@ import java.text.DecimalFormat; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CompletableFuture; -import java.util.UUID; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -70,8 +69,6 @@ public class GeyserConnector { private RemoteServer remoteServer; private AuthType authType; - private GeyserCommandMap commandMap; - private boolean shuttingDown = false; private final ScheduledExecutorService generalThreadPool; @@ -108,7 +105,6 @@ public class GeyserConnector { Toolbox.init(); Translators.start(); - commandMap = new GeyserCommandMap(this); remoteServer = new RemoteServer(config.getRemote().getAddress(), config.getRemote().getPort()); authType = AuthType.getByName(config.getRemote().getAuthType()); @@ -182,8 +178,7 @@ public class GeyserConnector { players.clear(); remoteServer = null; authType = null; - commandMap.getCommands().clear(); - commandMap = null; + this.getCommandManager().getCommands().clear(); bootstrap.getGeyserLogger().info("Geyser shutdown successfully."); } @@ -213,6 +208,10 @@ public class GeyserConnector { return bootstrap.getGeyserConfig(); } + public CommandManager getCommandManager() { + return (CommandManager) bootstrap.getGeyserCommandManager(); + } + public static GeyserConnector getInstance() { return instance; } diff --git a/connector/src/main/java/org/geysermc/connector/command/GeyserCommandMap.java b/connector/src/main/java/org/geysermc/connector/command/CommandManager.java similarity index 95% rename from connector/src/main/java/org/geysermc/connector/command/GeyserCommandMap.java rename to connector/src/main/java/org/geysermc/connector/command/CommandManager.java index c4bf488e..16070099 100644 --- a/connector/src/main/java/org/geysermc/connector/command/GeyserCommandMap.java +++ b/connector/src/main/java/org/geysermc/connector/command/CommandManager.java @@ -26,6 +26,7 @@ package org.geysermc.connector.command; import lombok.Getter; +import org.geysermc.common.command.ICommandManager; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.defaults.HelpCommand; import org.geysermc.connector.command.defaults.ReloadCommand; @@ -35,14 +36,14 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; -public class GeyserCommandMap { +public abstract class CommandManager implements ICommandManager { @Getter private final Map commands = Collections.synchronizedMap(new HashMap<>()); private GeyserConnector connector; - public GeyserCommandMap(GeyserConnector connector) { + public CommandManager(GeyserConnector connector) { this.connector = connector; registerCommand(new HelpCommand(connector, "help", "Shows help for all registered commands.", "geyser.command.help")); diff --git a/connector/src/main/java/org/geysermc/connector/command/defaults/HelpCommand.java b/connector/src/main/java/org/geysermc/connector/command/defaults/HelpCommand.java index cdfb612a..6acb7822 100644 --- a/connector/src/main/java/org/geysermc/connector/command/defaults/HelpCommand.java +++ b/connector/src/main/java/org/geysermc/connector/command/defaults/HelpCommand.java @@ -49,8 +49,8 @@ public class HelpCommand extends GeyserCommand { @Override public void execute(CommandSender sender, String[] args) { sender.sendMessage("---- Showing Help For: Geyser (Page 1/1) ----"); - Map cmds = connector.getCommandMap().getCommands(); - List commands = connector.getCommandMap().getCommands().keySet().stream().sorted().collect(Collectors.toList()); + Map cmds = connector.getCommandManager().getCommands(); + List commands = connector.getCommandManager().getCommands().keySet().stream().sorted().collect(Collectors.toList()); commands.forEach(cmd -> sender.sendMessage(ChatColor.YELLOW + "/geyser " + cmd + ChatColor.WHITE + ": " + cmds.get(cmd).getDescription())); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockCommandRequestTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockCommandRequestTranslator.java index e7d4c748..c8e11741 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockCommandRequestTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockCommandRequestTranslator.java @@ -27,7 +27,7 @@ package org.geysermc.connector.network.translators.bedrock; import org.geysermc.common.PlatformType; import org.geysermc.connector.GeyserConnector; -import org.geysermc.connector.command.GeyserCommandMap; +import org.geysermc.connector.command.CommandManager; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.Translator; @@ -42,9 +42,9 @@ public class BedrockCommandRequestTranslator extends PacketTranslator Date: Mon, 20 Apr 2020 02:56:03 +0100 Subject: [PATCH 099/109] Fix command execution on standalone --- .../geysermc/platform/standalone/GeyserBootstrap.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserBootstrap.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserBootstrap.java index b9c60d0f..20b7f5ea 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserBootstrap.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserBootstrap.java @@ -25,10 +25,6 @@ package org.geysermc.platform.standalone; -import java.io.File; -import java.io.IOException; -import java.util.UUID; - import org.geysermc.common.PlatformType; import org.geysermc.common.bootstrap.IGeyserBootstrap; import org.geysermc.connector.GeyserConnector; @@ -37,6 +33,10 @@ import org.geysermc.connector.utils.FileUtils; import org.geysermc.platform.standalone.command.GeyserCommandManager; import org.geysermc.platform.standalone.console.GeyserLogger; +import java.io.File; +import java.io.IOException; +import java.util.UUID; + public class GeyserBootstrap implements IGeyserBootstrap { private GeyserCommandManager geyserCommandManager; @@ -64,8 +64,8 @@ public class GeyserBootstrap implements IGeyserBootstrap { } connector = GeyserConnector.start(PlatformType.STANDALONE, this); - geyserLogger.start(); geyserCommandManager = new GeyserCommandManager(connector); + geyserLogger.start(); } @Override From 7417f57d4721f3a2d917c70755f33ae7d34146db Mon Sep 17 00:00:00 2001 From: rtm516 Date: Mon, 20 Apr 2020 06:29:36 +0100 Subject: [PATCH 100/109] Fish fixes (#374) * Fixed tropical fish display. * Added base pufferfish class * Fixed pufferfish, fish flags and cleaned up tropical fish spawning * Fixed tropical fish model variant * Fix tropical fish colours --- .../entity/living/AbstractFishEntity.java | 16 ++++ .../living/animal/PufferFishEntity.java | 51 +++++++++++ .../living/animal/TropicalFishEntity.java | 87 +++++++++++++++++++ .../connector/entity/type/EntityType.java | 4 +- 4 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/entity/living/animal/PufferFishEntity.java create mode 100644 connector/src/main/java/org/geysermc/connector/entity/living/animal/TropicalFishEntity.java diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/AbstractFishEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/AbstractFishEntity.java index 92acb117..54443825 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/AbstractFishEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/AbstractFishEntity.java @@ -25,12 +25,28 @@ package org.geysermc.connector.entity.living; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.data.EntityFlag; import org.geysermc.connector.entity.type.EntityType; +import org.geysermc.connector.network.session.GeyserSession; public class AbstractFishEntity extends WaterEntity { public AbstractFishEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { super(entityId, geyserId, entityType, position, motion, rotation); } + + @Override + public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { + metadata.getFlags().setFlag(EntityFlag.CAN_SWIM, true); + metadata.getFlags().setFlag(EntityFlag.BREATHING, true); + metadata.getFlags().setFlag(EntityFlag.CAN_CLIMB, false); + metadata.getFlags().setFlag(EntityFlag.HAS_GRAVITY, false); + + metadata.put(EntityData.AIR, (short) 400); + + super.updateBedrockMetadata(entityMetadata, session); + } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/PufferFishEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/PufferFishEntity.java new file mode 100644 index 00000000..d5503dc0 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/PufferFishEntity.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.entity.living.animal; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.EntityData; +import org.geysermc.connector.entity.living.AbstractFishEntity; +import org.geysermc.connector.entity.type.EntityType; +import org.geysermc.connector.network.session.GeyserSession; + +public class PufferFishEntity extends AbstractFishEntity { + + public PufferFishEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { + super(entityId, geyserId, entityType, position, motion, rotation); + } + + @Override + public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { + if (entityMetadata.getId() == 16) { + // Transfers correctly but doesn't apply on the client + int puffsize = (int) entityMetadata.getValue(); + metadata.put(EntityData.PUFFERFISH_SIZE, puffsize); + metadata.put(EntityData.VARIANT, puffsize); + } + super.updateBedrockMetadata(entityMetadata, session); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/TropicalFishEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/TropicalFishEntity.java new file mode 100644 index 00000000..5addcc2e --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/TropicalFishEntity.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.entity.living.animal; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.packet.AddEntityPacket; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.geysermc.connector.entity.living.AbstractFishEntity; +import org.geysermc.connector.entity.type.EntityType; +import org.geysermc.connector.network.session.GeyserSession; + +public class TropicalFishEntity extends AbstractFishEntity { + + public TropicalFishEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { + super(entityId, geyserId, entityType, position, motion, rotation); + } + + @Override + public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { + if (entityMetadata.getId() == 16) { + // Still not always the right model and colour is broken + TropicalFishVariant variant = TropicalFishVariant.fromVariantNumber((int) entityMetadata.getValue()); + metadata.put(EntityData.VARIANT, variant.getShape()); // Shape 0-1 + metadata.put(EntityData.MARK_VARIANT, variant.getPattern()); // Pattern 0-5 + metadata.put(EntityData.COLOR, variant.getBaseColor()); // Base color 0-15 + metadata.put(EntityData.COLOR_2, variant.getPatternColor()); // Pattern color 0-15 + } + super.updateBedrockMetadata(entityMetadata, session); + } + + @Override + public void spawnEntity(GeyserSession session) { + AddEntityPacket addEntityPacket = new AddEntityPacket(); + addEntityPacket.setIdentifier("minecraft:tropicalfish"); + addEntityPacket.setRuntimeEntityId(geyserId); + addEntityPacket.setUniqueEntityId(geyserId); + addEntityPacket.setPosition(position); + addEntityPacket.setMotion(motion); + addEntityPacket.setRotation(getBedrockRotation()); + addEntityPacket.setEntityType(entityType.getType()); + addEntityPacket.getMetadata().putAll(metadata); + + valid = true; + session.getUpstream().sendPacket(addEntityPacket); + + session.getConnector().getLogger().debug("Spawned entity " + entityType + " at location " + position + " with id " + geyserId + " (java id " + entityId + ")"); + } + + @Getter + @AllArgsConstructor + private static class TropicalFishVariant { + private int shape; + private int pattern; + private byte baseColor; + private byte patternColor; + + public static TropicalFishVariant fromVariantNumber(int varNumber) { + return new TropicalFishVariant((varNumber & 0xFF), ((varNumber >> 8) & 0xFF), (byte) ((varNumber >> 16) & 0xFF), (byte) ((varNumber >> 24) & 0xFF)); + } + } +} diff --git a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java index 8ea3240c..7a7e13c0 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java +++ b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java @@ -140,10 +140,10 @@ public enum EntityType { VEX(MonsterEntity.class, 105, 0f), ICE_BOMB(Entity.class, 106, 0f), BALLOON(Entity.class, 107, 0f), //TODO - PUFFERFISH(AbstractFishEntity.class, 108, 0.7f, 0.7f), + PUFFERFISH(PufferFishEntity.class, 108, 0.7f, 0.7f), SALMON(AbstractFishEntity.class, 109, 0.5f, 0.7f), DROWNED(ZombieEntity.class, 110, 1.95f, 0.6f), - TROPICAL_FISH(AbstractFishEntity.class, 111, 0.6f, 0.6f), + TROPICAL_FISH(TropicalFishEntity.class, 111, 0.6f, 0.6f), COD(AbstractFishEntity.class, 112, 0.25f, 0.5f), PANDA(PandaEntity.class, 113, 1.25f, 1.125f, 1.825f), FOX(FoxEntity.class, 121, 0.5f, 1.25f), From 4ee95f585dbf687f733ccf667538d01ffbebb293 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Mon, 20 Apr 2020 21:10:30 +0100 Subject: [PATCH 101/109] Move all json to Jackson instead of a mix of 2 libraries (#302) * Swapped most GSON refrences to Jackson * Converted FormWindow getJSONData Co-authored-by: Redned --- .../common/window/CustomFormWindow.java | 18 ++- .../geysermc/common/window/FormWindow.java | 2 + .../common/window/ModalFormWindow.java | 9 +- .../common/window/SimpleFormWindow.java | 9 +- .../geysermc/connector/metrics/Metrics.java | 132 +++++++++--------- .../connector/utils/SkinProvider.java | 4 - .../geysermc/connector/utils/SkinUtils.java | 15 +- 7 files changed, 107 insertions(+), 82 deletions(-) diff --git a/common/src/main/java/org/geysermc/common/window/CustomFormWindow.java b/common/src/main/java/org/geysermc/common/window/CustomFormWindow.java index 8d48fcfa..efc71ae8 100644 --- a/common/src/main/java/org/geysermc/common/window/CustomFormWindow.java +++ b/common/src/main/java/org/geysermc/common/window/CustomFormWindow.java @@ -25,8 +25,9 @@ package org.geysermc.common.window; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Getter; import lombok.Setter; import org.geysermc.common.window.button.FormImage; @@ -34,6 +35,7 @@ import org.geysermc.common.window.component.*; import org.geysermc.common.window.response.CustomFormResponse; import org.geysermc.common.window.response.FormResponseData; +import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -77,7 +79,11 @@ public class CustomFormWindow extends FormWindow { } public String getJSONData() { - String toModify = new Gson().toJson(this); + String toModify = ""; + try { + toModify = new ObjectMapper().writeValueAsString(this); + } catch (JsonProcessingException e) { } + //We need to replace this due to Java not supporting declaring class field 'default' return toModify.replace("defaultOptionIndex", "default") .replace("defaultText", "default") @@ -100,7 +106,11 @@ public class CustomFormWindow extends FormWindow { Map responses = new HashMap(); Map labelResponses = new HashMap(); - List componentResponses = new Gson().fromJson(data, new TypeToken>() { }.getType()); + List componentResponses = new ArrayList<>(); + try { + componentResponses = new ObjectMapper().readValue(data, new TypeReference>(){}); + } catch (IOException e) { } + for (String response : componentResponses) { if (i >= content.size()) { break; diff --git a/common/src/main/java/org/geysermc/common/window/FormWindow.java b/common/src/main/java/org/geysermc/common/window/FormWindow.java index 3cfaee43..c3cc4258 100644 --- a/common/src/main/java/org/geysermc/common/window/FormWindow.java +++ b/common/src/main/java/org/geysermc/common/window/FormWindow.java @@ -25,6 +25,7 @@ package org.geysermc.common.window; +import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.Getter; import lombok.Setter; import org.geysermc.common.window.response.FormResponse; @@ -50,6 +51,7 @@ public abstract class FormWindow { this.response = response; } + @JsonIgnore public abstract String getJSONData(); public abstract void setResponse(String response); diff --git a/common/src/main/java/org/geysermc/common/window/ModalFormWindow.java b/common/src/main/java/org/geysermc/common/window/ModalFormWindow.java index 66dda0b5..bfeafa1b 100644 --- a/common/src/main/java/org/geysermc/common/window/ModalFormWindow.java +++ b/common/src/main/java/org/geysermc/common/window/ModalFormWindow.java @@ -25,7 +25,8 @@ package org.geysermc.common.window; -import com.google.gson.Gson; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Getter; import lombok.Setter; import org.geysermc.common.window.response.ModalFormResponse; @@ -59,7 +60,11 @@ public class ModalFormWindow extends FormWindow { @Override public String getJSONData() { - return new Gson().toJson(this); + try { + return new ObjectMapper().writeValueAsString(this); + } catch (JsonProcessingException e) { + return ""; + } } public void setResponse(String data) { diff --git a/common/src/main/java/org/geysermc/common/window/SimpleFormWindow.java b/common/src/main/java/org/geysermc/common/window/SimpleFormWindow.java index 381cef39..7c1acc26 100644 --- a/common/src/main/java/org/geysermc/common/window/SimpleFormWindow.java +++ b/common/src/main/java/org/geysermc/common/window/SimpleFormWindow.java @@ -25,7 +25,8 @@ package org.geysermc.common.window; -import com.google.gson.Gson; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Getter; import lombok.Setter; import org.geysermc.common.window.button.FormButton; @@ -63,7 +64,11 @@ public class SimpleFormWindow extends FormWindow { @Override public String getJSONData() { - return new Gson().toJson(this); + try { + return new ObjectMapper().writeValueAsString(this); + } catch (JsonProcessingException e) { + return ""; + } } public void setResponse(String data) { diff --git a/connector/src/main/java/org/geysermc/connector/metrics/Metrics.java b/connector/src/main/java/org/geysermc/connector/metrics/Metrics.java index ff2cd097..36aa32c3 100644 --- a/connector/src/main/java/org/geysermc/connector/metrics/Metrics.java +++ b/connector/src/main/java/org/geysermc/connector/metrics/Metrics.java @@ -25,8 +25,10 @@ package org.geysermc.connector.metrics; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import org.geysermc.connector.GeyserConnector; import javax.net.ssl.HttpsURLConnection; @@ -71,6 +73,8 @@ public class Metrics { // A list with all custom charts private final List charts = new ArrayList<>(); + private final static ObjectMapper mapper = new ObjectMapper(); + private GeyserConnector connector; /** @@ -110,7 +114,7 @@ public class Metrics { */ private void startSubmitting() { connector.getGeneralThreadPool().scheduleAtFixedRate(this::submitData, 1, 30, TimeUnit.MINUTES); - // Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start + // Submit the data every 30 minutes, first time after 1 minutes to give other plugins enough time to start // WARNING: Changing the frequency has no effect but your plugin WILL be blocked/deleted! // WARNING: Just don't do it! } @@ -120,22 +124,22 @@ public class Metrics { * * @return The plugin specific data. */ - private JsonObject getPluginData() { - JsonObject data = new JsonObject(); + private ObjectNode getPluginData() { + ObjectNode data = mapper.createObjectNode(); - data.addProperty("pluginName", name); // Append the name of the server software - data.addProperty("pluginVersion", GeyserConnector.VERSION); // Append the name of the server software + data.put("pluginName", name); // Append the name of the server software + data.put("pluginVersion", GeyserConnector.VERSION); // Append the name of the server software - JsonArray customCharts = new JsonArray(); + ArrayNode customCharts = mapper.createArrayNode(); for (CustomChart customChart : charts) { // Add the data of the custom charts - JsonObject chart = customChart.getRequestJsonObject(); + JsonNode chart = customChart.getRequestJsonNode(); if (chart == null) { // If the chart is null, we skip it continue; } customCharts.add(chart); } - data.add("customCharts", customCharts); + data.put("customCharts", customCharts); return data; } @@ -145,7 +149,7 @@ public class Metrics { * * @return The server specific data. */ - private JsonObject getServerData() { + private ObjectNode getServerData() { // OS specific data int playerAmount = connector.getPlayers().size(); @@ -154,15 +158,15 @@ public class Metrics { String osVersion = System.getProperty("os.version"); int coreCount = Runtime.getRuntime().availableProcessors(); - JsonObject data = new JsonObject(); + ObjectNode data = mapper.createObjectNode(); - data.addProperty("serverUUID", serverUUID); + data.put("serverUUID", serverUUID); - data.addProperty("playerAmount", playerAmount); - data.addProperty("osName", osName); - data.addProperty("osArch", osArch); - data.addProperty("osVersion", osVersion); - data.addProperty("coreCount", coreCount); + data.put("playerAmount", playerAmount); + data.put("osName", osName); + data.put("osArch", osArch); + data.put("osVersion", osVersion); + data.put("coreCount", coreCount); return data; } @@ -171,11 +175,11 @@ public class Metrics { * Collects the data and sends it afterwards. */ private void submitData() { - final JsonObject data = getServerData(); + final ObjectNode data = getServerData(); - JsonArray pluginData = new JsonArray(); + ArrayNode pluginData = mapper.createArrayNode(); pluginData.add(getPluginData()); - data.add("plugins", pluginData); + data.putPOJO("plugins", pluginData); new Thread(() -> { try { @@ -196,7 +200,7 @@ public class Metrics { * @param data The data to send. * @throws Exception If the request failed. */ - private static void sendData(JsonObject data) throws Exception { + private static void sendData(ObjectNode data) throws Exception { if (data == null) { throw new IllegalArgumentException("Data cannot be null!"); } @@ -262,16 +266,16 @@ public class Metrics { this.chartId = chartId; } - private JsonObject getRequestJsonObject() { - JsonObject chart = new JsonObject(); - chart.addProperty("chartId", chartId); + private ObjectNode getRequestJsonNode() { + ObjectNode chart = new ObjectMapper().createObjectNode(); + chart.put("chartId", chartId); try { - JsonObject data = getChartData(); + ObjectNode data = getChartData(); if (data == null) { // If the data is null we don't send the chart. return null; } - chart.add("data", data); + chart.putPOJO("data", data); } catch (Throwable t) { if (logFailedRequests) { logger.log(Level.WARNING, "Failed to get data for custom chart with id " + chartId, t); @@ -281,7 +285,9 @@ public class Metrics { return chart; } - protected abstract JsonObject getChartData() throws Exception; + + + protected abstract ObjectNode getChartData() throws Exception; } @@ -304,14 +310,14 @@ public class Metrics { } @Override - protected JsonObject getChartData() throws Exception { - JsonObject data = new JsonObject(); + protected ObjectNode getChartData() throws Exception { + ObjectNode data = mapper.createObjectNode(); String value = callable.call(); if (value == null || value.isEmpty()) { // Null = skip the chart return null; } - data.addProperty("value", value); + data.put("value", value); return data; } } @@ -335,9 +341,9 @@ public class Metrics { } @Override - protected JsonObject getChartData() throws Exception { - JsonObject data = new JsonObject(); - JsonObject values = new JsonObject(); + protected ObjectNode getChartData() throws Exception { + ObjectNode data = mapper.createObjectNode(); + ObjectNode values = mapper.createObjectNode(); Map map = callable.call(); if (map == null || map.isEmpty()) { // Null = skip the chart @@ -349,13 +355,13 @@ public class Metrics { continue; // Skip this invalid } allSkipped = false; - values.addProperty(entry.getKey(), entry.getValue()); + values.put(entry.getKey(), entry.getValue()); } if (allSkipped) { // Null = skip the chart return null; } - data.add("values", values); + data.putPOJO("values", values); return data; } } @@ -379,9 +385,9 @@ public class Metrics { } @Override - public JsonObject getChartData() throws Exception { - JsonObject data = new JsonObject(); - JsonObject values = new JsonObject(); + public ObjectNode getChartData() throws Exception { + ObjectNode data = mapper.createObjectNode(); + ObjectNode values = mapper.createObjectNode(); Map> map = callable.call(); if (map == null || map.isEmpty()) { // Null = skip the chart @@ -389,22 +395,22 @@ public class Metrics { } boolean reallyAllSkipped = true; for (Map.Entry> entryValues : map.entrySet()) { - JsonObject value = new JsonObject(); + ObjectNode value = mapper.createObjectNode(); boolean allSkipped = true; for (Map.Entry valueEntry : map.get(entryValues.getKey()).entrySet()) { - value.addProperty(valueEntry.getKey(), valueEntry.getValue()); + value.put(valueEntry.getKey(), valueEntry.getValue()); allSkipped = false; } if (!allSkipped) { reallyAllSkipped = false; - values.add(entryValues.getKey(), value); + values.putPOJO(entryValues.getKey(), value); } } if (reallyAllSkipped) { // Null = skip the chart return null; } - data.add("values", values); + data.putPOJO("values", values); return data; } } @@ -428,14 +434,14 @@ public class Metrics { } @Override - protected JsonObject getChartData() throws Exception { - JsonObject data = new JsonObject(); + protected ObjectNode getChartData() throws Exception { + ObjectNode data = mapper.createObjectNode(); int value = callable.call(); if (value == 0) { // Null = skip the chart return null; } - data.addProperty("value", value); + data.put("value", value); return data; } @@ -460,9 +466,9 @@ public class Metrics { } @Override - protected JsonObject getChartData() throws Exception { - JsonObject data = new JsonObject(); - JsonObject values = new JsonObject(); + protected ObjectNode getChartData() throws Exception { + ObjectNode data = mapper.createObjectNode(); + ObjectNode values = mapper.createObjectNode(); Map map = callable.call(); if (map == null || map.isEmpty()) { // Null = skip the chart @@ -474,13 +480,13 @@ public class Metrics { continue; // Skip this invalid } allSkipped = false; - values.addProperty(entry.getKey(), entry.getValue()); + values.put(entry.getKey(), entry.getValue()); } if (allSkipped) { // Null = skip the chart return null; } - data.add("values", values); + data.putPOJO("values", values); return data; } @@ -505,20 +511,20 @@ public class Metrics { } @Override - protected JsonObject getChartData() throws Exception { - JsonObject data = new JsonObject(); - JsonObject values = new JsonObject(); + protected ObjectNode getChartData() throws Exception { + ObjectNode data = mapper.createObjectNode(); + ObjectNode values = mapper.createObjectNode(); Map map = callable.call(); if (map == null || map.isEmpty()) { // Null = skip the chart return null; } for (Map.Entry entry : map.entrySet()) { - JsonArray categoryValues = new JsonArray(); + ArrayNode categoryValues = mapper.createArrayNode(); categoryValues.add(entry.getValue()); - values.add(entry.getKey(), categoryValues); + values.putPOJO(entry.getKey(), categoryValues); } - data.add("values", values); + data.putPOJO("values", values); return data; } @@ -543,9 +549,9 @@ public class Metrics { } @Override - protected JsonObject getChartData() throws Exception { - JsonObject data = new JsonObject(); - JsonObject values = new JsonObject(); + protected ObjectNode getChartData() throws Exception { + ObjectNode data = mapper.createObjectNode(); + ObjectNode values = mapper.createObjectNode(); Map map = callable.call(); if (map == null || map.isEmpty()) { // Null = skip the chart @@ -557,17 +563,17 @@ public class Metrics { continue; // Skip this invalid } allSkipped = false; - JsonArray categoryValues = new JsonArray(); + ArrayNode categoryValues = mapper.createArrayNode(); for (int categoryValue : entry.getValue()) { categoryValues.add(categoryValue); } - values.add(entry.getKey(), categoryValues); + values.putPOJO(entry.getKey(), categoryValues); } if (allSkipped) { // Null = skip the chart return null; } - data.add("values", values); + data.putPOJO("values", values); return data; } diff --git a/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java b/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java index c6f53ae9..ade03c54 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java +++ b/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java @@ -25,9 +25,6 @@ package org.geysermc.connector.utils; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - import lombok.AllArgsConstructor; import lombok.Getter; @@ -43,7 +40,6 @@ import java.util.UUID; import java.util.concurrent.*; public class SkinProvider { - public static final Gson GSON = new GsonBuilder().create(); public static final boolean ALLOW_THIRD_PARTY_CAPES = GeyserConnector.getInstance().getConfig().isAllowThirdPartyCapes(); private static final ExecutorService EXECUTOR_SERVICE = Executors.newFixedThreadPool(ALLOW_THIRD_PARTY_CAPES ? 21 : 14); diff --git a/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java b/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java index 6e144498..7a5b9798 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java @@ -25,8 +25,9 @@ package org.geysermc.connector.utils; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import com.github.steveice10.mc.auth.data.GameProfile; -import com.google.gson.JsonObject; import com.nukkitx.protocol.bedrock.data.ImageData; import com.nukkitx.protocol.bedrock.data.SerializedSkin; import com.nukkitx.protocol.bedrock.packet.PlayerListPacket; @@ -108,18 +109,18 @@ public class SkinUtils { try { GameProfile.Property skinProperty = profile.getProperty("textures"); - JsonObject skinObject = SkinProvider.GSON.fromJson(new String(Base64.getDecoder().decode(skinProperty.getValue()), StandardCharsets.UTF_8), JsonObject.class); - JsonObject textures = skinObject.getAsJsonObject("textures"); + JsonNode skinObject = new ObjectMapper().readTree(new String(Base64.getDecoder().decode(skinProperty.getValue()), StandardCharsets.UTF_8)); + JsonNode textures = skinObject.get("textures"); - JsonObject skinTexture = textures.getAsJsonObject("SKIN"); - String skinUrl = skinTexture.get("url").getAsString(); + JsonNode skinTexture = textures.get("SKIN"); + String skinUrl = skinTexture.get("url").asText(); boolean isAlex = skinTexture.has("metadata"); String capeUrl = null; if (textures.has("CAPE")) { - JsonObject capeTexture = textures.getAsJsonObject("CAPE"); - capeUrl = capeTexture.get("url").getAsString(); + JsonNode capeTexture = textures.get("CAPE"); + capeUrl = capeTexture.get("url").asText(); } return new GameProfileData(skinUrl, capeUrl, isAlex); From 1b15f3058f8ce892cebc3ebbe789a0c8e7ded47c Mon Sep 17 00:00:00 2001 From: rtm516 Date: Tue, 21 Apr 2020 06:28:44 +0100 Subject: [PATCH 102/109] Javadoc a bit of Geyser (#392) * A bunch of javadoc comments * Cleaned up javadocs --- .../java/org/geysermc/common/AuthType.java | 7 +++ .../java/org/geysermc/common/ChatColor.java | 14 +++++ .../common/bootstrap/IGeyserBootstrap.java | 21 ++++++++ .../common/command/ICommandManager.java | 7 +++ .../living/animal/TropicalFishEntity.java | 9 +++- .../JavaServerDeclareCommandsTranslator.java | 37 +++++++++++-- .../connector/utils/DimensionUtils.java | 6 +++ .../geysermc/connector/utils/EntityUtils.java | 19 +++++++ .../geysermc/connector/utils/FileUtils.java | 53 ++++++++++++++++--- .../geysermc/connector/utils/LocaleUtils.java | 43 ++++++++++++++- .../geysermc/connector/utils/MathUtils.java | 6 +++ .../connector/utils/MessageUtils.java | 40 +++++++++++++- .../geysermc/connector/utils/SkinUtils.java | 12 +++++ .../org/geysermc/connector/utils/Toolbox.java | 6 +++ .../geysermc/connector/utils/WebUtils.java | 12 +++++ 15 files changed, 280 insertions(+), 12 deletions(-) diff --git a/common/src/main/java/org/geysermc/common/AuthType.java b/common/src/main/java/org/geysermc/common/AuthType.java index bec51560..8edbc4d5 100644 --- a/common/src/main/java/org/geysermc/common/AuthType.java +++ b/common/src/main/java/org/geysermc/common/AuthType.java @@ -14,6 +14,13 @@ public enum AuthType { return id < VALUES.length ? VALUES[id] : OFFLINE; } + /** + * Convert the AuthType string (from config) to the enum, OFFLINE on fail + * + * @param name AuthType string + * + * @return The converted AuthType + */ public static AuthType getByName(String name) { String upperCase = name.toUpperCase(); for (AuthType type : VALUES) { diff --git a/common/src/main/java/org/geysermc/common/ChatColor.java b/common/src/main/java/org/geysermc/common/ChatColor.java index e60012e7..8868b063 100644 --- a/common/src/main/java/org/geysermc/common/ChatColor.java +++ b/common/src/main/java/org/geysermc/common/ChatColor.java @@ -51,6 +51,13 @@ public class ChatColor { public static final String ITALIC = ESCAPE + "o"; public static final String RESET = ESCAPE + "r"; + /** + * Convert chat colour codes to terminal colours + * + * @param string The text to replace colours for + * + * @return A string ready for terminal printing + */ public static String toANSI(String string) { string = string.replace(BOLD, (char) 0x1b + "[1m"); string = string.replace(OBFUSCATED, (char) 0x1b + "[5m"); @@ -81,6 +88,13 @@ public class ChatColor { return message.replace(color, ESCAPE); } + /** + * Remove all colour formatting tags from a message + * + * @param message Message to remove colour tags from + * + * @return The sanitised message + */ public static String stripColors(String message) { return message = message.replaceAll("(&([a-fk-or0-9]))","").replaceAll("(§([a-fk-or0-9]))","").replaceAll("s/\\x1b\\[[0-9;]*[a-zA-Z]//g",""); } diff --git a/common/src/main/java/org/geysermc/common/bootstrap/IGeyserBootstrap.java b/common/src/main/java/org/geysermc/common/bootstrap/IGeyserBootstrap.java index 280723aa..5df61953 100644 --- a/common/src/main/java/org/geysermc/common/bootstrap/IGeyserBootstrap.java +++ b/common/src/main/java/org/geysermc/common/bootstrap/IGeyserBootstrap.java @@ -31,13 +31,34 @@ import org.geysermc.common.logger.IGeyserLogger; public interface IGeyserBootstrap { + /** + * Called when the GeyserBootstrap is enabled + */ void onEnable(); + /** + * Called when the GeyserBootstrap is disabled + */ void onDisable(); + /** + * Returns the current GeyserConfig + * + * @return The current GeyserConfig + */ IGeyserConfiguration getGeyserConfig(); + /** + * Returns the current GeyserLogger + * + * @return The current GeyserLogger + */ IGeyserLogger getGeyserLogger(); + /** + * Returns the current GeyserCommandManager + * + * @return The current GeyserCommandManager + */ ICommandManager getGeyserCommandManager(); } diff --git a/common/src/main/java/org/geysermc/common/command/ICommandManager.java b/common/src/main/java/org/geysermc/common/command/ICommandManager.java index 53e85fc7..f46dfafc 100644 --- a/common/src/main/java/org/geysermc/common/command/ICommandManager.java +++ b/common/src/main/java/org/geysermc/common/command/ICommandManager.java @@ -27,5 +27,12 @@ package org.geysermc.common.command; public interface ICommandManager { + /** + * Returns the description of the given command + * + * @param command Command to get the description for + * + * @return Command description + */ String getDescription(String command); } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/TropicalFishEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/TropicalFishEntity.java index 5addcc2e..3ded4cbf 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/TropicalFishEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/TropicalFishEntity.java @@ -44,8 +44,8 @@ public class TropicalFishEntity extends AbstractFishEntity { @Override public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { if (entityMetadata.getId() == 16) { - // Still not always the right model and colour is broken TropicalFishVariant variant = TropicalFishVariant.fromVariantNumber((int) entityMetadata.getValue()); + metadata.put(EntityData.VARIANT, variant.getShape()); // Shape 0-1 metadata.put(EntityData.MARK_VARIANT, variant.getPattern()); // Pattern 0-5 metadata.put(EntityData.COLOR, variant.getBaseColor()); // Base color 0-15 @@ -80,6 +80,13 @@ public class TropicalFishEntity extends AbstractFishEntity { private byte baseColor; private byte patternColor; + /** + * Convert the variant number from Java into separate values + * + * @param varNumber Variant number from Java edition + * + * @return The variant converted into TropicalFishVariant + */ public static TropicalFishVariant fromVariantNumber(int varNumber) { return new TropicalFishVariant((varNumber & 0xFF), ((varNumber >> 8) & 0xFF), (byte) ((varNumber >> 16) & 0xFF), (byte) ((varNumber >> 24) & 0xFF)); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaServerDeclareCommandsTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaServerDeclareCommandsTranslator.java index a383c5cc..edc20a64 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaServerDeclareCommandsTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaServerDeclareCommandsTranslator.java @@ -55,7 +55,7 @@ public class JavaServerDeclareCommandsTranslator extends PacketTranslator children; + /** + * Create a new parameter info object + * + * @param paramNode CommandNode the parameter is for + * @param paramData The existing parameters for the command + */ public ParamInfo(CommandNode paramNode, CommandParamData paramData) { this.paramNode = paramNode; this.paramData = paramData; this.children = new ArrayList<>(); } + /** + * Build the array of all the child parameters (recursive) + * + * @param allNodes Every command node + */ public void buildChildren(CommandNode[] allNodes) { int enumIndex = -1; @@ -247,6 +273,11 @@ public class JavaServerDeclareCommandsTranslator extends PacketTranslator getTree() { List treeParamData = new ArrayList<>(); diff --git a/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java b/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java index 199c5a5c..9d874f13 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java @@ -61,6 +61,12 @@ public class DimensionUtils { session.getUpstream().sendPacket(stopSoundPacket); } + /** + * Map the Java edition dimension IDs to Bedrock edition + * + * @param javaDimension Dimension ID to convert + * @return Converted Bedrock edition dimension ID + */ public static int javaToBedrock(int javaDimension) { switch (javaDimension) { case -1: diff --git a/connector/src/main/java/org/geysermc/connector/utils/EntityUtils.java b/connector/src/main/java/org/geysermc/connector/utils/EntityUtils.java index ec1ff451..79ce9e8b 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/EntityUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/EntityUtils.java @@ -32,6 +32,12 @@ import org.geysermc.connector.entity.type.EntityType; public class EntityUtils { + /** + * Convert Java edition effect IDs to Bedrock edition + * + * @param effect Effect to convert + * @return The numeric ID for the Bedrock edition effect + */ public static int toBedrockEffectId(Effect effect) { switch (effect) { case GLOWING: @@ -51,6 +57,13 @@ public class EntityUtils { return effect.ordinal() + 1; } } + + /** + * Converts a MobType to a Bedrock edition EntityType, returns null if the EntityType is not found + * + * @param type The MobType to convert + * @return Converted EntityType + */ public static EntityType toBedrockEntity(MobType type) { try { return EntityType.valueOf(type.name()); @@ -59,6 +72,12 @@ public class EntityUtils { } } + /** + * Converts a ObjectType to a Bedrock edition EntityType, returns null if the EntityType is not found + * + * @param type The ObjectType to convert + * @return Converted EntityType + */ public static EntityType toBedrockEntity(ObjectType type) { try { return EntityType.valueOf(type.name()); diff --git a/connector/src/main/java/org/geysermc/connector/utils/FileUtils.java b/connector/src/main/java/org/geysermc/connector/utils/FileUtils.java index 0938fa7c..23da3746 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/FileUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/FileUtils.java @@ -27,24 +27,51 @@ package org.geysermc.connector.utils; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; - import org.geysermc.connector.GeyserConnector; -import java.io.*; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.util.function.Function; public class FileUtils { + /** + * Load the given YAML file into the given class + * + * @param src File to load + * @param valueType Class to load file into + * @return The data as the given class + * @throws IOException + */ public static T loadConfig(File src, Class valueType) throws IOException { ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory()); return objectMapper.readValue(src, valueType); } - public static File fileOrCopiedFromResource(String name, Function s) throws IOException { - return fileOrCopiedFromResource(new File(name), name, s); + /** + * Open the specified file or copy if from resources + * + * @param name File and resource name + * @param fallback Formatting callback + * @return File handle of the specified file + * @throws IOException + */ + public static File fileOrCopiedFromResource(String name, Function fallback) throws IOException { + return fileOrCopiedFromResource(new File(name), name, fallback); } - public static File fileOrCopiedFromResource(File file, String name, Function s) throws IOException { + /** + * Open the specified file or copy if from resources + * + * @param file File to open + * @param name Name of the resource get if needed + * @param format Formatting callback + * @return File handle of the specified file + * @throws IOException + */ + public static File fileOrCopiedFromResource(File file, String name, Function format) throws IOException { if (!file.exists()) { file.createNewFile(); FileOutputStream fos = new FileOutputStream(file); @@ -54,7 +81,7 @@ public class FileUtils { input.read(bytes); - for(char c : s.apply(new String(bytes)).toCharArray()) { + for(char c : format.apply(new String(bytes)).toCharArray()) { fos.write(c); } @@ -66,6 +93,13 @@ public class FileUtils { return file; } + /** + * Writes the given data to the specified file on disk + * + * @param file File to write to + * @param data Data to write to the file + * @throws IOException + */ public static void writeFile(File file, char[] data) throws IOException { if (!file.exists()) { file.createNewFile(); @@ -81,6 +115,13 @@ public class FileUtils { fos.close(); } + /** + * Writes the given data to the specified file on disk + * + * @param name File path to write to + * @param data Data to write to the file + * @throws IOException + */ public static void writeFile(String name, char[] data) throws IOException { writeFile(new File(name), data); } diff --git a/connector/src/main/java/org/geysermc/connector/utils/LocaleUtils.java b/connector/src/main/java/org/geysermc/connector/utils/LocaleUtils.java index e8555eb0..726ad1c1 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/LocaleUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/LocaleUtils.java @@ -57,9 +57,15 @@ public class LocaleUtils { downloadAndLoadLocale(DEFAULT_LOCALE); } + /** + * Fetch the latest versions asset cache from Mojang so we can grab the locale files later + */ private static void generateAssetCache() { try { + // Get the version manifest from Mojang VersionManifest versionManifest = Toolbox.JSON_MAPPER.readValue(WebUtils.getBody("https://launchermeta.mojang.com/mc/game/version_manifest.json"), VersionManifest.class); + + // Get the url for the latest version of the games manifest String latestInfoURL = ""; for (Version version : versionManifest.getVersions()) { if (version.getId().equals(versionManifest.getLatestVersion().getRelease())) { @@ -68,12 +74,15 @@ public class LocaleUtils { } } + // Make sure we definitely got a version if (latestInfoURL.isEmpty()) { throw new Exception("Unable to get latest Minecraft version"); } + // Get the individual version manifest VersionInfo versionInfo = Toolbox.JSON_MAPPER.readValue(WebUtils.getBody(latestInfoURL), VersionInfo.class); + // Get the smallest jar for use when downloading the en_us locale, will be either the server or client int currentSize = Integer.MAX_VALUE; for (VersionDownload download : versionInfo.getDownloads().values()) { if (download.getUrl().endsWith(".jar") && download.getSize() < currentSize) { @@ -82,8 +91,10 @@ public class LocaleUtils { } } + // Get the assets list JsonNode assets = Toolbox.JSON_MAPPER.readTree(WebUtils.getBody(versionInfo.getAssetIndex().getUrl())).get("objects"); + // Put each asset into an array for use later Iterator> assetIterator = assets.fields(); while (assetIterator.hasNext()) { Map.Entry entry = assetIterator.next(); @@ -95,8 +106,15 @@ public class LocaleUtils { } } + /** + * Downloads a locale from Mojang if its not already loaded + * + * @param locale Locale to download and load + */ public static void downloadAndLoadLocale(String locale) { locale = locale.toLowerCase(); + + // Check the locale isn't already loaded if (!ASSET_MAP.containsKey("minecraft/lang/" + locale + ".json") && !locale.equals("en_us")) { GeyserConnector.getInstance().getLogger().warning("Invalid locale requested to download and load: " + locale); return; @@ -108,9 +126,15 @@ public class LocaleUtils { loadLocale(locale); } + /** + * Downloads the specified locale if its not already downloaded + * + * @param locale Locale to download + */ private static void downloadLocale(String locale) { File localeFile = new File("locales/" + locale + ".json"); + // Check if we have already downloaded the locale file if (localeFile.exists()) { GeyserConnector.getInstance().getLogger().debug("Locale already downloaded: " + locale); return; @@ -128,6 +152,11 @@ public class LocaleUtils { WebUtils.downloadFile("http://resources.download.minecraft.net/" + hash.substring(0, 2) + "/" + hash, "locales/" + locale + ".json"); } + /** + * Loads a locale already downloaded, if the file doesn't exist it just logs a warning + * + * @param locale Locale to load + */ private static void loadLocale(String locale) { File localeFile = new File("locales/" + locale + ".json"); @@ -146,7 +175,7 @@ public class LocaleUtils { try { localeObj = Toolbox.JSON_MAPPER.readTree(localeStream); } catch (Exception e) { - throw new AssertionError("Unable to load Java lang map for " + locale, e); + throw new AssertionError("Unable to load Java edition lang map for " + locale, e); } // Parse all the locale fields @@ -164,6 +193,11 @@ public class LocaleUtils { } } + /** + * Download then en_us locale by downloading the server jar and extracting it from there. + * + * @param localeFile File to save the locale to + */ private static void downloadEN_US(File localeFile) { try { // Let the user know we are downloading the JAR @@ -199,6 +233,13 @@ public class LocaleUtils { } } + /** + * Translate the given language string into the given locale, or falls back to the default locale + * + * @param messageText Language string to translate + * @param locale Locale to translate to + * @return Translated string or the original message if it was not found in the given locale + */ public static String getLocaleString(String messageText, String locale) { Map localeStrings = LocaleUtils.LOCALE_MAPPINGS.get(locale.toLowerCase()); if (localeStrings == null) diff --git a/connector/src/main/java/org/geysermc/connector/utils/MathUtils.java b/connector/src/main/java/org/geysermc/connector/utils/MathUtils.java index 79f8c274..4e8497c6 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/MathUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/MathUtils.java @@ -27,6 +27,12 @@ package org.geysermc.connector.utils; public class MathUtils { + /** + * Round the given float to the next whole number + * + * @param floatNumber Float to round + * @return Rounded number + */ public static int ceil(float floatNumber) { int truncated = (int) floatNumber; return floatNumber > truncated ? truncated + 1 : truncated; diff --git a/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java b/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java index 5be8eab1..c00d4bd5 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java @@ -121,6 +121,13 @@ public class MessageUtils { return getTranslatedBedrockMessage(message, null, false); } + /** + * Inserts the given parameters into the given message both in sequence and as requested + * + * @param message Message containing possible parameter replacement strings + * @param params A list of parameter strings + * @return Parsed message with all params inserted as needed + */ public static String insertParams(String message, List params) { String newMessage = message; @@ -130,7 +137,7 @@ public class MessageUtils { try { newMessage = newMessage.replaceFirst("%" + m.group(1) + "\\$s" , params.get(Integer.parseInt(m.group(1)) - 1)); } catch (Exception e) { - // Couldnt find the param to replace + // Couldn't find the param to replace } } @@ -141,6 +148,12 @@ public class MessageUtils { return newMessage; } + /** + * Gets the colour for the message style or fetches it from the parent (recursive) + * + * @param style The style to get the colour from + * @return Colour string to be used + */ private static String getColorOrParent(MessageStyle style) { ChatColor chatColor = style.getColor(); @@ -151,6 +164,12 @@ public class MessageUtils { return getColor(chatColor); } + /** + * Convert a ChatColor into a string for inserting into messages + * + * @param color ChatColor to convert + * @return The converted color string + */ private static String getColor(ChatColor color) { String base = "\u00a7"; switch (color) { @@ -213,6 +232,12 @@ public class MessageUtils { return base; } + /** + * Convert a list of ChatFormats into a string for inserting into messages + * + * @param formats ChatFormats to convert + * @return The converted chat formatting string + */ private static String getFormat(List formats) { StringBuilder str = new StringBuilder(); for (ChatFormat cf : formats) { @@ -243,6 +268,12 @@ public class MessageUtils { return str.toString(); } + /** + * Checks if the given text string is a json message + * + * @param text String to test + * @return True if its a valid message json string, false if not + */ public static boolean isMessage(String text) { JsonParser parser = new JsonParser(); try { @@ -296,6 +327,13 @@ public class MessageUtils { return ""; } + /** + * Checks if the given message is over 256 characters (Java edition server chat limit) and sends a message to the user if it is + * + * @param message Message to check + * @param session GeyserSession for the user + * @return True if the message is too long, false if not + */ public static boolean isTooLong(String message, GeyserSession session) { if (message.length() > 256) { // TODO: Add Geyser localization and translate this based on language diff --git a/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java b/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java index 7a5b9798..9480cffd 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java @@ -105,6 +105,12 @@ public class SkinUtils { private String capeUrl; private boolean alex; + /** + * Generate the GameProfileData from the given GameProfile + * + * @param profile GameProfile to build the GameProfileData from + * @return The built GameProfileData + */ public static GameProfileData from(GameProfile profile) { try { GameProfile.Property skinProperty = profile.getProperty("textures"); @@ -189,6 +195,12 @@ public class SkinUtils { }); } + /** + * Create a basic geometry json for the given name + * + * @param geometryName Geometry name to use + * @return Geometry data as a json string + */ private static String getLegacySkinGeometry(String geometryName) { return "{\"geometry\" :{\"default\" :\"" + geometryName + "\"}}"; } diff --git a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java index 9c1e10f6..989f9a3a 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java +++ b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java @@ -110,6 +110,12 @@ public class Toolbox { LocaleUtils.init(); } + /** + * Get an InputStream for the given resource path, throws AssertionError if resource is not found + * + * @param resource Resource to get + * @return InputStream of the given resource + */ public static InputStream getResource(String resource) { InputStream stream = Toolbox.class.getClassLoader().getResourceAsStream(resource); if (stream == null) { diff --git a/connector/src/main/java/org/geysermc/connector/utils/WebUtils.java b/connector/src/main/java/org/geysermc/connector/utils/WebUtils.java index 065d683a..50ab76d0 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/WebUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/WebUtils.java @@ -36,6 +36,12 @@ import java.nio.file.StandardCopyOption; public class WebUtils { + /** + * Makes a web request to the given URL and returns the body as a string + * + * @param reqURL URL to fetch + * @return Body contents or error message if the request fails + */ public static String getBody(String reqURL) { URL url = null; try { @@ -61,6 +67,12 @@ public class WebUtils { } } + /** + * Downloads a file from the given URL and saves it to disk + * + * @param reqURL File to fetch + * @param fileLocation Location to save on disk + */ public static void downloadFile(String reqURL, String fileLocation) { try { InputStream in = new URL(reqURL).openStream(); From 94ecb2c6c7f112ecda64eb1ec7b84af21ec63e1f Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Tue, 21 Apr 2020 01:32:32 -0400 Subject: [PATCH 103/109] Block entity rewrite (#382) * Initial attempt * Rewrite of the rewrite * First working implementation * Far better working implementation * Clean up imports * Remove commented code * Cleanup code; change things * Remove unused imports * Cleanup code * Add licenses; add comment * More cleanup * Clarifications * It complained about a JavaDoc comment * Update access permissions * Switch from reflections to iteration over BlockEntityTranslators --- .../network/translators/Translators.java | 25 ++-- .../translators/block/BlockStateValues.java | 127 ++++++++++++++++++ .../translators/block/BlockTranslator.java | 64 +++------ .../entity/BannerBlockEntityTranslator.java | 19 ++- .../entity/BedBlockEntityTranslator.java | 59 ++++---- .../translators/block/entity/BlockEntity.java | 45 +++++++ .../block/entity/BlockEntityTranslator.java | 8 +- .../entity/CampfireBlockEntityTranslator.java | 4 +- .../ContainerBlockEntityTranslator.java | 80 ----------- .../entity/EmptyBlockEntityTranslator.java | 4 +- .../EndGatewayBlockEntityTranslator.java | 5 +- .../block/entity/RequiresBlockState.java | 42 ++++++ .../entity/SignBlockEntityTranslator.java | 5 +- .../entity/SkullBlockEntityTranslator.java | 62 +++++---- .../java/world/JavaChunkDataTranslator.java | 24 +--- .../world/JavaUpdateTileEntityTranslator.java | 20 ++- .../geysermc/connector/utils/ChunkUtils.java | 68 ++++++---- 17 files changed, 402 insertions(+), 259 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/block/BlockStateValues.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntity.java delete mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ContainerBlockEntityTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/block/entity/RequiresBlockState.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java b/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java index f0098f3c..cffb85f1 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java @@ -91,15 +91,15 @@ public class Translators { if (Packet.class.isAssignableFrom(packet)) { Class targetPacket = (Class) packet; PacketTranslator translator = (PacketTranslator) clazz.newInstance(); - + Registry.registerJava(targetPacket, translator); - + } else if (BedrockPacket.class.isAssignableFrom(packet)) { Class targetPacket = (Class) packet; PacketTranslator translator = (PacketTranslator) clazz.newInstance(); - + Registry.registerBedrock(targetPacket, translator); - + } else { GeyserConnector.getInstance().getLogger().error("Class " + clazz.getCanonicalName() + " is annotated as a translator but has an invalid target packet."); } @@ -116,11 +116,18 @@ public class Translators { } private static void registerBlockEntityTranslators() { - blockEntityTranslators.put("Empty", new EmptyBlockEntityTranslator()); - blockEntityTranslators.put("Sign", new SignBlockEntityTranslator()); - blockEntityTranslators.put("Campfire", new CampfireBlockEntityTranslator()); - blockEntityTranslators.put("Banner", new BannerBlockEntityTranslator()); - blockEntityTranslators.put("EndGateway", new EndGatewayBlockEntityTranslator()); + Reflections ref = new Reflections("org.geysermc.connector.network.translators.block.entity"); + + for (Class clazz : ref.getTypesAnnotatedWith(BlockEntity.class)) { + + GeyserConnector.getInstance().getLogger().debug("Found annotated block entity: " + clazz.getCanonicalName()); + + try { + blockEntityTranslators.put(clazz.getAnnotation(BlockEntity.class).name(), (BlockEntityTranslator) clazz.newInstance()); + } catch (InstantiationException | IllegalAccessException e) { + GeyserConnector.getInstance().getLogger().error("Could not instantiate annotated block entity " + clazz.getCanonicalName() + "."); + } + } } private static void registerInventoryTranslators() { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockStateValues.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockStateValues.java new file mode 100644 index 00000000..19581c7e --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockStateValues.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.block; + +import com.fasterxml.jackson.databind.JsonNode; +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; +import it.unimi.dsi.fastutil.objects.Object2ByteMap; +import it.unimi.dsi.fastutil.objects.Object2ByteOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; + +import java.util.Map; + +/** + * Used for block entities if the Java block state contains Bedrock block information. + */ +public class BlockStateValues { + + private static final Object2IntMap BANNER_COLORS = new Object2IntOpenHashMap<>(); + private static final Object2ByteMap BED_COLORS = new Object2ByteOpenHashMap<>(); + private static final Object2ByteMap SKULL_VARIANTS = new Object2ByteOpenHashMap<>(); + private static final Object2ByteMap SKULL_ROTATIONS = new Object2ByteOpenHashMap<>(); + + /** + * Determines if the block state contains Bedrock block information + * @param entry The String -> JsonNode map used in BlockTranslator + * @param javaBlockState the Java Block State of the block + */ + public static void storeBlockStateValues(Map.Entry entry, BlockState javaBlockState) { + JsonNode bannerColor = entry.getValue().get("banner_color"); + if (bannerColor != null) { + BlockStateValues.BANNER_COLORS.put(javaBlockState, (byte) bannerColor.intValue()); + return; // There will never be a banner color and a skull variant + } + + JsonNode bedColor = entry.getValue().get("bed_color"); + if (bedColor != null) { + BlockStateValues.BED_COLORS.put(javaBlockState, (byte) bedColor.intValue()); + return; + } + + JsonNode skullVariation = entry.getValue().get("variation"); + if(skullVariation != null) { + BlockStateValues.SKULL_VARIANTS.put(javaBlockState, (byte) skullVariation.intValue()); + } + + JsonNode skullRotation = entry.getValue().get("skull_rotation"); + if (skullRotation != null) { + BlockStateValues.SKULL_ROTATIONS.put(javaBlockState, (byte) skullRotation.intValue()); + } + } + + /** + * Banner colors are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock. + * This gives an integer color that Bedrock can use. + * @param state BlockState of the block + * @return banner color integer or -1 if no color + */ + public static int getBannerColor(BlockState state) { + if (BANNER_COLORS.containsKey(state)) { + return BANNER_COLORS.getInt(state); + } + return -1; + } + + /** + * Bed colors are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock. + * This gives a byte color that Bedrock can use - Bedrock needs a byte in the final tag. + * @param state BlockState of the block + * @return bed color byte or -1 if no color + */ + public static byte getBedColor(BlockState state) { + if (BED_COLORS.containsKey(state)) { + return BED_COLORS.getByte(state); + } + return -1; + } + + /** + * Skull variations are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock. + * This gives a byte variant ID that Bedrock can use. + * @param state BlockState of the block + * @return skull variant byte or -1 if no variant + */ + public static byte getSkullVariant(BlockState state) { + if (SKULL_VARIANTS.containsKey(state)) { + return SKULL_VARIANTS.getByte(state); + } + return -1; + } + + /** + * + * @param state BlockState of the block + * @return skull rotation value or -1 if no value + */ + public static byte getSkullRotation(BlockState state) { + if (SKULL_ROTATIONS.containsKey(state)) { + return SKULL_ROTATIONS.getByte(state); + } + return -1; + } + +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java index d48b9a30..5b5d5c9c 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java @@ -42,12 +42,12 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; -import it.unimi.dsi.fastutil.objects.Object2ByteMap; -import it.unimi.dsi.fastutil.objects.Object2ByteOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.network.translators.block.entity.BlockEntity; import org.geysermc.connector.utils.Toolbox; +import org.reflections.Reflections; import java.io.InputStream; import java.util.*; @@ -66,9 +66,6 @@ public class BlockTranslator { public static final int CARPET = 171; private static final Map JAVA_ID_TO_BLOCK_ENTITY_MAP = new HashMap<>(); - private static final Object2ByteMap BED_COLORS = new Object2ByteOpenHashMap<>(); - private static final Object2ByteMap SKULL_VARIANTS = new Object2ByteOpenHashMap<>(); - private static final Object2ByteMap SKULL_ROTATIONS = new Object2ByteOpenHashMap<>(); public static final Int2DoubleMap JAVA_RUNTIME_ID_TO_HARDNESS = new Int2DoubleOpenHashMap(); public static final Int2BooleanMap JAVA_RUNTIME_ID_TO_CAN_HARVEST_WITH_HAND = new Int2BooleanOpenHashMap(); @@ -110,6 +107,9 @@ public class BlockTranslator { addedStatesMap.defaultReturnValue(-1); List paletteList = new ArrayList<>(); + Reflections ref = new Reflections("org.geysermc.connector.network.translators.block.entity"); + ref.getTypesAnnotatedWith(BlockEntity.class); + int waterRuntimeId = -1; int javaRuntimeId = -1; int bedrockRuntimeId = 0; @@ -145,28 +145,19 @@ public class BlockTranslator { JAVA_ID_BLOCK_MAP.put(javaId, javaBlockState); - if (javaId.contains("sign[")) { - JAVA_ID_TO_BLOCK_ENTITY_MAP.put(javaBlockState, javaId); + // Used for adding all "special" Java block states to block state map + String identifier; + String bedrock_identifer = entry.getValue().get("bedrock_identifier").asText(); + for (Class clazz : ref.getTypesAnnotatedWith(BlockEntity.class)) { + identifier = clazz.getAnnotation(BlockEntity.class).regex(); + // Endswith, or else the block bedrock gets picked up for bed + if (bedrock_identifer.endsWith(identifier) && !identifier.equals("")) { + JAVA_ID_TO_BLOCK_ENTITY_MAP.put(javaBlockState, clazz.getAnnotation(BlockEntity.class).name()); + break; + } } - - JsonNode skullVariation = entry.getValue().get("variation"); - if(skullVariation != null) { - SKULL_VARIANTS.put(javaBlockState, (byte) skullVariation.intValue()); - } - - JsonNode skullRotation = entry.getValue().get("skull_rotation"); - if (skullRotation != null) { - SKULL_ROTATIONS.put(javaBlockState, (byte) skullRotation.intValue()); - } - - // If the Java ID is bed, signal that it needs a tag to show color - // The color is in the namespace ID in Java Edition but it's a tag in Bedrock. - JsonNode bedColor = entry.getValue().get("bed_color"); - if (bedColor != null) { - // Converting to byte because the final tag value is a byte. bedColor.binaryValue() returns an array - BED_COLORS.put(javaBlockState, (byte) bedColor.intValue()); - } + BlockStateValues.storeBlockStateValues(entry, javaBlockState); if ("minecraft:water[level=0]".equals(javaId)) { waterRuntimeId = bedrockRuntimeId; @@ -186,7 +177,7 @@ public class BlockTranslator { addedStatesMap.put(blockTag, bedrockRuntimeId); paletteList.add(runtimeTag); } else { - int duplicateRuntimeId = addedStatesMap.get(blockTag); + int duplicateRuntimeId = addedStatesMap.getOrDefault(blockTag, -1); if (duplicateRuntimeId == -1) { GeyserConnector.getInstance().getLogger().debug("Mapping " + javaId + " was not found for bedrock edition!"); } else { @@ -274,27 +265,6 @@ public class BlockTranslator { return WATERLOGGED.contains(state.getId()); } - public static byte getBedColor(BlockState state) { - if (BED_COLORS.containsKey(state)) { - return BED_COLORS.getByte(state); - } - return -1; - } - - public static byte getSkullVariant(BlockState state) { - if (SKULL_VARIANTS.containsKey(state)) { - return SKULL_VARIANTS.getByte(state); - } - return -1; - } - - public static byte getSkullRotation(BlockState state) { - if (SKULL_ROTATIONS.containsKey(state)) { - return SKULL_ROTATIONS.getByte(state); - } - return -1; - } - public static BlockState getJavaWaterloggedState(int bedrockId) { return BEDROCK_TO_JAVA_BLOCK_MAP.get(1 << 31 | bedrockId); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BannerBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BannerBlockEntityTranslator.java index cf868fa3..22d26cb4 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BannerBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BannerBlockEntityTranslator.java @@ -25,20 +25,33 @@ package org.geysermc.connector.network.translators.block.entity; +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.tag.IntTag; import com.nukkitx.nbt.tag.StringTag; import com.nukkitx.nbt.tag.Tag; +import org.geysermc.connector.network.translators.block.BlockStateValues; import java.util.ArrayList; import java.util.List; -public class BannerBlockEntityTranslator extends BlockEntityTranslator { +@BlockEntity(name = "Banner", delay = false, regex = "banner") +public class BannerBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { @Override - public List> translateTag(CompoundTag tag) { + public boolean isBlock(BlockState blockState) { + return BlockStateValues.getBannerColor(blockState) != -1; + } + + @Override + public List> translateTag(CompoundTag tag, BlockState blockState) { List> tags = new ArrayList<>(); + int bannerColor = BlockStateValues.getBannerColor(blockState); + if (bannerColor != -1) { + tags.add(new IntTag("Base", 15 - bannerColor)); + } ListTag patterns = tag.get("Patterns"); List tagsList = new ArrayList<>(); if (tag.contains("Patterns")) { @@ -71,7 +84,7 @@ public class BannerBlockEntityTranslator extends BlockEntityTranslator { protected com.nukkitx.nbt.tag.CompoundTag getPattern(CompoundTag pattern) { return CompoundTagBuilder.builder() - .intTag("Color", (int) pattern.get("Color").getValue()) + .intTag("Color", 15 - (int) pattern.get("Color").getValue()) .stringTag("Pattern", (String) pattern.get("Pattern").getValue()) .buildRootTag(); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BedBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BedBlockEntityTranslator.java index 7522506a..a8dae253 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BedBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BedBlockEntityTranslator.java @@ -25,42 +25,43 @@ package org.geysermc.connector.network.translators.block.entity; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; -import com.nukkitx.math.vector.Vector3i; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.nukkitx.nbt.CompoundTagBuilder; -import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.block.BlockTranslator; -import org.geysermc.connector.utils.BlockEntityUtils; +import com.nukkitx.nbt.tag.ByteTag; +import com.nukkitx.nbt.tag.Tag; +import org.geysermc.connector.network.translators.block.BlockStateValues; -import java.util.concurrent.TimeUnit; +import java.util.ArrayList; +import java.util.List; -public class BedBlockEntityTranslator { +@BlockEntity(name = "Bed", delay = false, regex = "bed") +public class BedBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { - public static void checkForBedColor(GeyserSession session, BlockState blockState, Vector3i position) { - byte bedcolor = BlockTranslator.getBedColor(blockState); - // If Bed Color is not -1 then it is indeed a bed with a color. - if (bedcolor > -1) { - Position pos = new Position(position.getX(), position.getY(), position.getZ()); - com.nukkitx.nbt.tag.CompoundTag finalbedTag = getBedTag(bedcolor, pos); - // Delay needed, otherwise newly placed beds will not get their color - // Delay is not needed for beds already placed on login - session.getConnector().getGeneralThreadPool().schedule(() -> - BlockEntityUtils.updateBlockEntity(session, finalbedTag, pos), - 500, - TimeUnit.MILLISECONDS - ); - } + @Override + public boolean isBlock(BlockState blockState) { + return BlockStateValues.getBedColor(blockState) != -1; } - public static com.nukkitx.nbt.tag.CompoundTag getBedTag(byte bedcolor, Position pos) { - CompoundTagBuilder tagBuilder = CompoundTagBuilder.builder() - .intTag("x", pos.getX()) - .intTag("y", pos.getY()) - .intTag("z", pos.getZ()) - .stringTag("id", "Bed"); - tagBuilder.byteTag("color", bedcolor); + @Override + public List> translateTag(CompoundTag tag, BlockState blockState) { + List> tags = new ArrayList<>(); + byte bedcolor = BlockStateValues.getBedColor(blockState); + // Just in case... + if (bedcolor == -1) bedcolor = 0; + tags.add(new ByteTag("color", bedcolor)); + return tags; + } + + @Override + public CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) { + return null; + } + + @Override + public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { + CompoundTagBuilder tagBuilder = getConstantBedrockTag(bedrockId, x, y, z).toBuilder(); + tagBuilder.byteTag("color", (byte) 0); return tagBuilder.buildRootTag(); } - } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntity.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntity.java new file mode 100644 index 00000000..0321f2c1 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntity.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.block.entity; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(value = RetentionPolicy.RUNTIME) +public @interface BlockEntity { + /** + * Whether to delay the sending of the block entity + */ + boolean delay(); + /** + * The block entity name + */ + String name(); + /** + * The search term used in BlockTranslator + */ + String regex(); +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java index d7683c4a..f2825789 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java @@ -25,32 +25,32 @@ package org.geysermc.connector.network.translators.block.entity; +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.nukkitx.nbt.CompoundTagBuilder; import com.nukkitx.nbt.tag.Tag; -import lombok.AllArgsConstructor; import org.geysermc.connector.utils.BlockEntityUtils; import java.util.List; public abstract class BlockEntityTranslator { - public abstract List> translateTag(CompoundTag tag); + public abstract List> translateTag(CompoundTag tag, BlockState blockState); public abstract CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z); public abstract com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z); - public com.nukkitx.nbt.tag.CompoundTag getBlockEntityTag(String id, CompoundTag tag) { + public com.nukkitx.nbt.tag.CompoundTag getBlockEntityTag(String id, CompoundTag tag, BlockState blockState) { int x = Integer.parseInt(String.valueOf(tag.getValue().get("x").getValue())); int y = Integer.parseInt(String.valueOf(tag.getValue().get("y").getValue())); int z = Integer.parseInt(String.valueOf(tag.getValue().get("z").getValue())); CompoundTagBuilder tagBuilder = getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId(id), x, y, z).toBuilder(); - translateTag(tag).forEach(tagBuilder::tag); + translateTag(tag, blockState).forEach(tagBuilder::tag); return tagBuilder.buildRootTag(); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/CampfireBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/CampfireBlockEntityTranslator.java index ead43b06..11b7e864 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/CampfireBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/CampfireBlockEntityTranslator.java @@ -25,6 +25,7 @@ package org.geysermc.connector.network.translators.block.entity; +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.nukkitx.nbt.CompoundTagBuilder; @@ -37,10 +38,11 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; +@BlockEntity(name = "Campfire", delay = false, regex = "campfire") public class CampfireBlockEntityTranslator extends BlockEntityTranslator { @Override - public List> translateTag(CompoundTag tag) { + public List> translateTag(CompoundTag tag, BlockState blockState) { List> tags = new ArrayList<>(); ListTag items = tag.get("Items"); int i = 1; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ContainerBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ContainerBlockEntityTranslator.java deleted file mode 100644 index 7eb3b1a7..00000000 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ContainerBlockEntityTranslator.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * @author GeyserMC - * @link https://github.com/GeyserMC/Geyser - */ - -package org.geysermc.connector.network.translators.block.entity; - -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.nukkitx.nbt.CompoundTagBuilder; -import com.nukkitx.nbt.tag.Tag; - -import org.geysermc.connector.network.translators.Translators; -import org.geysermc.connector.network.translators.item.ItemEntry; - -import java.util.ArrayList; -import java.util.List; - -public class ContainerBlockEntityTranslator extends BlockEntityTranslator { - - @Override - public List> translateTag(CompoundTag tag) { - List> tags = new ArrayList<>(); - ListTag items = tag.get("Items"); - List tagsList = new ArrayList<>(); - for (com.github.steveice10.opennbt.tag.builtin.Tag itemTag : items.getValue()) { - tagsList.add(getItem((CompoundTag) itemTag)); - } - - com.nukkitx.nbt.tag.ListTag bedrockItems = - new com.nukkitx.nbt.tag.ListTag<>("Items", com.nukkitx.nbt.tag.CompoundTag.class, tagsList); - tags.add(bedrockItems); - return tags; - } - - @Override - public CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) { - CompoundTag tag = getConstantJavaTag(javaId, x, y, z); - tag.put(new ListTag("Items")); - return tag; - } - - @Override - public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { - CompoundTagBuilder tagBuilder = getConstantBedrockTag(bedrockId, x, y, z).toBuilder(); - tagBuilder.listTag("Items", com.nukkitx.nbt.tag.CompoundTag.class, new ArrayList<>()); - return tagBuilder.buildRootTag(); - } - - protected com.nukkitx.nbt.tag.CompoundTag getItem(CompoundTag tag) { - ItemEntry entry = Translators.getItemTranslator().getItemEntry((String) tag.get("id").getValue()); - CompoundTagBuilder tagBuilder = CompoundTagBuilder.builder() - .shortTag("id", (short) entry.getBedrockId()) - .byteTag("Count", (byte) tag.get("Count").getValue()) - .shortTag("Damage", (short) entry.getBedrockData()) - .byteTag("Slot", (byte) tag.get("Slot").getValue()) - .tag(CompoundTagBuilder.builder().build("tag")); - return tagBuilder.buildRootTag(); - } -} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java index a523eab2..e4601400 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java @@ -25,16 +25,18 @@ package org.geysermc.connector.network.translators.block.entity; +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.nukkitx.nbt.tag.Tag; import java.util.ArrayList; import java.util.List; +@BlockEntity(name = "Empty", delay = false, regex = "") public class EmptyBlockEntityTranslator extends BlockEntityTranslator { @Override - public List> translateTag(CompoundTag tag) { + public List> translateTag(CompoundTag tag, BlockState blockState) { return new ArrayList<>(); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EndGatewayBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EndGatewayBlockEntityTranslator.java index e66a0bcd..de5868a4 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EndGatewayBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EndGatewayBlockEntityTranslator.java @@ -25,6 +25,7 @@ package org.geysermc.connector.network.translators.block.entity; +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.LongTag; import com.nukkitx.nbt.CompoundTagBuilder; @@ -35,9 +36,11 @@ import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; +@BlockEntity(name = "EndGateway", delay = true, regex = "end_gateway") public class EndGatewayBlockEntityTranslator extends BlockEntityTranslator { + @Override - public List> translateTag(CompoundTag tag) { + public List> translateTag(CompoundTag tag, BlockState blockState) { List> tags = new ArrayList<>(); tags.add(new IntTag("Age", (int) (long) tag.get("Age").getValue())); // Java sometimes does not provide this tag, but Bedrock crashes if it doesn't exist diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/RequiresBlockState.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/RequiresBlockState.java new file mode 100644 index 00000000..ed8e6ede --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/RequiresBlockState.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.block.entity; + +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; + +/** + * Implemented in block entities if their Java block state is required for additional values in Bedrock + */ +public interface RequiresBlockState { + + /** + * Determines if block is part of class + * @param blockState BlockState to be compared + * @return true if part of the class + */ + boolean isBlock(BlockState blockState); + +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java index 658f665b..74dcdd13 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java @@ -25,21 +25,22 @@ package org.geysermc.connector.network.translators.block.entity; +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.mc.protocol.data.message.Message; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.nukkitx.nbt.CompoundTagBuilder; import com.nukkitx.nbt.tag.StringTag; import com.nukkitx.nbt.tag.Tag; - import org.geysermc.connector.utils.MessageUtils; import java.util.ArrayList; import java.util.List; +@BlockEntity(name = "Sign", delay = true, regex = "sign") public class SignBlockEntityTranslator extends BlockEntityTranslator { @Override - public List> translateTag(CompoundTag tag) { + public List> translateTag(CompoundTag tag, BlockState blockState) { List> tags = new ArrayList<>(); String line1 = getOrDefault(tag.getValue().get("Text1"), ""); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java index 12526d8e..2380663b 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java @@ -25,43 +25,47 @@ package org.geysermc.connector.network.translators.block.entity; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; -import com.nukkitx.math.vector.Vector3i; import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.tag.ByteTag; import com.nukkitx.nbt.tag.CompoundTag; -import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.block.BlockTranslator; -import org.geysermc.connector.utils.BlockEntityUtils; +import com.nukkitx.nbt.tag.FloatTag; +import com.nukkitx.nbt.tag.Tag; +import org.geysermc.connector.network.translators.block.BlockStateValues; -import java.util.concurrent.TimeUnit; +import java.util.ArrayList; +import java.util.List; -public class SkullBlockEntityTranslator { +@BlockEntity(name = "Skull", delay = false, regex = "skull") +public class SkullBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { - public static void checkForSkullVariant(GeyserSession session, BlockState blockState, Vector3i position) { - byte skullVariant = BlockTranslator.getSkullVariant(blockState); - byte rotation = BlockTranslator.getSkullRotation(blockState); - if (skullVariant > -1) { - Position pos = new Position(position.getX(), position.getY(), position.getZ()); - CompoundTag finalSkullTag = getSkullTag(skullVariant, pos, rotation); - // Delay needed, otherwise newly placed skulls will not appear - // Delay is not needed for skulls already placed on login - session.getConnector().getGeneralThreadPool().schedule(() -> - BlockEntityUtils.updateBlockEntity(session, finalSkullTag, pos), - 500, - TimeUnit.MILLISECONDS - ); - } + @Override + public boolean isBlock(BlockState blockState) { + return BlockStateValues.getSkullVariant(blockState) != -1; } - public static CompoundTag getSkullTag(byte skullvariant, Position pos, byte rotation) { - CompoundTagBuilder tagBuilder = CompoundTagBuilder.builder() - .intTag("x", pos.getX()) - .intTag("y", pos.getY()) - .intTag("z", pos.getZ()) - .stringTag("id", "Skull") - .floatTag("Rotation", rotation * 22.5f); - tagBuilder.byteTag("SkullType", skullvariant); + @Override + public List> translateTag(com.github.steveice10.opennbt.tag.builtin.CompoundTag tag, BlockState blockState) { + List> tags = new ArrayList<>(); + byte skullVariant = BlockStateValues.getSkullVariant(blockState); + float rotation = BlockStateValues.getSkullRotation(blockState) * 22.5f; + // Just in case... + if (skullVariant == -1) skullVariant = 0; + tags.add(new FloatTag("Rotation", rotation)); + tags.add(new ByteTag("SkullType", skullVariant)); + return tags; + } + + @Override + public com.github.steveice10.opennbt.tag.builtin.CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) { + return null; + } + + @Override + public CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { + CompoundTagBuilder tagBuilder = getConstantBedrockTag(bedrockId, x, y, z).toBuilder(); + tagBuilder.floatTag("Rotation", 0); + tagBuilder.byteTag("SkullType", (byte) 0); return tagBuilder.buildRootTag(); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java index 9309ca75..e72038c5 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java @@ -85,7 +85,7 @@ public class JavaChunkDataTranslator extends PacketTranslator blockEntityEntry : chunkData.signs.object2IntEntrySet()) { + // Some block entities need to be loaded in later or else text doesn't show (signs) or they crash the game (end gateway blocks) + for (Object2IntMap.Entry blockEntityEntry : chunkData.getLoadBlockEntitiesLater().object2IntEntrySet()) { int x = blockEntityEntry.getKey().getInt("x"); int y = blockEntityEntry.getKey().getInt("y"); int z = blockEntityEntry.getKey().getInt("z"); ChunkUtils.updateBlock(session, new BlockState(blockEntityEntry.getIntValue()), new Position(x, y, z)); } + chunkData.getLoadBlockEntitiesLater().clear(); - for (Object2IntMap.Entry blockEntityEntry : chunkData.gateways.object2IntEntrySet()) { - int x = blockEntityEntry.getKey().getInt("x"); - int y = blockEntityEntry.getKey().getInt("y"); - int z = blockEntityEntry.getKey().getInt("z"); - ChunkUtils.updateBlock(session, new BlockState(blockEntityEntry.getIntValue()), new Position(x, y, z)); - } - - for (Map.Entry blockEntityEntry: chunkData.beds.entrySet()) { - ChunkUtils.updateBlock(session, blockEntityEntry.getValue(), blockEntityEntry.getKey()); - } - for (Map.Entry blockEntityEntry: chunkData.skulls.entrySet()) { - ChunkUtils.updateBlock(session, blockEntityEntry.getValue(), blockEntityEntry.getKey()); - } - chunkData.signs.clear(); - chunkData.gateways.clear(); - chunkData.beds.clear(); - chunkData.skulls.clear(); } catch (Exception ex) { ex.printStackTrace(); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java index e6b5a335..b1158ef1 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java @@ -30,27 +30,35 @@ import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerUpdate import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.Translator; +import org.geysermc.connector.network.translators.block.entity.BlockEntity; import org.geysermc.connector.network.translators.block.entity.BlockEntityTranslator; import org.geysermc.connector.utils.BlockEntityUtils; +import org.geysermc.connector.utils.ChunkUtils; import java.util.concurrent.TimeUnit; @Translator(packet = ServerUpdateTileEntityPacket.class) public class JavaUpdateTileEntityTranslator extends PacketTranslator { + // This should be modified if sign text is not showing up + private static final int DELAY = 500; + @Override public void translate(ServerUpdateTileEntityPacket packet, GeyserSession session) { String id = BlockEntityUtils.getBedrockBlockEntityId(packet.getType().name()); BlockEntityTranslator translator = BlockEntityUtils.getBlockEntityTranslator(id); - if (id.equalsIgnoreCase("Sign")) { + // If not null then the BlockState is used in BlockEntityTranslator.translateTag() + if (ChunkUtils.CACHED_BLOCK_ENTITIES.get(packet.getPosition()) != null) { + BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag(id, packet.getNbt(), + ChunkUtils.CACHED_BLOCK_ENTITIES.get(packet.getPosition())), packet.getPosition()); + ChunkUtils.CACHED_BLOCK_ENTITIES.remove(packet.getPosition()); + } else if (translator.getClass().getAnnotation(BlockEntity.class).delay()) { // Delay so chunks can finish sending session.getConnector().getGeneralThreadPool().schedule(() -> - BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag("Sign", packet.getNbt()), packet.getPosition()), - 5, - TimeUnit.SECONDS - ); + BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag(id, packet.getNbt(), null), packet.getPosition()), + DELAY, TimeUnit.MILLISECONDS); } else { - BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag(id, packet.getNbt()), packet.getPosition()); + BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag(id, packet.getNbt(), null), packet.getPosition()); } } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java index c75664b8..d496215a 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -39,14 +39,13 @@ import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import lombok.Getter; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.block.entity.BlockEntityTranslator; -import org.geysermc.connector.network.translators.block.entity.SkullBlockEntityTranslator; -import org.geysermc.connector.world.chunk.ChunkPosition; +import org.geysermc.connector.network.translators.block.entity.*; import org.geysermc.connector.network.translators.Translators; import org.geysermc.connector.network.translators.block.BlockTranslator; -import org.geysermc.connector.network.translators.block.entity.BedBlockEntityTranslator; +import org.geysermc.connector.world.chunk.ChunkPosition; import org.geysermc.connector.world.chunk.ChunkSection; import java.util.HashMap; @@ -56,12 +55,20 @@ import static org.geysermc.connector.network.translators.block.BlockTranslator.B public class ChunkUtils { + /** + * Temporarily stores positions of BlockState values that are needed for certain block entities actively + */ + public static final Map CACHED_BLOCK_ENTITIES = new HashMap<>(); + public static ChunkData translateToBedrock(Column column) { ChunkData chunkData = new ChunkData(); Chunk[] chunks = column.getChunks(); chunkData.sections = new ChunkSection[chunks.length]; CompoundTag[] blockEntities = column.getTileEntities(); + // Temporarily stores positions of BlockState values per chunk load + Map blockEntityPositions = new HashMap<>(); + for (int chunkY = 0; chunkY < chunks.length; chunkY++) { chunkData.sections[chunkY] = new ChunkSection(); Chunk chunk = chunks[chunkY]; @@ -76,21 +83,19 @@ public class ChunkUtils { BlockState blockState = chunk.get(x, y, z); int id = BlockTranslator.getBedrockBlockId(blockState); - if (BlockTranslator.getBlockEntityString(blockState) != null && BlockTranslator.getBlockEntityString(blockState).contains("sign[")) { + // Check to see if the name is in BlockTranslator.getBlockEntityString, and therefore must be handled differently + if (BlockTranslator.getBlockEntityString(blockState) != null) { + // Get the block entity translator + BlockEntityTranslator blockEntityTranslator = BlockEntityUtils.getBlockEntityTranslator(BlockTranslator.getBlockEntityString(blockState)); Position pos = new ChunkPosition(column.getX(), column.getZ()).getBlock(x, (chunkY << 4) + y, z); - chunkData.signs.put(Translators.getBlockEntityTranslators().get("Sign").getDefaultBedrockTag("Sign", pos.getX(), pos.getY(), pos.getZ()), blockState.getId()); - } else if (BlockTranslator.getBlockEntityString(blockState) != null && BlockTranslator.getBlockEntityString(blockState).contains("end_gateway")) { - Position pos = new ChunkPosition(column.getX(), column.getZ()).getBlock(x, (chunkY << 4) + y, z); - chunkData.gateways.put(Translators.getBlockEntityTranslators().get("EndGateway").getDefaultBedrockTag("EndGateway", pos.getX(), pos.getY(), pos.getZ()), blockState.getId()); - } else if (BlockTranslator.getBedColor(blockState) > -1) { - Position pos = new ChunkPosition(column.getX(), column.getZ()).getBlock(x, (chunkY << 4) + y, z); - // Beds need to be updated separately to add the bed color tag - // Previously this was done by matching block state but this resulted in only one bed per color+orientation showing - chunkData.beds.put(pos, blockState); - } else if (BlockTranslator.getSkullVariant(blockState) > 0) { - Position pos = new ChunkPosition(column.getX(), column.getZ()).getBlock(x, (chunkY << 4) + y, z); - //Doing the same stuff as beds - chunkData.skulls.put(pos, blockState); + blockEntityPositions.put(pos, blockState); + // If there is a delay required for the block, allow it. + if (blockEntityTranslator.getClass().getAnnotation(BlockEntity.class).delay()) { + chunkData.loadBlockEntitiesLater.put(blockEntityTranslator.getDefaultBedrockTag(BlockEntityUtils.getBedrockBlockEntityId(BlockTranslator.getBlockEntityString(blockState)), + pos.getX(), pos.getY(), pos.getZ()), blockState.getId()); + } else { + section.getBlockStorageArray()[0].setFullBlock(ChunkSection.blockPosition(x, y, z), id); + } } else { section.getBlockStorageArray()[0].setFullBlock(ChunkSection.blockPosition(x, y, z), id); } @@ -101,6 +106,7 @@ public class ChunkUtils { } } } + } com.nukkitx.nbt.tag.CompoundTag[] bedrockBlockEntities = new com.nukkitx.nbt.tag.CompoundTag[blockEntities.length]; @@ -116,7 +122,8 @@ public class ChunkUtils { String id = BlockEntityUtils.getBedrockBlockEntityId(tagName); BlockEntityTranslator blockEntityTranslator = BlockEntityUtils.getBlockEntityTranslator(id); - bedrockBlockEntities[i] = blockEntityTranslator.getBlockEntityTag(tagName, tag); + BlockState blockState = blockEntityPositions.get(new Position((int) tag.get("x").getValue(), (int) tag.get("y").getValue(), (int) tag.get("z").getValue())); + bedrockBlockEntities[i] = blockEntityTranslator.getBlockEntityTag(tagName, tag, blockState); } chunkData.blockEntities = bedrockBlockEntities; @@ -162,10 +169,18 @@ public class ChunkUtils { } session.getUpstream().sendPacket(waterPacket); - // Since Java stores bed colors as part of the namespaced ID and Bedrock stores it as a tag + // Since Java stores bed colors/skull information as part of the namespaced ID and Bedrock stores it as a tag // This is the only place I could find that interacts with the Java block state and block updates - BedBlockEntityTranslator.checkForBedColor(session, blockState, position); - SkullBlockEntityTranslator.checkForSkullVariant(session, blockState, position); + // Iterates through all block entity translators and determines if the block state needs to be saved + for (Map.Entry entry : Translators.getBlockEntityTranslators().entrySet()) { + if (entry.getValue() instanceof RequiresBlockState) { + RequiresBlockState requiresBlockState = (RequiresBlockState) entry.getValue(); + if (requiresBlockState.isBlock(blockState)) { + CACHED_BLOCK_ENTITIES.put(new Position(position.getX(), position.getY(), position.getZ()), blockState); + break; //No block will be a part of two classes + } + } + } } public static void sendEmptyChunks(GeyserSession session, Vector3i position, int radius, boolean forceUpdate) { @@ -196,10 +211,9 @@ public class ChunkUtils { public static final class ChunkData { public ChunkSection[] sections; - public com.nukkitx.nbt.tag.CompoundTag[] blockEntities = new com.nukkitx.nbt.tag.CompoundTag[0]; - public Object2IntMap signs = new Object2IntOpenHashMap<>(); - public Object2IntMap gateways = new Object2IntOpenHashMap<>(); - public Map beds = new HashMap<>(); - public Map skulls = new HashMap<>(); + @Getter + private com.nukkitx.nbt.tag.CompoundTag[] blockEntities = new com.nukkitx.nbt.tag.CompoundTag[0]; + @Getter + private Object2IntMap loadBlockEntitiesLater = new Object2IntOpenHashMap<>(); } } From aad45369904204dd382c94acf370204223409171 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Tue, 21 Apr 2020 15:36:13 -0400 Subject: [PATCH 104/109] Fix /fly command (#396) * Fix /fly * Add comment --- .../java/entity/player/JavaPlayerAbilitiesTranslator.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerAbilitiesTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerAbilitiesTranslator.java index dcf6371d..3029f38e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerAbilitiesTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerAbilitiesTranslator.java @@ -27,6 +27,7 @@ package org.geysermc.connector.network.translators.java.entity.player; import java.util.Set; +import com.nukkitx.protocol.bedrock.data.CommandPermission; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; @@ -68,6 +69,8 @@ public class JavaPlayerAbilitiesTranslator extends PacketTranslator Date: Wed, 22 Apr 2020 06:41:25 +0100 Subject: [PATCH 105/109] Improved the outdated version kick message (#394) * Improved the outdated version kick message * Swapped 'server' to 'proxy' --- .../geysermc/connector/network/UpstreamPacketHandler.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java b/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java index 2ccb3723..4ad4deff 100644 --- a/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java @@ -46,8 +46,11 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { @Override public boolean handle(LoginPacket loginPacket) { - if (loginPacket.getProtocolVersion() != GeyserConnector.BEDROCK_PACKET_CODEC.getProtocolVersion()) { - session.getUpstream().disconnect("Unsupported Bedrock version. Are you running an outdated version?"); + if (loginPacket.getProtocolVersion() > GeyserConnector.BEDROCK_PACKET_CODEC.getProtocolVersion()) { + session.getUpstream().disconnect("Outdated Geyser proxy! I'm still on " + GeyserConnector.BEDROCK_PACKET_CODEC.getMinecraftVersion()); + return true; + } else if (loginPacket.getProtocolVersion() < GeyserConnector.BEDROCK_PACKET_CODEC.getProtocolVersion()) { + session.getUpstream().disconnect("Outdated Bedrock client! Please use " + GeyserConnector.BEDROCK_PACKET_CODEC.getMinecraftVersion()); return true; } From 87d2dd95b7f030cbde561f2f42a8ec0eaa0b590d Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Wed, 22 Apr 2020 00:45:29 -0500 Subject: [PATCH 106/109] Update what's left on README --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 056a83ca..f11b9bfb 100644 --- a/README.md +++ b/README.md @@ -28,12 +28,14 @@ Take a look [here](https://github.com/GeyserMC/Geyser/wiki#Setup) for how to set - Donate: https://patreon.com/GeyserMC ## What's Left to be Added/Fixed -- Inventories ([`inventory`](https://github.com/GeyserMC/Geyser/tree/inventory)) -- Crafting ([`inventory`](https://github.com/GeyserMC/Geyser/tree/inventory)) -- Creative Mode ([`inventory`](https://github.com/GeyserMC/Geyser/tree/inventory)) +- The Following Inventories + - [ ] Enchantment Table + - [ ] Beacon + - [ ] Cartography Table + - [ ] Stonecutter + - [ ] Villager Trading - Sounds - Block Particles -- Block Entities ([`inventory`](https://github.com/GeyserMC/Geyser/tree/inventory)) - Some Entity Flags ## Compiling From e8bf8ff2a0e1900f9ad0b52341f8eb4b80428ee8 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Wed, 22 Apr 2020 01:03:46 -0500 Subject: [PATCH 107/109] Fix javadoc related errors --- .../java/org/geysermc/connector/entity/Entity.java | 4 ++++ .../network/translators/block/BlockStateValues.java | 2 +- .../network/translators/block/entity/BlockEntity.java | 6 ++++++ .../org/geysermc/connector/scoreboard/Objective.java | 2 ++ .../java/org/geysermc/connector/utils/FileUtils.java | 10 +++++----- 5 files changed, 18 insertions(+), 6 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/Entity.java b/connector/src/main/java/org/geysermc/connector/entity/Entity.java index 177d0d7a..dcd2475a 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/Entity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/Entity.java @@ -120,6 +120,9 @@ public class Entity { } /** + * Despawns the entity + * + * @param session The GeyserSession * @return can be deleted */ public boolean despawnEntity(GeyserSession session) { @@ -234,6 +237,7 @@ public class Entity { /** * x = Pitch, y = HeadYaw, z = Yaw + * @return the bedrock rotation */ public Vector3f getBedrockRotation() { return Vector3f.from(rotation.getY(), rotation.getZ(), rotation.getX()); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockStateValues.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockStateValues.java index 19581c7e..25d6070f 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockStateValues.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockStateValues.java @@ -46,7 +46,7 @@ public class BlockStateValues { /** * Determines if the block state contains Bedrock block information - * @param entry The String -> JsonNode map used in BlockTranslator + * @param entry The String to JsonNode map used in BlockTranslator * @param javaBlockState the Java Block State of the block */ public static void storeBlockStateValues(Map.Entry entry, BlockState javaBlockState) { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntity.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntity.java index 0321f2c1..47cbbaf3 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntity.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntity.java @@ -30,16 +30,22 @@ import java.lang.annotation.RetentionPolicy; @Retention(value = RetentionPolicy.RUNTIME) public @interface BlockEntity { + /** * Whether to delay the sending of the block entity + * @return the delay for when sending the block entity */ boolean delay(); + /** * The block entity name + * @return the name of the block entity */ String name(); + /** * The search term used in BlockTranslator + * @return the search term used in BlockTranslator */ String regex(); } diff --git a/connector/src/main/java/org/geysermc/connector/scoreboard/Objective.java b/connector/src/main/java/org/geysermc/connector/scoreboard/Objective.java index d9d78dfd..c3e6c863 100644 --- a/connector/src/main/java/org/geysermc/connector/scoreboard/Objective.java +++ b/connector/src/main/java/org/geysermc/connector/scoreboard/Objective.java @@ -54,6 +54,8 @@ public class Objective { /** * /!\ This method is made for temporary objectives until the real objective is received + * @param scoreboard the scoreboard + * @param objectiveName the name of the objective */ public Objective(Scoreboard scoreboard, String objectiveName) { this(scoreboard); diff --git a/connector/src/main/java/org/geysermc/connector/utils/FileUtils.java b/connector/src/main/java/org/geysermc/connector/utils/FileUtils.java index 23da3746..dea42728 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/FileUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/FileUtils.java @@ -43,7 +43,7 @@ public class FileUtils { * @param src File to load * @param valueType Class to load file into * @return The data as the given class - * @throws IOException + * @throws IOException if the config could not be loaded */ public static T loadConfig(File src, Class valueType) throws IOException { ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory()); @@ -56,7 +56,7 @@ public class FileUtils { * @param name File and resource name * @param fallback Formatting callback * @return File handle of the specified file - * @throws IOException + * @throws IOException if the file failed to copy from resource */ public static File fileOrCopiedFromResource(String name, Function fallback) throws IOException { return fileOrCopiedFromResource(new File(name), name, fallback); @@ -69,7 +69,7 @@ public class FileUtils { * @param name Name of the resource get if needed * @param format Formatting callback * @return File handle of the specified file - * @throws IOException + * @throws IOException if the file failed to copy from resource */ public static File fileOrCopiedFromResource(File file, String name, Function format) throws IOException { if (!file.exists()) { @@ -98,7 +98,7 @@ public class FileUtils { * * @param file File to write to * @param data Data to write to the file - * @throws IOException + * @throws IOException if the file failed to write */ public static void writeFile(File file, char[] data) throws IOException { if (!file.exists()) { @@ -120,7 +120,7 @@ public class FileUtils { * * @param name File path to write to * @param data Data to write to the file - * @throws IOException + * @throws IOException if the file failed to write */ public static void writeFile(String name, char[] data) throws IOException { writeFile(new File(name), data); From a8805d9d713891554897bb94a4f873e97f8ff2fe Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Wed, 22 Apr 2020 01:51:49 -0500 Subject: [PATCH 108/109] Add a /geyser list command (Closes #342) --- .../connector/command/CommandManager.java | 2 + .../command/defaults/ListCommand.java | 50 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 connector/src/main/java/org/geysermc/connector/command/defaults/ListCommand.java diff --git a/connector/src/main/java/org/geysermc/connector/command/CommandManager.java b/connector/src/main/java/org/geysermc/connector/command/CommandManager.java index 16070099..24ce37a6 100644 --- a/connector/src/main/java/org/geysermc/connector/command/CommandManager.java +++ b/connector/src/main/java/org/geysermc/connector/command/CommandManager.java @@ -29,6 +29,7 @@ import lombok.Getter; import org.geysermc.common.command.ICommandManager; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.defaults.HelpCommand; +import org.geysermc.connector.command.defaults.ListCommand; import org.geysermc.connector.command.defaults.ReloadCommand; import org.geysermc.connector.command.defaults.StopCommand; @@ -47,6 +48,7 @@ public abstract class CommandManager implements ICommandManager { this.connector = connector; registerCommand(new HelpCommand(connector, "help", "Shows help for all registered commands.", "geyser.command.help")); + registerCommand(new ListCommand(connector, "list", "List all players connected through Geyser.", "geyser.command.list")); registerCommand(new ReloadCommand(connector, "reload", "Reloads the Geyser configurations. Kicks all players when used!", "geyser.command.reload")); registerCommand(new StopCommand(connector, "stop", "Shuts down Geyser.", "geyser.command.stop")); } diff --git a/connector/src/main/java/org/geysermc/connector/command/defaults/ListCommand.java b/connector/src/main/java/org/geysermc/connector/command/defaults/ListCommand.java new file mode 100644 index 00000000..21fa4253 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/command/defaults/ListCommand.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.command.defaults; + +import org.geysermc.common.ChatColor; +import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.command.CommandSender; +import org.geysermc.connector.command.GeyserCommand; +import org.geysermc.connector.network.session.GeyserSession; + +import java.util.stream.Collectors; + +public class ListCommand extends GeyserCommand { + + private GeyserConnector connector; + + public ListCommand(GeyserConnector connector, String name, String description, String permission) { + super(name, description, permission); + + this.connector = connector; + } + + @Override + public void execute(CommandSender sender, String[] args) { + sender.sendMessage(ChatColor.YELLOW + "Online Players (" + connector.getPlayers().size() + "): " + ChatColor.WHITE + connector.getPlayers().values().stream().map(GeyserSession::getName).collect(Collectors.joining(" "))); + } +} From 733ec2a0ec864ef4e010f9bb1441b4fae06ccbe0 Mon Sep 17 00:00:00 2001 From: ForceUpdate1 Date: Wed, 22 Apr 2020 23:26:16 +0200 Subject: [PATCH 109/109] Implement Updated Item Translator (#388) * add item translator * add item translator * add nbt item translator * fix empty list tags * formatting code * use Int2ObjectMap remove session * rename annotation --- .../geysermc/connector/entity/ItemEntity.java | 2 +- .../network/translators/ItemRemapper.java | 34 ++ .../translators/ItemStackTranslator.java | 250 ++++++++++++ .../translators/NbtItemStackTranslator.java | 45 +++ .../network/translators/Translators.java | 1 + .../inventory/PlayerInventoryTranslator.java | 20 +- .../action/InventoryActionDataTranslator.java | 4 +- .../updater/ChestInventoryUpdater.java | 4 +- .../updater/ContainerInventoryUpdater.java | 4 +- .../updater/CursorInventoryUpdater.java | 4 +- .../inventory/updater/InventoryUpdater.java | 4 +- .../network/translators/item/Enchantment.java | 2 +- .../translators/item/ItemTranslator.java | 364 ++++-------------- .../network/translators/item/Potion.java | 2 +- .../item/translators/PotionTranslator.java | 80 ++++ .../nbt/EnchantedBookTranslator.java | 66 ++++ .../nbt/EnchantmentTranslator.java | 140 +++++++ .../nbt/LeatherArmorTranslator.java | 73 ++++ .../translators/nbt/MapItemTranslator.java | 58 +++ .../java/JavaDeclareRecipesTranslator.java | 14 +- .../entity/JavaEntityEquipmentTranslator.java | 2 +- .../connector/utils/InventoryUtils.java | 2 +- 22 files changed, 859 insertions(+), 316 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/ItemRemapper.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/ItemStackTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/NbtItemStackTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/item/translators/PotionTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantedBookTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantmentTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/LeatherArmorTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/MapItemTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/entity/ItemEntity.java b/connector/src/main/java/org/geysermc/connector/entity/ItemEntity.java index a8032307..a28b563b 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/ItemEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/ItemEntity.java @@ -49,7 +49,7 @@ public class ItemEntity extends Entity { itemPacket.setUniqueEntityId(geyserId); itemPacket.setFromFishing(false); itemPacket.getMetadata().putAll(metadata); - itemPacket.setItemInHand(Translators.getItemTranslator().translateToBedrock((ItemStack) entityMetadata.getValue())); + itemPacket.setItemInHand(Translators.getItemTranslator().translateToBedrock(session, (ItemStack) entityMetadata.getValue())); session.getUpstream().sendPacket(itemPacket); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/ItemRemapper.java b/connector/src/main/java/org/geysermc/connector/network/translators/ItemRemapper.java new file mode 100644 index 00000000..6c286da2 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/ItemRemapper.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(value = RetentionPolicy.RUNTIME) +public @interface ItemRemapper { + int priority() default 0; +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/ItemStackTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/ItemStackTranslator.java new file mode 100644 index 00000000..ac4bb2f2 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/ItemStackTranslator.java @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.message.Message; +import com.github.steveice10.opennbt.tag.builtin.*; +import com.nukkitx.nbt.tag.CompoundTag; +import com.nukkitx.nbt.tag.Tag; +import com.nukkitx.protocol.bedrock.data.ItemData; +import org.geysermc.connector.network.translators.item.ItemEntry; +import org.geysermc.connector.utils.MessageUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public abstract class ItemStackTranslator { + + public ItemData translateToBedrock(ItemStack itemStack, ItemEntry itemEntry) { + if (itemStack == null) { + return ItemData.AIR; + } + if (itemStack.getNbt() == null) { + return ItemData.of(itemEntry.getBedrockId(), (short) itemEntry.getBedrockData(), itemStack.getAmount()); + } + return ItemData.of(itemEntry.getBedrockId(), (short) itemEntry.getBedrockData(), itemStack.getAmount(), this.translateNbtToBedrock(itemStack.getNbt())); + } + + public ItemStack translateToJava(ItemData itemData, ItemEntry itemEntry) { + if (itemData == null) return null; + if (itemData.getTag() == null) { + return new ItemStack(itemEntry.getJavaId(), itemData.getCount()); + } + return new ItemStack(itemEntry.getJavaId(), itemData.getCount(), this.translateToJavaNBT(itemData.getTag())); + } + + public abstract List getAppliedItems(); + + public CompoundTag translateNbtToBedrock(com.github.steveice10.opennbt.tag.builtin.CompoundTag tag) { + Map> javaValue = new HashMap>(); + if (tag.getValue() != null && !tag.getValue().isEmpty()) { + for (String str : tag.getValue().keySet()) { + com.github.steveice10.opennbt.tag.builtin.Tag javaTag = tag.get(str); + com.nukkitx.nbt.tag.Tag translatedTag = translateToBedrockNBT(javaTag); + if (translatedTag == null) + continue; + + javaValue.put(translatedTag.getName(), translatedTag); + } + } + + com.nukkitx.nbt.tag.CompoundTag bedrockTag = new com.nukkitx.nbt.tag.CompoundTag(tag.getName(), javaValue); + return bedrockTag; + } + + private com.nukkitx.nbt.tag.Tag translateToBedrockNBT(com.github.steveice10.opennbt.tag.builtin.Tag tag) { + if (tag instanceof ByteArrayTag) { + ByteArrayTag byteArrayTag = (ByteArrayTag) tag; + return new com.nukkitx.nbt.tag.ByteArrayTag(byteArrayTag.getName(), byteArrayTag.getValue()); + } + + if (tag instanceof ByteTag) { + ByteTag byteTag = (ByteTag) tag; + return new com.nukkitx.nbt.tag.ByteTag(byteTag.getName(), byteTag.getValue()); + } + + if (tag instanceof DoubleTag) { + DoubleTag doubleTag = (DoubleTag) tag; + return new com.nukkitx.nbt.tag.DoubleTag(doubleTag.getName(), doubleTag.getValue()); + } + + if (tag instanceof FloatTag) { + FloatTag floatTag = (FloatTag) tag; + return new com.nukkitx.nbt.tag.FloatTag(floatTag.getName(), floatTag.getValue()); + } + + if (tag instanceof IntArrayTag) { + IntArrayTag intArrayTag = (IntArrayTag) tag; + return new com.nukkitx.nbt.tag.IntArrayTag(intArrayTag.getName(), intArrayTag.getValue()); + } + + if (tag instanceof IntTag) { + IntTag intTag = (IntTag) tag; + return new com.nukkitx.nbt.tag.IntTag(intTag.getName(), intTag.getValue()); + } + + if (tag instanceof LongArrayTag) { + LongArrayTag longArrayTag = (LongArrayTag) tag; + return new com.nukkitx.nbt.tag.LongArrayTag(longArrayTag.getName(), longArrayTag.getValue()); + } + + if (tag instanceof LongTag) { + LongTag longTag = (LongTag) tag; + return new com.nukkitx.nbt.tag.LongTag(longTag.getName(), longTag.getValue()); + } + + if (tag instanceof ShortTag) { + ShortTag shortTag = (ShortTag) tag; + return new com.nukkitx.nbt.tag.ShortTag(shortTag.getName(), shortTag.getValue()); + } + + if (tag instanceof StringTag) { + StringTag stringTag = (StringTag) tag; + return new com.nukkitx.nbt.tag.StringTag(stringTag.getName(), MessageUtils.getBedrockMessage(Message.fromString(stringTag.getValue()))); + } + + if (tag instanceof ListTag) { + ListTag listTag = (ListTag) tag; + + List tagList = new ArrayList<>(); + for (com.github.steveice10.opennbt.tag.builtin.Tag value : listTag) { + tagList.add(translateToBedrockNBT(value)); + } + Class clazz = CompoundTag.class; + if (!tagList.isEmpty()) { + clazz = tagList.get(0).getClass(); + } + return new com.nukkitx.nbt.tag.ListTag(listTag.getName(), clazz, tagList); + } + + if (tag instanceof com.github.steveice10.opennbt.tag.builtin.CompoundTag) { + com.github.steveice10.opennbt.tag.builtin.CompoundTag compoundTag = (com.github.steveice10.opennbt.tag.builtin.CompoundTag) tag; + + return translateNbtToBedrock(compoundTag); + } + + return null; + } + + public com.github.steveice10.opennbt.tag.builtin.CompoundTag translateToJavaNBT(com.nukkitx.nbt.tag.CompoundTag tag) { + com.github.steveice10.opennbt.tag.builtin.CompoundTag javaTag = new com.github.steveice10.opennbt.tag.builtin.CompoundTag(tag.getName()); + Map javaValue = javaTag.getValue(); + if (tag.getValue() != null && !tag.getValue().isEmpty()) { + for (String str : tag.getValue().keySet()) { + com.nukkitx.nbt.tag.Tag bedrockTag = tag.get(str); + com.github.steveice10.opennbt.tag.builtin.Tag translatedTag = translateToJavaNBT(bedrockTag); + if (translatedTag == null) + continue; + + javaValue.put(translatedTag.getName(), translatedTag); + } + } + + javaTag.setValue(javaValue); + return javaTag; + } + + private com.github.steveice10.opennbt.tag.builtin.Tag translateToJavaNBT(com.nukkitx.nbt.tag.Tag tag) { + if (tag instanceof com.nukkitx.nbt.tag.ByteArrayTag) { + com.nukkitx.nbt.tag.ByteArrayTag byteArrayTag = (com.nukkitx.nbt.tag.ByteArrayTag) tag; + return new ByteArrayTag(byteArrayTag.getName(), byteArrayTag.getValue()); + } + + if (tag instanceof com.nukkitx.nbt.tag.ByteTag) { + com.nukkitx.nbt.tag.ByteTag byteTag = (com.nukkitx.nbt.tag.ByteTag) tag; + return new ByteTag(byteTag.getName(), byteTag.getValue()); + } + + if (tag instanceof com.nukkitx.nbt.tag.DoubleTag) { + com.nukkitx.nbt.tag.DoubleTag doubleTag = (com.nukkitx.nbt.tag.DoubleTag) tag; + return new DoubleTag(doubleTag.getName(), doubleTag.getValue()); + } + + if (tag instanceof com.nukkitx.nbt.tag.FloatTag) { + com.nukkitx.nbt.tag.FloatTag floatTag = (com.nukkitx.nbt.tag.FloatTag) tag; + return new FloatTag(floatTag.getName(), floatTag.getValue()); + } + + if (tag instanceof com.nukkitx.nbt.tag.IntArrayTag) { + com.nukkitx.nbt.tag.IntArrayTag intArrayTag = (com.nukkitx.nbt.tag.IntArrayTag) tag; + return new IntArrayTag(intArrayTag.getName(), intArrayTag.getValue()); + } + + if (tag instanceof com.nukkitx.nbt.tag.IntTag) { + com.nukkitx.nbt.tag.IntTag intTag = (com.nukkitx.nbt.tag.IntTag) tag; + return new IntTag(intTag.getName(), intTag.getValue()); + } + + if (tag instanceof com.nukkitx.nbt.tag.LongArrayTag) { + com.nukkitx.nbt.tag.LongArrayTag longArrayTag = (com.nukkitx.nbt.tag.LongArrayTag) tag; + return new LongArrayTag(longArrayTag.getName(), longArrayTag.getValue()); + } + + if (tag instanceof com.nukkitx.nbt.tag.LongTag) { + com.nukkitx.nbt.tag.LongTag longTag = (com.nukkitx.nbt.tag.LongTag) tag; + return new LongTag(longTag.getName(), longTag.getValue()); + } + + if (tag instanceof com.nukkitx.nbt.tag.ShortTag) { + com.nukkitx.nbt.tag.ShortTag shortTag = (com.nukkitx.nbt.tag.ShortTag) tag; + return new ShortTag(shortTag.getName(), shortTag.getValue()); + } + + if (tag instanceof com.nukkitx.nbt.tag.StringTag) { + com.nukkitx.nbt.tag.StringTag stringTag = (com.nukkitx.nbt.tag.StringTag) tag; + return new StringTag(stringTag.getName(), stringTag.getValue()); + } + + if (tag instanceof com.nukkitx.nbt.tag.ListTag) { + com.nukkitx.nbt.tag.ListTag listTag = (com.nukkitx.nbt.tag.ListTag) tag; + + List tags = new ArrayList<>(); + + for (Object value : listTag.getValue()) { + if (!(value instanceof com.nukkitx.nbt.tag.Tag)) + continue; + + com.nukkitx.nbt.tag.Tag tagValue = (com.nukkitx.nbt.tag.Tag) value; + com.github.steveice10.opennbt.tag.builtin.Tag javaTag = translateToJavaNBT(tagValue); + if (javaTag != null) + tags.add(javaTag); + } + return new ListTag(listTag.getName(), tags); + } + + if (tag instanceof com.nukkitx.nbt.tag.CompoundTag) { + com.nukkitx.nbt.tag.CompoundTag compoundTag = (com.nukkitx.nbt.tag.CompoundTag) tag; + return translateToJavaNBT(compoundTag); + } + + return null; + } + + +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/NbtItemStackTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/NbtItemStackTranslator.java new file mode 100644 index 00000000..56c780f4 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/NbtItemStackTranslator.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators; + +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import org.geysermc.connector.network.translators.item.ItemEntry; + +public class NbtItemStackTranslator { + + public void translateToBedrock(CompoundTag itemTag, ItemEntry itemEntry) { + + } + + public void translateToJava(CompoundTag itemTag, ItemEntry itemEntry) { + + } + + public boolean acceptItem(ItemEntry itemEntry) { + return true; + } + +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java b/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java index cffb85f1..f0a3fd28 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java @@ -109,6 +109,7 @@ public class Translators { } itemTranslator = new ItemTranslator(); + itemTranslator.init(); BlockTranslator.init(); registerBlockEntityTranslators(); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java index 440d01dc..c1e00d2a 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java @@ -51,7 +51,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { InventorySlotPacket slotPacket = new InventorySlotPacket(); slotPacket.setContainerId(ContainerId.CURSOR); slotPacket.setSlot(i + 27); - slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(inventory.getItem(i))); + slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(i))); session.getUpstream().sendPacket(slotPacket); } @@ -60,11 +60,11 @@ public class PlayerInventoryTranslator extends InventoryTranslator { ItemData[] contents = new ItemData[36]; // Inventory for (int i = 9; i < 36; i++) { - contents[i] = Translators.getItemTranslator().translateToBedrock(inventory.getItem(i)); + contents[i] = Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(i)); } // Hotbar for (int i = 36; i < 45; i++) { - contents[i - 36] = Translators.getItemTranslator().translateToBedrock(inventory.getItem(i)); + contents[i - 36] = Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(i)); } inventoryContentPacket.setContents(contents); session.getUpstream().sendPacket(inventoryContentPacket); @@ -74,7 +74,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { armorContentPacket.setContainerId(ContainerId.ARMOR); contents = new ItemData[4]; for (int i = 5; i < 9; i++) { - contents[i - 5] = Translators.getItemTranslator().translateToBedrock(inventory.getItem(i)); + contents[i - 5] = Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(i)); } armorContentPacket.setContents(contents); session.getUpstream().sendPacket(armorContentPacket); @@ -82,7 +82,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { // Offhand InventoryContentPacket offhandPacket = new InventoryContentPacket(); offhandPacket.setContainerId(ContainerId.OFFHAND); - offhandPacket.setContents(new ItemData[]{Translators.getItemTranslator().translateToBedrock(inventory.getItem(45))}); + offhandPacket.setContents(new ItemData[]{Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(45))}); session.getUpstream().sendPacket(offhandPacket); } @@ -104,12 +104,12 @@ public class PlayerInventoryTranslator extends InventoryTranslator { slotPacket.setContainerId(ContainerId.CURSOR); slotPacket.setSlot(slot + 27); } - slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(inventory.getItem(slot))); + slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(slot))); session.getUpstream().sendPacket(slotPacket); } else if (slot == 45) { InventoryContentPacket offhandPacket = new InventoryContentPacket(); offhandPacket.setContainerId(ContainerId.OFFHAND); - offhandPacket.setContents(new ItemData[]{Translators.getItemTranslator().translateToBedrock(inventory.getItem(slot))}); + offhandPacket.setContents(new ItemData[]{Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(slot))}); session.getUpstream().sendPacket(offhandPacket); } } @@ -180,7 +180,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { if (action.getToItem().getId() == 0) { javaItem = new ItemStack(-1, 0, null); } else { - javaItem = Translators.getItemTranslator().translateToJava(action.getToItem()); + javaItem = Translators.getItemTranslator().translateToJava(session, action.getToItem()); } ClientCreativeInventoryActionPacket creativePacket = new ClientCreativeInventoryActionPacket(javaSlot, javaItem); session.getDownstream().getSession().send(creativePacket); @@ -188,13 +188,13 @@ public class PlayerInventoryTranslator extends InventoryTranslator { break; case ContainerId.CURSOR: if (action.getSlot() == 0) { - session.getInventory().setCursor(Translators.getItemTranslator().translateToJava(action.getToItem())); + session.getInventory().setCursor(Translators.getItemTranslator().translateToJava(session, action.getToItem())); } break; case ContainerId.NONE: if (action.getSource().getType() == InventorySource.Type.WORLD_INTERACTION && action.getSource().getFlag() == InventorySource.Flag.DROP_ITEM) { - javaItem = Translators.getItemTranslator().translateToJava(action.getToItem()); + javaItem = Translators.getItemTranslator().translateToJava(session, action.getToItem()); ClientCreativeInventoryActionPacket creativeDropPacket = new ClientCreativeInventoryActionPacket(-1, javaItem); session.getDownstream().getSession().send(creativeDropPacket); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java index 750de5c8..370d4177 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java @@ -61,13 +61,13 @@ public class InventoryActionDataTranslator { worldAction = action; } else if (action.getSource().getContainerId() == ContainerId.CURSOR && action.getSlot() == 0) { cursorAction = action; - ItemData translatedCursor = Translators.getItemTranslator().translateToBedrock(session.getInventory().getCursor()); + ItemData translatedCursor = Translators.getItemTranslator().translateToBedrock(session, session.getInventory().getCursor()); if (!translatedCursor.equals(action.getFromItem())) { refresh = true; } } else { containerAction = action; - ItemData translatedItem = Translators.getItemTranslator().translateToBedrock(inventory.getItem(translator.bedrockSlotToJava(action))); + ItemData translatedItem = Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(translator.bedrockSlotToJava(action))); if (!translatedItem.equals(action.getFromItem())) { refresh = true; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java index dcffcd35..e8e0fc45 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java @@ -45,7 +45,7 @@ public class ChestInventoryUpdater extends InventoryUpdater { ItemData[] bedrockItems = new ItemData[paddedSize]; for (int i = 0; i < bedrockItems.length; i++) { if (i <= translator.size) { - bedrockItems[i] = Translators.getItemTranslator().translateToBedrock(inventory.getItem(i)); + bedrockItems[i] = Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(i)); } else { bedrockItems[i] = ItemData.AIR; } @@ -65,7 +65,7 @@ public class ChestInventoryUpdater extends InventoryUpdater { InventorySlotPacket slotPacket = new InventorySlotPacket(); slotPacket.setContainerId(inventory.getId()); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); - slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(inventory.getItem(javaSlot))); + slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(javaSlot))); session.getUpstream().sendPacket(slotPacket); return true; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java index 812ce8f8..d187ffd9 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java @@ -40,7 +40,7 @@ public class ContainerInventoryUpdater extends InventoryUpdater { ItemData[] bedrockItems = new ItemData[translator.size]; for (int i = 0; i < bedrockItems.length; i++) { - bedrockItems[translator.javaSlotToBedrock(i)] = Translators.getItemTranslator().translateToBedrock(inventory.getItem(i)); + bedrockItems[translator.javaSlotToBedrock(i)] = Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(i)); } InventoryContentPacket contentPacket = new InventoryContentPacket(); @@ -57,7 +57,7 @@ public class ContainerInventoryUpdater extends InventoryUpdater { InventorySlotPacket slotPacket = new InventorySlotPacket(); slotPacket.setContainerId(inventory.getId()); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); - slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(inventory.getItem(javaSlot))); + slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(javaSlot))); session.getUpstream().sendPacket(slotPacket); return true; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java index f0c1c760..e3dc1864 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java @@ -44,7 +44,7 @@ public class CursorInventoryUpdater extends InventoryUpdater { InventorySlotPacket slotPacket = new InventorySlotPacket(); slotPacket.setContainerId(ContainerId.CURSOR); slotPacket.setSlot(bedrockSlot); - slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(inventory.getItem(i))); + slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(i))); session.getUpstream().sendPacket(slotPacket); } } @@ -57,7 +57,7 @@ public class CursorInventoryUpdater extends InventoryUpdater { InventorySlotPacket slotPacket = new InventorySlotPacket(); slotPacket.setContainerId(ContainerId.CURSOR); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); - slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(inventory.getItem(javaSlot))); + slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(javaSlot))); session.getUpstream().sendPacket(slotPacket); return true; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java index 32005685..2f139e27 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java @@ -39,7 +39,7 @@ public abstract class InventoryUpdater { ItemData[] bedrockItems = new ItemData[36]; for (int i = 0; i < 36; i++) { final int offset = i < 9 ? 27 : -9; - bedrockItems[i] = Translators.getItemTranslator().translateToBedrock(inventory.getItem(translator.size + i + offset)); + bedrockItems[i] = Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(translator.size + i + offset)); } InventoryContentPacket contentPacket = new InventoryContentPacket(); contentPacket.setContainerId(ContainerId.INVENTORY); @@ -52,7 +52,7 @@ public abstract class InventoryUpdater { InventorySlotPacket slotPacket = new InventorySlotPacket(); slotPacket.setContainerId(ContainerId.INVENTORY); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); - slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(inventory.getItem(javaSlot))); + slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(javaSlot))); session.getUpstream().sendPacket(slotPacket); return true; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/Enchantment.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/Enchantment.java index c5c152a2..b9348e25 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/Enchantment.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/Enchantment.java @@ -30,7 +30,7 @@ import lombok.Getter; import java.util.Locale; @Getter -enum Enchantment { +public enum Enchantment { PROTECTION, FIRE_PROTECTION, FEATHER_FALLING, diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java index 0bcbf4b7..79dae31f 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java @@ -26,86 +26,107 @@ package org.geysermc.connector.network.translators.item; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; -import com.github.steveice10.mc.protocol.data.message.Message; -import com.github.steveice10.opennbt.tag.builtin.ByteArrayTag; -import com.github.steveice10.opennbt.tag.builtin.ByteTag; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.github.steveice10.opennbt.tag.builtin.DoubleTag; -import com.github.steveice10.opennbt.tag.builtin.FloatTag; -import com.github.steveice10.opennbt.tag.builtin.IntArrayTag; -import com.github.steveice10.opennbt.tag.builtin.IntTag; -import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.github.steveice10.opennbt.tag.builtin.LongArrayTag; -import com.github.steveice10.opennbt.tag.builtin.LongTag; -import com.github.steveice10.opennbt.tag.builtin.ShortTag; -import com.github.steveice10.opennbt.tag.builtin.StringTag; -import com.github.steveice10.opennbt.tag.builtin.Tag; import com.nukkitx.protocol.bedrock.data.ItemData; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import org.geysermc.connector.GeyserConnector; -import org.geysermc.connector.utils.MessageUtils; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.*; import org.geysermc.connector.utils.Toolbox; +import org.reflections.Reflections; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.stream.Collectors; public class ItemTranslator { + private Int2ObjectMap itemTranslators = new Int2ObjectOpenHashMap(); + private List nbtItemTranslators; private Map javaIdentifierMap = new HashMap<>(); - public ItemStack translateToJava(ItemData data) { - ItemEntry javaItem = getItem(data); + public void init() { + Reflections ref = new Reflections("org.geysermc.connector.network.translators.item"); - if (data.getTag() == null) { - return new ItemStack(javaItem.getJavaId(), data.getCount()); - } else if (javaItem.getJavaIdentifier().equals("minecraft:enchanted_book")) { - CompoundTag javaTag = translateToJavaNBT(data.getTag()); - Map javaValue = javaTag.getValue(); - Tag enchTag = javaValue.get("Enchantments"); - if (enchTag instanceof ListTag) { - enchTag = new ListTag("StoredEnchantments", ((ListTag) enchTag).getValue()); - javaValue.remove("Enchantments"); - javaValue.put("StoredEnchantments", enchTag); - javaTag.setValue(javaValue); + Map loadedNbtItemTranslators = new HashMap<>(); + for (Class clazz : ref.getTypesAnnotatedWith(ItemRemapper.class)) { + int priority = clazz.getAnnotation(ItemRemapper.class).priority(); + + GeyserConnector.getInstance().getLogger().debug("Found annotated item translator: " + clazz.getCanonicalName()); + + try { + if (NbtItemStackTranslator.class.isAssignableFrom(clazz)) { + NbtItemStackTranslator nbtItemTranslator = (NbtItemStackTranslator) clazz.newInstance(); + loadedNbtItemTranslators.put(nbtItemTranslator, priority); + continue; + } + ItemStackTranslator itemStackTranslator = (ItemStackTranslator) clazz.newInstance(); + List appliedItems = itemStackTranslator.getAppliedItems(); + for (ItemEntry item : appliedItems) { + ItemStackTranslator registered = itemTranslators.get(item.getJavaId()); + if (registered != null) { + GeyserConnector.getInstance().getLogger().error("Could not instantiate annotated item translator " + clazz.getCanonicalName() + "." + + " Item translator " + registered.getClass().getCanonicalName() + " is already registered for the item " + item.getJavaIdentifier()); + continue; + } + itemTranslators.put(item.getJavaId(), itemStackTranslator); + } + } catch (InstantiationException | IllegalAccessException e) { + GeyserConnector.getInstance().getLogger().error("Could not instantiate annotated item translator " + clazz.getCanonicalName() + "."); } - return new ItemStack(javaItem.getJavaId(), data.getCount(), javaTag); } - return new ItemStack(javaItem.getJavaId(), data.getCount(), translateToJavaNBT(data.getTag())); + + nbtItemTranslators = loadedNbtItemTranslators.keySet().stream() + .sorted(Comparator.comparingInt(value -> loadedNbtItemTranslators.get(value))).collect(Collectors.toList()); } - public ItemData translateToBedrock(ItemStack stack) { + public ItemStack translateToJava(GeyserSession session, ItemData data) { + if (data == null) { + return new ItemStack(0); + } + ItemEntry javaItem = getItem(data); + + ItemStack itemStack; + + ItemStackTranslator itemStackTranslator = itemTranslators.get(javaItem.getJavaId()); + if (itemStackTranslator != null) { + itemStack = itemStackTranslator.translateToJava(data, javaItem); + } else { + itemStack = DEFAULT_TRANSLATOR.translateToJava(data, javaItem); + } + + if (itemStack != null && itemStack.getNbt() != null) { + for (NbtItemStackTranslator translator : nbtItemTranslators) { + if (translator.acceptItem(javaItem)) { + translator.translateToJava(itemStack.getNbt(), javaItem); + } + } + } + return itemStack; + } + + public ItemData translateToBedrock(GeyserSession session, ItemStack stack) { if (stack == null) { return ItemData.AIR; } ItemEntry bedrockItem = getItem(stack); - if (stack.getNbt() == null) { - return ItemData.of(bedrockItem.getBedrockId(), (short) bedrockItem.getBedrockData(), stack.getAmount()); - } else if (bedrockItem.getJavaIdentifier().endsWith("potion")) { - Tag potionTag = stack.getNbt().get("Potion"); - if (potionTag instanceof StringTag) { - Potion potion = Potion.getByJavaIdentifier(((StringTag) potionTag).getValue()); - if (potion != null) { - return ItemData.of(bedrockItem.getBedrockId(), potion.getBedrockId(), stack.getAmount(), translateToBedrockNBT(stack.getNbt())); + + if (stack != null && stack.getNbt() != null) { + for (NbtItemStackTranslator translator : nbtItemTranslators) { + if (translator.acceptItem(bedrockItem)) { + translator.translateToBedrock(stack.getNbt(), bedrockItem); } - GeyserConnector.getInstance().getLogger().debug("Unknown java potion: " + potionTag.getValue()); } } - // TODO: Create proper transformers instead of shoving everything here - CompoundTag tag = stack.getNbt(); - IntTag mapId = tag.get("map"); - - if (mapId != null) { - tag.put(new StringTag("map_uuid", mapId.getValue().toString())); - tag.put(new IntTag("map_name_index", mapId.getValue())); + ItemStackTranslator itemStackTranslator = itemTranslators.get(bedrockItem.getJavaId()); + if (itemStackTranslator != null) { + return itemStackTranslator.translateToBedrock(stack, bedrockItem); + } else { + return DEFAULT_TRANSLATOR.translateToBedrock(stack, bedrockItem); } - - - return ItemData.of(bedrockItem.getBedrockId(), (short) bedrockItem.getBedrockData(), stack.getAmount(), translateToBedrockNBT(tag)); } public ItemEntry getItem(ItemStack stack) { @@ -135,235 +156,10 @@ public class ItemTranslator { .stream().filter(itemEntry -> itemEntry.getJavaIdentifier().equals(key)).findFirst().orElse(null)); } - private CompoundTag translateToJavaNBT(com.nukkitx.nbt.tag.CompoundTag tag) { - CompoundTag javaTag = new CompoundTag(tag.getName()); - Map javaValue = javaTag.getValue(); - if (tag.getValue() != null && !tag.getValue().isEmpty()) { - for (String str : tag.getValue().keySet()) { - com.nukkitx.nbt.tag.Tag bedrockTag = tag.get(str); - Tag translatedTag = translateToJavaNBT(bedrockTag); - if (translatedTag == null) - continue; - - javaValue.put(translatedTag.getName(), translatedTag); - } + private static final ItemStackTranslator DEFAULT_TRANSLATOR = new ItemStackTranslator() { + @Override + public List getAppliedItems() { + return null; } - - javaTag.setValue(javaValue); - return javaTag; - } - - private Tag translateToJavaNBT(com.nukkitx.nbt.tag.Tag tag) { - if (tag instanceof com.nukkitx.nbt.tag.ByteArrayTag) { - com.nukkitx.nbt.tag.ByteArrayTag byteArrayTag = (com.nukkitx.nbt.tag.ByteArrayTag) tag; - return new ByteArrayTag(byteArrayTag.getName(), byteArrayTag.getValue()); - } - - if (tag instanceof com.nukkitx.nbt.tag.ByteTag) { - com.nukkitx.nbt.tag.ByteTag byteTag = (com.nukkitx.nbt.tag.ByteTag) tag; - return new ByteTag(byteTag.getName(), byteTag.getValue()); - } - - if (tag instanceof com.nukkitx.nbt.tag.DoubleTag) { - com.nukkitx.nbt.tag.DoubleTag doubleTag = (com.nukkitx.nbt.tag.DoubleTag) tag; - return new DoubleTag(doubleTag.getName(), doubleTag.getValue()); - } - - if (tag instanceof com.nukkitx.nbt.tag.FloatTag) { - com.nukkitx.nbt.tag.FloatTag floatTag = (com.nukkitx.nbt.tag.FloatTag) tag; - return new FloatTag(floatTag.getName(), floatTag.getValue()); - } - - if (tag instanceof com.nukkitx.nbt.tag.IntArrayTag) { - com.nukkitx.nbt.tag.IntArrayTag intArrayTag = (com.nukkitx.nbt.tag.IntArrayTag) tag; - return new IntArrayTag(intArrayTag.getName(), intArrayTag.getValue()); - } - - if (tag instanceof com.nukkitx.nbt.tag.IntTag) { - com.nukkitx.nbt.tag.IntTag intTag = (com.nukkitx.nbt.tag.IntTag) tag; - return new IntTag(intTag.getName(), intTag.getValue()); - } - - if (tag instanceof com.nukkitx.nbt.tag.LongArrayTag) { - com.nukkitx.nbt.tag.LongArrayTag longArrayTag = (com.nukkitx.nbt.tag.LongArrayTag) tag; - return new LongArrayTag(longArrayTag.getName(), longArrayTag.getValue()); - } - - if (tag instanceof com.nukkitx.nbt.tag.LongTag) { - com.nukkitx.nbt.tag.LongTag longTag = (com.nukkitx.nbt.tag.LongTag) tag; - return new LongTag(longTag.getName(), longTag.getValue()); - } - - if (tag instanceof com.nukkitx.nbt.tag.ShortTag) { - com.nukkitx.nbt.tag.ShortTag shortTag = (com.nukkitx.nbt.tag.ShortTag) tag; - return new ShortTag(shortTag.getName(), shortTag.getValue()); - } - - if (tag instanceof com.nukkitx.nbt.tag.StringTag) { - com.nukkitx.nbt.tag.StringTag stringTag = (com.nukkitx.nbt.tag.StringTag) tag; - return new StringTag(stringTag.getName(), stringTag.getValue()); - } - - if (tag instanceof com.nukkitx.nbt.tag.ListTag) { - com.nukkitx.nbt.tag.ListTag listTag = (com.nukkitx.nbt.tag.ListTag) tag; - - List tags = new ArrayList<>(); - - if (tag.getName().equals("ench")) { - for (Object value : listTag.getValue()) { - if (!(value instanceof com.nukkitx.nbt.tag.CompoundTag)) - continue; - - com.nukkitx.nbt.tag.CompoundTag tagValue = (com.nukkitx.nbt.tag.CompoundTag) value; - int bedrockId = tagValue.getShort("id", (short) -1); - Enchantment enchantment = Enchantment.getByBedrockId(bedrockId); - if (enchantment != null) { - CompoundTag javaTag = new CompoundTag(""); - Map javaValue = javaTag.getValue(); - javaValue.put("id", new StringTag("id", enchantment.getJavaIdentifier())); - javaValue.put("lvl", new IntTag("lvl", tagValue.getShort("lvl", (short) 1))); - javaTag.setValue(javaValue); - tags.add(javaTag); - } else { - GeyserConnector.getInstance().getLogger().debug("Unknown bedrock enchantment: " + bedrockId); - } - } - return new ListTag("Enchantments", tags); - } - - for (Object value : listTag.getValue()) { - if (!(value instanceof com.nukkitx.nbt.tag.Tag)) - continue; - - com.nukkitx.nbt.tag.Tag tagValue = (com.nukkitx.nbt.tag.Tag) value; - Tag javaTag = translateToJavaNBT(tagValue); - if (javaTag != null) - tags.add(javaTag); - } - return new ListTag(listTag.getName(), tags); - } - - if (tag instanceof com.nukkitx.nbt.tag.CompoundTag) { - return translateToJavaNBT((com.nukkitx.nbt.tag.CompoundTag) tag); - } - - return null; - } - - private com.nukkitx.nbt.tag.CompoundTag translateToBedrockNBT(CompoundTag tag) { - Map> javaValue = new HashMap>(); - if (tag.getValue() != null && !tag.getValue().isEmpty()) { - for (String str : tag.getValue().keySet()) { - Tag javaTag = tag.get(str); - com.nukkitx.nbt.tag.Tag translatedTag = translateToBedrockNBT(javaTag); - if (translatedTag == null) - continue; - - javaValue.put(translatedTag.getName(), translatedTag); - } - } - - com.nukkitx.nbt.tag.CompoundTag bedrockTag = new com.nukkitx.nbt.tag.CompoundTag(tag.getName(), javaValue); - return bedrockTag; - } - - private com.nukkitx.nbt.tag.Tag translateToBedrockNBT(Tag tag) { - if (tag instanceof ByteArrayTag) { - ByteArrayTag byteArrayTag = (ByteArrayTag) tag; - return new com.nukkitx.nbt.tag.ByteArrayTag(byteArrayTag.getName(), byteArrayTag.getValue()); - } - - if (tag instanceof ByteTag) { - ByteTag byteTag = (ByteTag) tag; - return new com.nukkitx.nbt.tag.ByteTag(byteTag.getName(), byteTag.getValue()); - } - - if (tag instanceof DoubleTag) { - DoubleTag doubleTag = (DoubleTag) tag; - return new com.nukkitx.nbt.tag.DoubleTag(doubleTag.getName(), doubleTag.getValue()); - } - - if (tag instanceof FloatTag) { - FloatTag floatTag = (FloatTag) tag; - return new com.nukkitx.nbt.tag.FloatTag(floatTag.getName(), floatTag.getValue()); - } - - if (tag instanceof IntArrayTag) { - IntArrayTag intArrayTag = (IntArrayTag) tag; - return new com.nukkitx.nbt.tag.IntArrayTag(intArrayTag.getName(), intArrayTag.getValue()); - } - - if (tag instanceof IntTag) { - IntTag intTag = (IntTag) tag; - return new com.nukkitx.nbt.tag.IntTag(intTag.getName(), intTag.getValue()); - } - - if (tag instanceof LongArrayTag) { - LongArrayTag longArrayTag = (LongArrayTag) tag; - return new com.nukkitx.nbt.tag.LongArrayTag(longArrayTag.getName(), longArrayTag.getValue()); - } - - if (tag instanceof LongTag) { - LongTag longTag = (LongTag) tag; - return new com.nukkitx.nbt.tag.LongTag(longTag.getName(), longTag.getValue()); - } - - if (tag instanceof ShortTag) { - ShortTag shortTag = (ShortTag) tag; - return new com.nukkitx.nbt.tag.ShortTag(shortTag.getName(), shortTag.getValue()); - } - - if (tag instanceof StringTag) { - StringTag stringTag = (StringTag) tag; - return new com.nukkitx.nbt.tag.StringTag(stringTag.getName(), MessageUtils.getBedrockMessage(Message.fromString(stringTag.getValue()))); - } - - if (tag instanceof ListTag) { - ListTag listTag = (ListTag) tag; - if (listTag.getName().equalsIgnoreCase("Enchantments") || listTag.getName().equalsIgnoreCase("StoredEnchantments")) { - List tags = new ArrayList<>(); - for (Object value : listTag.getValue()) { - if (!(value instanceof CompoundTag)) - continue; - - Tag javaEnchLvl = ((CompoundTag) value).get("lvl"); - if (!(javaEnchLvl instanceof ShortTag)) - continue; - - Tag javaEnchId = ((CompoundTag) value).get("id"); - if (!(javaEnchId instanceof StringTag)) - continue; - - Enchantment enchantment = Enchantment.getByJavaIdentifier(((StringTag) javaEnchId).getValue()); - if (enchantment == null) { - GeyserConnector.getInstance().getLogger().debug("Unknown java enchantment: " + javaEnchId.getValue()); - continue; - } - - com.nukkitx.nbt.CompoundTagBuilder builder = com.nukkitx.nbt.tag.CompoundTag.EMPTY.toBuilder(); - builder.shortTag("lvl", ((ShortTag) javaEnchLvl).getValue()); - builder.shortTag("id", (short) enchantment.ordinal()); - tags.add(builder.buildRootTag()); - } - return new com.nukkitx.nbt.tag.ListTag<>("ench", com.nukkitx.nbt.tag.CompoundTag.class, tags); - } else if (listTag.getName().equalsIgnoreCase("Lore")) { - List tags = new ArrayList<>(); - for (Object value : listTag.getValue()) { - if (!(value instanceof Tag)) - continue; - - com.nukkitx.nbt.tag.StringTag bedrockTag = (com.nukkitx.nbt.tag.StringTag) translateToBedrockNBT((Tag) value); - if (bedrockTag != null) - tags.add(bedrockTag); - } - return new com.nukkitx.nbt.tag.ListTag<>(listTag.getName(), com.nukkitx.nbt.tag.StringTag.class, tags); - } - } - - if (tag instanceof CompoundTag) { - return translateToBedrockNBT((CompoundTag) tag); - } - - return null; - } + }; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/Potion.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/Potion.java index f711d3ea..51ae36e4 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/Potion.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/Potion.java @@ -30,7 +30,7 @@ import lombok.Getter; import java.util.Locale; @Getter -enum Potion { +public enum Potion { WATER(0), MUNDANE(1), THICK(3), diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/PotionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/PotionTranslator.java new file mode 100644 index 00000000..e528b448 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/PotionTranslator.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.item.translators; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.opennbt.tag.builtin.StringTag; +import com.github.steveice10.opennbt.tag.builtin.Tag; +import com.nukkitx.protocol.bedrock.data.ItemData; +import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.network.translators.ItemStackTranslator; +import org.geysermc.connector.network.translators.ItemRemapper; +import org.geysermc.connector.network.translators.item.ItemEntry; +import org.geysermc.connector.network.translators.item.Potion; +import org.geysermc.connector.utils.Toolbox; + +import java.util.List; +import java.util.stream.Collectors; + +@ItemRemapper +public class PotionTranslator extends ItemStackTranslator { + + private List appliedItems; + + public PotionTranslator() { + appliedItems = Toolbox.ITEM_ENTRIES.values().stream().filter(entry -> entry.getJavaIdentifier().endsWith("potion")).collect(Collectors.toList()); + } + + @Override + public ItemData translateToBedrock(ItemStack itemStack, ItemEntry itemEntry) { + if (itemStack.getNbt() == null) return super.translateToBedrock(itemStack, itemEntry); + Tag potionTag = itemStack.getNbt().get("Potion"); + if (potionTag instanceof StringTag) { + Potion potion = Potion.getByJavaIdentifier(((StringTag) potionTag).getValue()); + if (potion != null) { + return ItemData.of(itemEntry.getBedrockId(), potion.getBedrockId(), itemStack.getAmount(), translateNbtToBedrock(itemStack.getNbt())); + } + GeyserConnector.getInstance().getLogger().debug("Unknown java potion: " + potionTag.getValue()); + } + return super.translateToBedrock(itemStack, itemEntry); + } + + @Override + public ItemStack translateToJava(ItemData itemData, ItemEntry itemEntry) { + Potion potion = Potion.getByBedrockId(itemData.getDamage()); + ItemStack itemStack = super.translateToJava(itemData, itemEntry); + if (potion != null) { + StringTag potionTag = new StringTag("Potion", potion.getJavaIdentifier()); + itemStack.getNbt().put(potionTag); + } + return itemStack; + } + + @Override + public List getAppliedItems() { + return appliedItems; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantedBookTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantedBookTranslator.java new file mode 100644 index 00000000..2ca6e35c --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantedBookTranslator.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.item.translators.nbt; + +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.ListTag; +import com.github.steveice10.opennbt.tag.builtin.Tag; +import org.geysermc.connector.network.translators.ItemRemapper; +import org.geysermc.connector.network.translators.NbtItemStackTranslator; +import org.geysermc.connector.network.translators.item.ItemEntry; + +@ItemRemapper(priority = 1) +public class EnchantedBookTranslator extends NbtItemStackTranslator { + + @Override + public void translateToBedrock(CompoundTag itemTag, ItemEntry itemEntry) { + if (itemTag.contains("StoredEnchantments")) { + Tag enchTag = itemTag.get("StoredEnchantments"); + if (enchTag instanceof ListTag) { + enchTag = new ListTag("Enchantments", ((ListTag) enchTag).getValue()); + itemTag.remove("StoredEnchantments"); + itemTag.put(enchTag); + } + } + } + + @Override + public void translateToJava(CompoundTag itemTag, ItemEntry itemEntry) { + if (itemTag.contains("Enchantments")) { + Tag enchTag = itemTag.get("Enchantments"); + if (enchTag instanceof ListTag) { + enchTag = new ListTag("StoredEnchantments", ((ListTag) enchTag).getValue()); + itemTag.remove("Enchantments"); + itemTag.put(enchTag); + } + } + } + + @Override + public boolean acceptItem(ItemEntry itemEntry) { + return "minecraft:enchanted_book".equals(itemEntry.getJavaIdentifier()); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantmentTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantmentTranslator.java new file mode 100644 index 00000000..fba20666 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantmentTranslator.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.item.translators.nbt; + +import com.github.steveice10.opennbt.tag.builtin.*; +import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.network.translators.ItemRemapper; +import org.geysermc.connector.network.translators.NbtItemStackTranslator; +import org.geysermc.connector.network.translators.item.Enchantment; +import org.geysermc.connector.network.translators.item.ItemEntry; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@ItemRemapper +public class EnchantmentTranslator extends NbtItemStackTranslator { + + @Override + public void translateToBedrock(CompoundTag itemTag, ItemEntry itemEntry) { + List newTags = new ArrayList<>(); + if (itemTag.contains("Enchantments")) { + ListTag enchantmentTag = itemTag.get("Enchantments"); + for (Tag tag : enchantmentTag.getValue()) { + if (!(tag instanceof CompoundTag)) continue; + + CompoundTag bedrockTag = remapEnchantment((CompoundTag) tag); + newTags.add(bedrockTag); + } + itemTag.remove("Enchantments"); + } + if (itemTag.contains("StoredEnchantments")) { + ListTag enchantmentTag = itemTag.get("StoredEnchantments"); + for (Tag tag : enchantmentTag.getValue()) { + if (!(tag instanceof CompoundTag)) continue; + + CompoundTag bedrockTag = remapEnchantment((CompoundTag) tag); + bedrockTag.put(new ShortTag("GeyserStoredEnchantment", (short) 0)); + newTags.add(bedrockTag); + } + itemTag.remove("StoredEnchantments"); + } + + if (!newTags.isEmpty()) { + itemTag.put(new ListTag("ench", newTags)); + } + } + + @Override + public void translateToJava(CompoundTag itemTag, ItemEntry itemEntry) { + if (itemTag.contains("ench")) { + ListTag enchantmentTag = itemTag.get("ench"); + List enchantments = new ArrayList<>(); + List storedEnchantments = new ArrayList<>(); + for (Tag value : enchantmentTag.getValue()) { + if (!(value instanceof CompoundTag)) + continue; + + CompoundTag tagValue = (CompoundTag) value; + ShortTag bedrockId = tagValue.get("id"); + if (bedrockId == null) continue; + + ShortTag geyserStoredEnchantmentTag = tagValue.get("GeyserStoredEnchantment"); + + Enchantment enchantment = Enchantment.getByBedrockId(bedrockId.getValue()); + if (enchantment != null) { + CompoundTag javaTag = new CompoundTag(""); + Map javaValue = javaTag.getValue(); + javaValue.put("id", new StringTag("id", enchantment.getJavaIdentifier())); + ShortTag levelTag = tagValue.get("lvl"); + javaValue.put("lvl", new IntTag("lvl", levelTag != null ? levelTag.getValue() : 1)); + javaTag.setValue(javaValue); + + + if (geyserStoredEnchantmentTag != null) { + tagValue.remove("GeyserStoredEnchantment"); + storedEnchantments.add(javaTag); + } else { + enchantments.add(javaTag); + } + } else { + GeyserConnector.getInstance().getLogger().debug("Unknown bedrock enchantment: " + bedrockId); + } + } + if (!enchantments.isEmpty()) { + itemTag.put(new ListTag("Enchantments", enchantments)); + } + if (!storedEnchantments.isEmpty()) { + itemTag.put(new ListTag("StoredEnchantments", enchantments)); + } + itemTag.remove("ench"); + } + } + + + private CompoundTag remapEnchantment(CompoundTag tag) { + Tag javaEnchLvl = ((CompoundTag) tag).get("lvl"); + if (!(javaEnchLvl instanceof ShortTag)) + return null; + + Tag javaEnchId = ((CompoundTag) tag).get("id"); + if (!(javaEnchId instanceof StringTag)) + return null; + + Enchantment enchantment = Enchantment.getByJavaIdentifier(((StringTag) javaEnchId).getValue()); + if (enchantment == null) { + GeyserConnector.getInstance().getLogger().debug("Unknown java enchantment: " + javaEnchId.getValue()); + return null; + } + + CompoundTag bedrockTag = new CompoundTag(""); + bedrockTag.put(new ShortTag("id", (short) enchantment.ordinal())); + bedrockTag.put(new ShortTag("lvl", ((ShortTag) javaEnchLvl).getValue())); + return bedrockTag; + } + +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/LeatherArmorTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/LeatherArmorTranslator.java new file mode 100644 index 00000000..4b01d912 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/LeatherArmorTranslator.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.item.translators.nbt; + +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.IntTag; +import org.geysermc.connector.network.translators.ItemRemapper; +import org.geysermc.connector.network.translators.NbtItemStackTranslator; +import org.geysermc.connector.network.translators.item.ItemEntry; + +@ItemRemapper +public class LeatherArmorTranslator extends NbtItemStackTranslator { + + private static final String[] ITEMS = new String[]{"minecraft:leather_helmet", "minecraft:leather_chestplate", "minecraft:leather_leggings", "minecraft:leather_boots"}; + + @Override + public void translateToBedrock(CompoundTag itemTag, ItemEntry itemEntry) { + if (itemTag.contains("display")) { + CompoundTag displayTag = itemTag.get("display"); + if (displayTag.contains("color")) { + IntTag color = displayTag.get("color"); + if (color != null) { + itemTag.put(new IntTag("customColor", color.getValue())); + displayTag.remove("color"); + } + } + } + } + + @Override + public void translateToJava(CompoundTag itemTag, ItemEntry itemEntry) { + if (itemTag.contains("customColor")) { + IntTag color = itemTag.get("customColor"); + CompoundTag displayTag = itemTag.get("display"); + if (displayTag == null) { + displayTag = new CompoundTag("display"); + } + displayTag.put(color); + itemTag.remove("customColor"); + } + } + + @Override + public boolean acceptItem(ItemEntry itemEntry) { + for (String item : ITEMS) { + if (itemEntry.getJavaIdentifier().equals(item)) return true; + } + return false; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/MapItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/MapItemTranslator.java new file mode 100644 index 00000000..cdf272ec --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/MapItemTranslator.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.item.translators.nbt; + +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.IntTag; +import com.github.steveice10.opennbt.tag.builtin.StringTag; +import org.geysermc.connector.network.translators.ItemRemapper; +import org.geysermc.connector.network.translators.NbtItemStackTranslator; +import org.geysermc.connector.network.translators.item.ItemEntry; + +@ItemRemapper +public class MapItemTranslator extends NbtItemStackTranslator { + + @Override + public void translateToBedrock(CompoundTag itemTag, ItemEntry itemEntry) { + IntTag mapId = itemTag.get("map"); + + if (mapId != null) { + itemTag.put(new StringTag("map_uuid", mapId.getValue().toString())); + itemTag.put(new IntTag("map_name_index", mapId.getValue())); + itemTag.remove("map"); + } + } + + @Override + public void translateToJava(CompoundTag itemTag, ItemEntry itemEntry) { + IntTag tag = itemTag.get("map_name_index"); + if (tag != null) { + itemTag.put(new IntTag("map", tag.getValue())); + itemTag.remove("map_name_index"); + itemTag.remove("map_uuid"); + } + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java index 18b155e0..c78493a3 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java @@ -64,9 +64,9 @@ public class JavaDeclareRecipesTranslator extends PacketTranslator, IntSet> squashedOptions = new HashMap<>(); for (int i = 0; i < ingredients.length; i++) { if (ingredients[i].getOptions().length == 0) { @@ -103,7 +103,7 @@ public class JavaDeclareRecipesTranslator extends PacketTranslator> groupedByIds = Arrays.stream(ingredient.getOptions()) - .map(item -> Translators.getItemTranslator().translateToBedrock(item)) + .map(item -> Translators.getItemTranslator().translateToBedrock(session, item)) .collect(Collectors.groupingBy(item -> new GroupedItem(item.getId(), item.getCount(), item.getTag()))); Set optionSet = new HashSet<>(groupedByIds.size()); for (Map.Entry> entry : groupedByIds.entrySet()) { @@ -136,7 +136,7 @@ public class JavaDeclareRecipesTranslator extends PacketTranslator 0) { - translatedItems[i] = Translators.getItemTranslator().translateToBedrock(ingredients[i].getOptions()[0]); + translatedItems[i] = Translators.getItemTranslator().translateToBedrock(session, ingredients[i].getOptions()[0]); } else { translatedItems[i] = ItemData.AIR; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityEquipmentTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityEquipmentTranslator.java index 70c17142..a010752d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityEquipmentTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityEquipmentTranslator.java @@ -55,7 +55,7 @@ public class JavaEntityEquipmentTranslator extends PacketTranslator