Merge branch 'server-inventory' of https://github.com/GeyserMC/Geyser into server-inventory

This commit is contained in:
Camotoy 2021-02-25 12:15:46 -05:00
commit 9f1fa51cfc
No known key found for this signature in database
GPG Key ID: 7EEFB66FE798081F
11 changed files with 61 additions and 35 deletions

View File

@ -61,6 +61,10 @@ public class Inventory {
@Getter @Getter
protected short transactionId = 0; protected short transactionId = 0;
@Getter
@Setter
private boolean pending = false;
protected Inventory(int id, int size) { protected Inventory(int id, int size) {
this("Inventory", id, size); this("Inventory", id, size);
} }

View File

@ -136,6 +136,8 @@ public class GeyserSession implements CommandSender {
private final PlayerInventory playerInventory; private final PlayerInventory playerInventory;
@Setter @Setter
private Inventory openInventory; private Inventory openInventory;
@Setter
private boolean closingInventory;
@Setter @Setter
private InventoryTranslator inventoryTranslator = InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR; private InventoryTranslator inventoryTranslator = InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR;

View File

@ -31,6 +31,7 @@ import org.geysermc.connector.inventory.Inventory;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.PacketTranslator;
import org.geysermc.connector.network.translators.Translator; import org.geysermc.connector.network.translators.Translator;
import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
import org.geysermc.connector.utils.InventoryUtils; import org.geysermc.connector.utils.InventoryUtils;
@Translator(packet = ContainerClosePacket.class) @Translator(packet = ContainerClosePacket.class)
@ -42,19 +43,21 @@ public class BedrockContainerCloseTranslator extends PacketTranslator<ContainerC
session.setLastWindowCloseTime(0); session.setLastWindowCloseTime(0);
byte windowId = packet.getId(); byte windowId = packet.getId();
if (windowId == -1 && session.getOpenInventory() != null) {
windowId = (byte) session.getOpenInventory().getId();
}
Inventory openInventory = session.getOpenInventory();
if (openInventory != null && windowId == openInventory.getId()) {
ClientCloseWindowPacket closeWindowPacket = new ClientCloseWindowPacket(windowId);
session.sendDownstreamPacket(closeWindowPacket);
InventoryUtils.closeInventory(session, windowId);
}
//Client wants close confirmation //Client wants close confirmation
session.sendUpstreamPacket(packet); session.sendUpstreamPacket(packet);
session.setClosingInventory(false);
Inventory openInventory = session.getOpenInventory();
if (openInventory != null) {
if (windowId == openInventory.getId()) {
ClientCloseWindowPacket closeWindowPacket = new ClientCloseWindowPacket(windowId);
session.sendDownstreamPacket(closeWindowPacket);
InventoryUtils.closeInventory(session, windowId, false);
} else if (openInventory.isPending()) {
InventoryUtils.displayInventory(session, openInventory);
openInventory.setPending(false);
}
}
}); });
} }
} }

View File

@ -70,7 +70,7 @@ public class BedrockLecternUpdateTranslator extends PacketTranslator<LecternUpda
// The same page means Bedrock is closing the window // The same page means Bedrock is closing the window
ClientCloseWindowPacket closeWindowPacket = new ClientCloseWindowPacket(lecternContainer.getId()); ClientCloseWindowPacket closeWindowPacket = new ClientCloseWindowPacket(lecternContainer.getId());
session.sendDownstreamPacket(closeWindowPacket); session.sendDownstreamPacket(closeWindowPacket);
InventoryUtils.closeInventory(session, lecternContainer.getId()); InventoryUtils.closeInventory(session, lecternContainer.getId(), false);
} else { } else {
// Each "page" Bedrock gives to us actually represents two pages (think opening a book and seeing two pages) // Each "page" Bedrock gives to us actually represents two pages (think opening a book and seeing two pages)
// Each "page" on Java is just one page (think a spiral notebook folded back to only show one page) // Each "page" on Java is just one page (think a spiral notebook folded back to only show one page)

View File

@ -91,7 +91,7 @@ public class LecternInventoryTranslator extends BaseInventoryTranslator {
ClientClickWindowButtonPacket packet = new ClientClickWindowButtonPacket(inventory.getId(), 3); ClientClickWindowButtonPacket packet = new ClientClickWindowButtonPacket(inventory.getId(), 3);
session.sendDownstreamPacket(packet); session.sendDownstreamPacket(packet);
session.setDroppingLecternBook(false); session.setDroppingLecternBook(false);
InventoryUtils.closeInventory(session, inventory.getId()); InventoryUtils.closeInventory(session, inventory.getId(), false);
} else if (lecternContainer.getBlockEntityTag() == null) { } else if (lecternContainer.getBlockEntityTag() == null) {
// If the method returns true, this is already handled for us // If the method returns true, this is already handled for us
GeyserItemStack geyserItemStack = inventory.getItem(0); GeyserItemStack geyserItemStack = inventory.getItem(0);
@ -123,7 +123,7 @@ public class LecternInventoryTranslator extends BaseInventoryTranslator {
// Close the window - we will reopen it once the client has this data synced // Close the window - we will reopen it once the client has this data synced
ClientCloseWindowPacket closeWindowPacket = new ClientCloseWindowPacket(lecternContainer.getId()); ClientCloseWindowPacket closeWindowPacket = new ClientCloseWindowPacket(lecternContainer.getId());
session.sendDownstreamPacket(closeWindowPacket); session.sendDownstreamPacket(closeWindowPacket);
InventoryUtils.closeInventory(session, inventory.getId()); InventoryUtils.closeInventory(session, inventory.getId(), false);
} }
} }
} }

View File

@ -31,6 +31,7 @@ import com.nukkitx.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder; import com.nukkitx.nbt.NbtMapBuilder;
import com.nukkitx.protocol.bedrock.data.inventory.ContainerType; import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket;
import com.nukkitx.protocol.bedrock.packet.ContainerClosePacket;
import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket; import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket;
import org.geysermc.connector.inventory.Container; import org.geysermc.connector.inventory.Container;
@ -142,6 +143,11 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
public void closeInventory(GeyserSession session, Inventory inventory) { public void closeInventory(GeyserSession session, Inventory inventory) {
if (((Container) inventory).isUsingRealBlock()) { if (((Container) inventory).isUsingRealBlock()) {
// No need to reset a block since we didn't change any blocks // No need to reset a block since we didn't change any blocks
// But send a container close packet because we aren't destroying the original.
ContainerClosePacket packet = new ContainerClosePacket();
packet.setId((byte) inventory.getId());
packet.setUnknownBool0(true); //TODO needs to be changed in Protocol to "server-side" or something
session.sendUpstreamPacket(packet);
return; return;
} }

View File

@ -37,10 +37,10 @@ public class SingleChestInventoryTranslator extends ChestInventoryTranslator {
public SingleChestInventoryTranslator(int size) { public SingleChestInventoryTranslator(int size) {
super(size, 27); super(size, 27);
this.holder = new BlockInventoryHolder("minecraft:chest[facing=north,type=single,waterlogged=false]", ContainerType.CONTAINER, this.holder = new BlockInventoryHolder("minecraft:chest[facing=north,type=single,waterlogged=false]", ContainerType.CONTAINER,
"minecraft:ender_chest", "minecraft:trapped_chest") { "minecraft:ender_chest", "minecraft:trapped_chest", "minecraft:barrel") {
@Override @Override
protected boolean isValidBlock(String[] javaBlockString) { protected boolean isValidBlock(String[] javaBlockString) {
if (javaBlockString[0].equals("minecraft:ender_chest")) { if (javaBlockString[0].equals("minecraft:ender_chest") || javaBlockString[0].equals("minecraft:barrel")) {
// Can't have double ender chests // Can't have double ender chests
return true; return true;
} }

View File

@ -52,6 +52,7 @@ public class JavaRespawnTranslator extends PacketTranslator<ServerRespawnPacket>
session.addInventoryTask(() -> { session.addInventoryTask(() -> {
session.setInventoryTranslator(InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR); session.setInventoryTranslator(InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR);
session.setOpenInventory(null); session.setOpenInventory(null);
session.setClosingInventory(false);
}); });
SetPlayerGameTypePacket playerGameTypePacket = new SetPlayerGameTypePacket(); SetPlayerGameTypePacket playerGameTypePacket = new SetPlayerGameTypePacket();

View File

@ -36,6 +36,6 @@ public class JavaCloseWindowTranslator extends PacketTranslator<ServerCloseWindo
@Override @Override
public void translate(ServerCloseWindowPacket packet, GeyserSession session) { public void translate(ServerCloseWindowPacket packet, GeyserSession session) {
session.addInventoryTask(() -> InventoryUtils.closeInventory(session, packet.getWindowId())); session.addInventoryTask(() -> InventoryUtils.closeInventory(session, packet.getWindowId(), true));
} }
} }

View File

@ -51,7 +51,7 @@ public class JavaOpenWindowTranslator extends PacketTranslator<ServerOpenWindowP
//No translator exists for this window type. Close all windows and return. //No translator exists for this window type. Close all windows and return.
if (newTranslator == null) { if (newTranslator == null) {
if (openInventory != null) { if (openInventory != null) {
InventoryUtils.closeInventory(session, openInventory.getId()); InventoryUtils.closeInventory(session, openInventory.getId(), true);
} }
ClientCloseWindowPacket closeWindowPacket = new ClientCloseWindowPacket(packet.getWindowId()); ClientCloseWindowPacket closeWindowPacket = new ClientCloseWindowPacket(packet.getWindowId());
session.sendDownstreamPacket(closeWindowPacket); session.sendDownstreamPacket(closeWindowPacket);
@ -63,7 +63,7 @@ public class JavaOpenWindowTranslator extends PacketTranslator<ServerOpenWindowP
Inventory newInventory = newTranslator.createInventory(name, packet.getWindowId(), packet.getType(), session.getPlayerInventory()); Inventory newInventory = newTranslator.createInventory(name, packet.getWindowId(), packet.getType(), session.getPlayerInventory());
if (openInventory != null) { if (openInventory != null) {
InventoryUtils.closeInventory(session, openInventory.getId()); InventoryUtils.closeInventory(session, openInventory.getId(), true);
} }
session.setInventoryTranslator(newTranslator); session.setInventoryTranslator(newTranslator);

View File

@ -39,11 +39,10 @@ import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket;
import com.nukkitx.protocol.bedrock.packet.PlayerHotbarPacket; import com.nukkitx.protocol.bedrock.packet.PlayerHotbarPacket;
import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.common.ChatColor; import org.geysermc.connector.common.ChatColor;
import org.geysermc.connector.inventory.GeyserItemStack; import org.geysermc.connector.inventory.*;
import org.geysermc.connector.inventory.Inventory;
import org.geysermc.connector.inventory.PlayerInventory;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.inventory.InventoryTranslator; import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
import org.geysermc.connector.network.translators.inventory.translators.LecternInventoryTranslator;
import org.geysermc.connector.network.translators.inventory.translators.chest.DoubleChestInventoryTranslator; import org.geysermc.connector.network.translators.inventory.translators.chest.DoubleChestInventoryTranslator;
import org.geysermc.connector.network.translators.item.ItemEntry; import org.geysermc.connector.network.translators.item.ItemEntry;
import org.geysermc.connector.network.translators.item.ItemRegistry; import org.geysermc.connector.network.translators.item.ItemRegistry;
@ -56,21 +55,30 @@ public class InventoryUtils {
public static final ItemStack REFRESH_ITEM = new ItemStack(1, 127, new CompoundTag("")); public static final ItemStack REFRESH_ITEM = new ItemStack(1, 127, new CompoundTag(""));
public static void openInventory(GeyserSession session, Inventory inventory) { public static void openInventory(GeyserSession session, Inventory inventory) {
session.setOpenInventory(inventory);
if (session.isClosingInventory()) {
//Wait for close confirmation from client before opening the new inventory.
//Handled in BedrockContainerCloseTranslator
inventory.setPending(true);
return;
}
displayInventory(session, inventory);
}
public static void displayInventory(GeyserSession session, Inventory inventory) {
InventoryTranslator translator = session.getInventoryTranslator(); InventoryTranslator translator = session.getInventoryTranslator();
if (translator != null) { if (translator != null) {
session.setOpenInventory(inventory);
translator.prepareInventory(session, inventory); translator.prepareInventory(session, inventory);
//Ensure at least half a second passes between closing and opening a new window if (translator instanceof DoubleChestInventoryTranslator && !((Container) inventory).isUsingRealBlock()) {
//The client will not open the new window if it is still closing the old one
long delay = 700 - (System.currentTimeMillis() - session.getLastWindowCloseTime());
if (translator instanceof DoubleChestInventoryTranslator) {
delay = Math.max(delay, 200);
}
if (delay > 0) {
GeyserConnector.getInstance().getGeneralThreadPool().schedule(() -> { GeyserConnector.getInstance().getGeneralThreadPool().schedule(() -> {
session.addInventoryTask(() -> {
Inventory openInv = session.getOpenInventory();
if (openInv != null && openInv.getId() == inventory.getId()) {
translator.openInventory(session, inventory); translator.openInventory(session, inventory);
translator.updateInventory(session, inventory); translator.updateInventory(session, inventory);
}, delay, TimeUnit.MILLISECONDS); }
});
}, 200, TimeUnit.MILLISECONDS);
} else { } else {
translator.openInventory(session, inventory); translator.openInventory(session, inventory);
translator.updateInventory(session, inventory); translator.updateInventory(session, inventory);
@ -78,7 +86,7 @@ public class InventoryUtils {
} }
} }
public static void closeInventory(GeyserSession session, int windowId) { public static void closeInventory(GeyserSession session, int windowId, boolean confirm) {
session.getPlayerInventory().setCursor(GeyserItemStack.EMPTY, session); session.getPlayerInventory().setCursor(GeyserItemStack.EMPTY, session);
updateCursor(session); updateCursor(session);
@ -86,7 +94,9 @@ public class InventoryUtils {
if (inventory != null) { if (inventory != null) {
InventoryTranslator translator = session.getInventoryTranslator(); InventoryTranslator translator = session.getInventoryTranslator();
translator.closeInventory(session, inventory); translator.closeInventory(session, inventory);
session.setLastWindowCloseTime(System.currentTimeMillis()); if (confirm && !inventory.isPending() && !(translator instanceof LecternInventoryTranslator)) {
session.setClosingInventory(true);
}
} }
session.setInventoryTranslator(InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR); session.setInventoryTranslator(InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR);
session.setOpenInventory(null); session.setOpenInventory(null);