From 78337830c6929b759dc6c71dd872d1e945b949fd Mon Sep 17 00:00:00 2001
From: Camotoy <20743703+Camotoy@users.noreply.github.com>
Date: Fri, 12 Feb 2021 14:39:41 -0500
Subject: [PATCH] Use the real block for opening inventory when possible
---
.../connector/inventory/Container.java | 15 ++++
.../inventory/Generic3X3Container.java | 48 +++++++++++++
.../network/session/GeyserSession.java | 17 +++--
...BedrockInventoryTransactionTranslator.java | 5 +-
.../BedrockLecternUpdateTranslator.java | 4 +-
.../inventory/InventoryTranslator.java | 5 +-
.../holder/BlockInventoryHolder.java | 60 +++++++++++++---
.../AbstractBlockInventoryTranslator.java | 8 +--
.../translators/AnvilInventoryTranslator.java | 3 +-
.../Generic3X3InventoryTranslator.java | 71 +++++++++++++++++++
...or.java => HopperInventoryTranslator.java} | 6 +-
.../LecternInventoryTranslator.java | 3 +-
.../chest/DoubleChestInventoryTranslator.java | 47 ++++++++++--
.../chest/SingleChestInventoryTranslator.java | 5 +-
.../java/world/JavaBlockChangeTranslator.java | 2 +-
.../DoubleChestBlockEntityTranslator.java | 52 ++++++++------
16 files changed, 290 insertions(+), 61 deletions(-)
create mode 100644 connector/src/main/java/org/geysermc/connector/inventory/Generic3X3Container.java
create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/Generic3X3InventoryTranslator.java
rename connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/{GenericBlockInventoryTranslator.java => HopperInventoryTranslator.java} (87%)
diff --git a/connector/src/main/java/org/geysermc/connector/inventory/Container.java b/connector/src/main/java/org/geysermc/connector/inventory/Container.java
index 520a76ef3..6302a7daa 100644
--- a/connector/src/main/java/org/geysermc/connector/inventory/Container.java
+++ b/connector/src/main/java/org/geysermc/connector/inventory/Container.java
@@ -38,6 +38,11 @@ public class Container extends Inventory {
private final PlayerInventory playerInventory;
private final int containerSize;
+ /**
+ * Whether we are using a real block when opening this inventory.
+ */
+ private boolean isUsingRealBlock = false;
+
public Container(String title, int id, int size, PlayerInventory playerInventory) {
super(title, id, size);
this.playerInventory = playerInventory;
@@ -66,4 +71,14 @@ public class Container extends Inventory {
public int getSize() {
return this.containerSize;
}
+
+ /**
+ * Will be overwritten for droppers.
+ *
+ * @param usingRealBlock whether this container is using a real container or not
+ * @param javaBlockId the Java block string of the block, if real
+ */
+ public void setUsingRealBlock(boolean usingRealBlock, String javaBlockId) {
+ isUsingRealBlock = usingRealBlock;
+ }
}
diff --git a/connector/src/main/java/org/geysermc/connector/inventory/Generic3X3Container.java b/connector/src/main/java/org/geysermc/connector/inventory/Generic3X3Container.java
new file mode 100644
index 000000000..be8d13a74
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/inventory/Generic3X3Container.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2019-2021 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.inventory;
+
+import lombok.Getter;
+
+public class Generic3X3Container extends Container {
+ /**
+ * Whether we need to set the container type as {@link com.nukkitx.protocol.bedrock.data.inventory.ContainerType#DROPPER}
+ */
+ @Getter
+ private boolean isDropper = false;
+
+ public Generic3X3Container(String title, int id, int size, PlayerInventory playerInventory) {
+ super(title, id, size, playerInventory);
+ }
+
+ @Override
+ public void setUsingRealBlock(boolean usingRealBlock, String javaBlockId) {
+ super.setUsingRealBlock(usingRealBlock, javaBlockId);
+ if (usingRealBlock) {
+ isDropper = javaBlockId.startsWith("minecraft:dropper");
+ }
+ }
+}
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 15357ada3..00d654764 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
@@ -38,7 +38,6 @@ import com.github.steveice10.mc.protocol.data.SubProtocol;
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
import com.github.steveice10.mc.protocol.data.game.recipe.Recipe;
import com.github.steveice10.mc.protocol.data.game.statistic.Statistic;
-import com.github.steveice10.mc.protocol.data.game.window.VillagerTrade;
import com.github.steveice10.mc.protocol.packet.handshake.client.HandshakePacket;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPositionPacket;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPositionRotationPacket;
@@ -73,10 +72,10 @@ import lombok.Setter;
import org.geysermc.common.window.CustomFormWindow;
import org.geysermc.common.window.FormWindow;
import org.geysermc.connector.GeyserConnector;
-import org.geysermc.connector.entity.Tickable;
import org.geysermc.connector.command.CommandSender;
import org.geysermc.connector.common.AuthType;
import org.geysermc.connector.entity.Entity;
+import org.geysermc.connector.entity.Tickable;
import org.geysermc.connector.entity.player.SessionPlayerEntity;
import org.geysermc.connector.entity.player.SkullPlayerEntity;
import org.geysermc.connector.inventory.Inventory;
@@ -234,7 +233,15 @@ public class GeyserSession implements CommandSender {
* Initialized as (0, 0, 0) so it is always not-null.
*/
@Setter
- private Vector3i lastInteractionPosition = Vector3i.ZERO;
+ private Vector3i lastInteractionBlockPosition = Vector3i.ZERO;
+
+ /**
+ * Stores the position of the player the last time they interacted.
+ * Used to verify that the player did not move since their last interaction.
+ * Initialized as (0, 0, 0) so it is always not-null.
+ */
+ @Setter
+ private Vector3f lastInteractionPlayerPosition = Vector3f.ZERO;
@Setter
private Entity ridingVehicleEntity;
@@ -242,15 +249,13 @@ public class GeyserSession implements CommandSender {
@Setter
private long lastWindowCloseTime = 0;
- @Setter
- private VillagerTrade[] villagerTrades;
@Setter
private long lastInteractedVillagerEid;
@Setter
private Int2ObjectMap craftingRecipes;
private final Set unlockedRecipes;
- private AtomicInteger lastRecipeNetId;
+ private final AtomicInteger lastRecipeNetId;
/**
* Saves a list of all stonecutter recipes, for use in a stonecutter inventory.
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 d6c9badb9..79f658188 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
@@ -117,8 +117,9 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator {
@Override
public void translate(LecternUpdatePacket packet, GeyserSession session) {
- session.getConnector().getLogger().error(packet.toString());
if (packet.isDroppingBook()) {
// Bedrock drops the book outside of the GUI. Java drops it in the GUI
// So, we enter the GUI and then drop it! :)
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 e5a9705bc..7fd24080e 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
@@ -33,7 +33,6 @@ 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.data.game.window.WindowType;
import com.nukkitx.protocol.bedrock.data.inventory.ContainerSlotType;
-import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
import com.nukkitx.protocol.bedrock.data.inventory.StackRequestSlotInfoData;
import com.nukkitx.protocol.bedrock.data.inventory.stackrequestactions.*;
import com.nukkitx.protocol.bedrock.packet.ItemStackRequestPacket;
@@ -94,8 +93,8 @@ public abstract class InventoryTranslator {
put(WindowType.STONECUTTER, new StonecutterInventoryTranslator());
/* Generics */
- put(WindowType.GENERIC_3X3, new GenericBlockInventoryTranslator(9, "minecraft:dispenser[facing=north,triggered=false]", ContainerType.DISPENSER));
- put(WindowType.HOPPER, new GenericBlockInventoryTranslator(5, "minecraft:hopper[enabled=false,facing=down]", ContainerType.HOPPER));
+ put(WindowType.GENERIC_3X3, new Generic3X3InventoryTranslator());
+ put(WindowType.HOPPER, new HopperInventoryTranslator());
/* Lectern */
put(WindowType.LECTERN, new LecternInventoryTranslator());
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 5c49c723e..c6da2aeb2 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,43 +26,79 @@
package org.geysermc.connector.network.translators.inventory.holder;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
+import com.google.common.collect.Sets;
import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.nbt.NbtMap;
import com.nukkitx.protocol.bedrock.data.inventory.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.Container;
import org.geysermc.connector.inventory.Inventory;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
+import java.util.Collections;
+import java.util.Set;
+
/**
- * Manages the fake block we implement for each inventory.
+ * Manages the fake block we implement for each inventory, should we need to.
+ * This class will attempt to use a real block first, if possible.
*/
-@AllArgsConstructor
public class BlockInventoryHolder extends InventoryHolder {
- private final int blockId;
+ /**
+ * The default Bedrock block ID to use as a fake block
+ */
+ private final int defaultBedrockBlockId;
private final ContainerType containerType;
+ private final Set validBlocks;
+
+ public BlockInventoryHolder(String javaBlockIdentifier, ContainerType containerType, String... validBlocks) {
+ int javaBlockState = BlockTranslator.getJavaBlockState(javaBlockIdentifier);
+ this.defaultBedrockBlockId = BlockTranslator.getBedrockBlockId(javaBlockState);
+ this.containerType = containerType;
+ if (validBlocks != null) {
+ this.validBlocks = Sets.newHashSet(validBlocks);
+ this.validBlocks.add(javaBlockIdentifier.split("\\[")[0]);
+ } else {
+ this.validBlocks = Collections.singleton(javaBlockIdentifier.split("\\[")[0]);
+ }
+ }
@Override
public void prepareInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) {
- //TODO: Improve on this (for example, multiple block states). We need this for the beacon.
- if (BlockTranslator.getBedrockBlockId(session.getConnector().getWorldManager().getBlockAt(session, session.getLastInteractionPosition())) == blockId) {
- inventory.setHolderPosition(session.getLastInteractionPosition());
- return;
+ // Check to see if there is an existing block we can use that the player just selected.
+ // First, verify that the player's position has not changed, so we don't try to select a block wildly out of range.
+ // (This could be a virtual inventory that the player is opening)
+ if (session.getLastInteractionPlayerPosition().equals(session.getPlayerEntity().getPosition())) {
+ // Then, check to see if the interacted block is valid for this inventory by ensuring the block state identifier is valid
+ int javaBlockId = session.getConnector().getWorldManager().getBlockAt(session, session.getLastInteractionBlockPosition());
+ String javaBlockString = BlockTranslator.getJavaIdBlockMap().inverse().getOrDefault(javaBlockId, "minecraft:air").split("\\[")[0];
+ if (this.validBlocks.contains(javaBlockString)) {
+ // We can safely use this block
+ inventory.setHolderPosition(session.getLastInteractionBlockPosition());
+ ((Container) inventory).setUsingRealBlock(true, javaBlockString);
+ setCustomName(session, session.getLastInteractionBlockPosition(), inventory);
+ return;
+ }
}
+
+ // Otherwise, time to conjure up a fake block!
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.setRuntimeId(defaultBedrockBlockId);
blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
session.sendUpstreamPacket(blockPacket);
inventory.setHolderPosition(position);
+ setCustomName(session, position, inventory);
+ }
+
+ protected void setCustomName(GeyserSession session, Vector3i position, Inventory inventory) {
NbtMap tag = NbtMap.builder()
.putInt("x", position.getX())
.putInt("y", position.getY())
@@ -86,10 +122,12 @@ public class BlockInventoryHolder extends InventoryHolder {
@Override
public void closeInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) {
- Vector3i holderPos = inventory.getHolderPosition();
- if (holderPos.equals(session.getLastInteractionPosition())) {
+ if (((Container) inventory).isUsingRealBlock()) {
+ // No need to reset a block since we didn't change any blocks
return;
}
+
+ Vector3i holderPos = inventory.getHolderPosition();
Position pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ());
int realBlock = session.getConnector().getWorldManager().getBlockAt(session, pos.getX(), pos.getY(), pos.getZ());
UpdateBlockPacket blockPacket = new UpdateBlockPacket();
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/AbstractBlockInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/AbstractBlockInventoryTranslator.java
index 92710656d..8664dc192 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/AbstractBlockInventoryTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/AbstractBlockInventoryTranslator.java
@@ -31,7 +31,6 @@ import org.geysermc.connector.network.session.GeyserSession;
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;
-import org.geysermc.connector.network.translators.world.block.BlockTranslator;
/**
* Provided as a base for any inventory that requires a block for opening it
@@ -45,11 +44,12 @@ public abstract class AbstractBlockInventoryTranslator extends BaseInventoryTran
* @param javaBlockIdentifier a Java block identifier that is used as a temporary block
* @param containerType the container type of this inventory
* @param updater updater
+ * @param additionalValidBlocks any other block identifiers that can safely use this inventory without a fake block
*/
- public AbstractBlockInventoryTranslator(int size, String javaBlockIdentifier, ContainerType containerType, InventoryUpdater updater) {
+ public AbstractBlockInventoryTranslator(int size, String javaBlockIdentifier, ContainerType containerType, InventoryUpdater updater,
+ String... additionalValidBlocks) {
super(size);
- int javaBlockState = BlockTranslator.getJavaBlockState(javaBlockIdentifier);
- this.holder = new BlockInventoryHolder(BlockTranslator.getBedrockBlockId(javaBlockState), containerType);
+ this.holder = new BlockInventoryHolder(javaBlockIdentifier, containerType, additionalValidBlocks);
this.updater = updater;
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/AnvilInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/AnvilInventoryTranslator.java
index 9d4fbfeec..0d2b62153 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/AnvilInventoryTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/AnvilInventoryTranslator.java
@@ -48,7 +48,8 @@ import org.geysermc.connector.network.translators.item.ItemTranslator;
public class AnvilInventoryTranslator extends AbstractBlockInventoryTranslator {
public AnvilInventoryTranslator() {
- super(3, "minecraft:anvil[facing=north]", ContainerType.ANVIL, UIInventoryUpdater.INSTANCE);
+ super(3, "minecraft:anvil[facing=north]", ContainerType.ANVIL, UIInventoryUpdater.INSTANCE,
+ "minecraft:chipped_anvil", "minecraft:damaged_anvil");
}
/* 1.16.100 support start */
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/Generic3X3InventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/Generic3X3InventoryTranslator.java
new file mode 100644
index 000000000..eb417c51e
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/Generic3X3InventoryTranslator.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019-2021 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.translators;
+
+import com.github.steveice10.mc.protocol.data.game.window.WindowType;
+import com.nukkitx.protocol.bedrock.data.inventory.ContainerSlotType;
+import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
+import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
+import org.geysermc.connector.inventory.Generic3X3Container;
+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.BedrockContainerSlot;
+import org.geysermc.connector.network.translators.inventory.updater.ContainerInventoryUpdater;
+
+/**
+ * Droppers and dispensers
+ */
+public class Generic3X3InventoryTranslator extends AbstractBlockInventoryTranslator {
+
+ public Generic3X3InventoryTranslator() {
+ super(9, "minecraft:dispenser[facing=north,triggered=false]", ContainerType.DISPENSER, ContainerInventoryUpdater.INSTANCE,
+ "minecraft:dropper");
+ }
+
+ @Override
+ public Inventory createInventory(String name, int windowId, WindowType windowType, PlayerInventory playerInventory) {
+ return new Generic3X3Container(name, windowId, this.size, playerInventory);
+ }
+
+ @Override
+ public void openInventory(GeyserSession session, Inventory inventory) {
+ ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket();
+ containerOpenPacket.setId((byte) inventory.getId());
+ containerOpenPacket.setType(((Generic3X3Container) inventory).isDropper() ? ContainerType.DROPPER : ContainerType.DISPENSER);
+ containerOpenPacket.setBlockPosition(inventory.getHolderPosition());
+ containerOpenPacket.setUniqueEntityId(inventory.getHolderId());
+ session.sendUpstreamPacket(containerOpenPacket);
+ }
+
+ @Override
+ public BedrockContainerSlot javaSlotToBedrockContainer(int javaSlot) {
+ if (javaSlot < this.size) {
+ return new BedrockContainerSlot(ContainerSlotType.CONTAINER, javaSlot);
+ }
+ return super.javaSlotToBedrockContainer(javaSlot);
+ }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/GenericBlockInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/HopperInventoryTranslator.java
similarity index 87%
rename from connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/GenericBlockInventoryTranslator.java
rename to connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/HopperInventoryTranslator.java
index 55df41c1e..7f067d1c0 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/GenericBlockInventoryTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/HopperInventoryTranslator.java
@@ -33,9 +33,9 @@ import org.geysermc.connector.network.translators.inventory.updater.ContainerInv
/**
* Implemented on top of any block that does not have special properties implemented
*/
-public class GenericBlockInventoryTranslator extends AbstractBlockInventoryTranslator {
- public GenericBlockInventoryTranslator(int size, String javaBlockIdentifier, ContainerType containerType) {
- super(size, javaBlockIdentifier, containerType, ContainerInventoryUpdater.INSTANCE);
+public class HopperInventoryTranslator extends AbstractBlockInventoryTranslator {
+ public HopperInventoryTranslator() {
+ super(5, "minecraft:hopper[enabled=false,facing=down]", ContainerType.HOPPER, ContainerInventoryUpdater.INSTANCE);
}
@Override
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/LecternInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/LecternInventoryTranslator.java
index 9ce0ee0d1..157f63164 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/LecternInventoryTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/LecternInventoryTranslator.java
@@ -98,7 +98,7 @@ public class LecternInventoryTranslator extends BaseInventoryTranslator {
CompoundTag tag = geyserItemStack.getNbt();
if (tag != null) {
// Position has to be the last interacted position... right?
- Vector3i position = session.getLastInteractionPosition();
+ Vector3i position = session.getLastInteractionBlockPosition();
// shouldRefresh means that we should boot out the client on our side because their lectern GUI isn't updated yet
boolean shouldRefresh = !session.getConnector().getWorldManager().shouldExpectLecternHandled() && !session.getLecternCache().contains(position);
int pagesSize = ((ListTag) tag.get("pages")).size();
@@ -124,7 +124,6 @@ public class LecternInventoryTranslator extends BaseInventoryTranslator {
ClientCloseWindowPacket closeWindowPacket = new ClientCloseWindowPacket(lecternContainer.getId());
session.sendDownstreamPacket(closeWindowPacket);
InventoryUtils.closeInventory(session, inventory.getId());
- session.getConnector().getLogger().warning("Closing inventory");
}
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/chest/DoubleChestInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/chest/DoubleChestInventoryTranslator.java
index c27eacff5..d1e628fce 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/chest/DoubleChestInventoryTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/chest/DoubleChestInventoryTranslator.java
@@ -28,32 +28,66 @@ package org.geysermc.connector.network.translators.inventory.translators.chest;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.nbt.NbtMap;
+import com.nukkitx.nbt.NbtMapBuilder;
import com.nukkitx.protocol.bedrock.data.inventory.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.Container;
import org.geysermc.connector.inventory.Inventory;
import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.network.translators.world.block.BlockStateValues;
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
+import org.geysermc.connector.network.translators.world.block.DoubleChestValue;
+import org.geysermc.connector.network.translators.world.block.entity.DoubleChestBlockEntityTranslator;
public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
- private final int blockId;
+ private final int defaultBedrockBlockId;
public DoubleChestInventoryTranslator(int size) {
super(size, 54);
int javaBlockState = BlockTranslator.getJavaBlockState("minecraft:chest[facing=north,type=single,waterlogged=false]");
- this.blockId = BlockTranslator.getBedrockBlockId(javaBlockState);
+ this.defaultBedrockBlockId = BlockTranslator.getBedrockBlockId(javaBlockState);
}
@Override
public void prepareInventory(GeyserSession session, Inventory inventory) {
+ // See BlockInventoryHolder - same concept there except we're also dealing with a specific block state
+ if (session.getLastInteractionPlayerPosition().equals(session.getPlayerEntity().getPosition())) {
+ int javaBlockId = session.getConnector().getWorldManager().getBlockAt(session, session.getLastInteractionBlockPosition());
+ String[] javaBlockString = BlockTranslator.getJavaIdBlockMap().inverse().getOrDefault(javaBlockId, "minecraft:air").split("\\[");
+ if (javaBlockString.length > 1 && (javaBlockString[0].equals("minecraft:chest") || javaBlockString[0].equals("minecraft:trapped_chest"))
+ && !javaBlockString[1].contains("type=single")) {
+ inventory.setHolderPosition(session.getLastInteractionBlockPosition());
+ ((Container) inventory).setUsingRealBlock(true, javaBlockString[0]);
+
+ NbtMapBuilder tag = NbtMap.builder()
+ .putString("id", "Chest")
+ .putInt("x", session.getLastInteractionBlockPosition().getX())
+ .putInt("y", session.getLastInteractionBlockPosition().getY())
+ .putInt("z", session.getLastInteractionBlockPosition().getZ())
+ .putString("CustomName", inventory.getTitle())
+ .putString("id", "Chest");
+
+ DoubleChestValue chestValue = BlockStateValues.getDoubleChestValues().get(javaBlockId);
+ DoubleChestBlockEntityTranslator.translateChestValue(tag, chestValue,
+ session.getLastInteractionBlockPosition().getX(), session.getLastInteractionBlockPosition().getZ());
+
+ BlockEntityDataPacket dataPacket = new BlockEntityDataPacket();
+ dataPacket.setData(tag.build());
+ dataPacket.setBlockPosition(session.getLastInteractionBlockPosition());
+ session.sendUpstreamPacket(dataPacket);
+ return;
+ }
+ }
+
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.setRuntimeId(defaultBedrockBlockId);
blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
session.sendUpstreamPacket(blockPacket);
@@ -73,7 +107,7 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
blockPacket = new UpdateBlockPacket();
blockPacket.setDataLayer(0);
blockPacket.setBlockPosition(pairPosition);
- blockPacket.setRuntimeId(blockId);
+ blockPacket.setRuntimeId(defaultBedrockBlockId);
blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
session.sendUpstreamPacket(blockPacket);
@@ -105,6 +139,11 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
@Override
public void closeInventory(GeyserSession session, Inventory inventory) {
+ if (((Container) inventory).isUsingRealBlock()) {
+ // No need to reset a block since we didn't change any blocks
+ return;
+ }
+
Vector3i holderPos = inventory.getHolderPosition();
Position pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ());
int realBlock = session.getConnector().getWorldManager().getBlockAt(session, pos.getX(), pos.getY(), pos.getZ());
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/chest/SingleChestInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/chest/SingleChestInventoryTranslator.java
index 9fc3c0165..7b9b12c4f 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/chest/SingleChestInventoryTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/translators/chest/SingleChestInventoryTranslator.java
@@ -30,15 +30,14 @@ import org.geysermc.connector.inventory.Inventory;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.inventory.holder.BlockInventoryHolder;
import org.geysermc.connector.network.translators.inventory.holder.InventoryHolder;
-import org.geysermc.connector.network.translators.world.block.BlockTranslator;
public class SingleChestInventoryTranslator extends ChestInventoryTranslator {
private final InventoryHolder holder;
public SingleChestInventoryTranslator(int size) {
super(size, 27);
- int javaBlockState = BlockTranslator.getJavaBlockState("minecraft:chest[facing=north,type=single,waterlogged=false]");
- this.holder = new BlockInventoryHolder(BlockTranslator.getBedrockBlockId(javaBlockState), ContainerType.CONTAINER);
+ this.holder = new BlockInventoryHolder("minecraft:chest[facing=north,type=single,waterlogged=false]", ContainerType.CONTAINER,
+ "minecraft:ender_chest", "minecraft:trapped_chest");
}
@Override
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockChangeTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockChangeTranslator.java
index d74165b14..9bff2652e 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockChangeTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockChangeTranslator.java
@@ -93,7 +93,7 @@ public class JavaBlockChangeTranslator extends PacketTranslator