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
protected short transactionId = 0;
@Getter
@Setter
private boolean pending = false;
protected Inventory(int id, int size) {
this("Inventory", id, size);
}

View File

@ -136,6 +136,8 @@ public class GeyserSession implements CommandSender {
private final PlayerInventory playerInventory;
@Setter
private Inventory openInventory;
@Setter
private boolean closingInventory;
@Setter
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.translators.PacketTranslator;
import org.geysermc.connector.network.translators.Translator;
import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
import org.geysermc.connector.utils.InventoryUtils;
@Translator(packet = ContainerClosePacket.class)
@ -42,19 +43,21 @@ public class BedrockContainerCloseTranslator extends PacketTranslator<ContainerC
session.setLastWindowCloseTime(0);
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
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
ClientCloseWindowPacket closeWindowPacket = new ClientCloseWindowPacket(lecternContainer.getId());
session.sendDownstreamPacket(closeWindowPacket);
InventoryUtils.closeInventory(session, lecternContainer.getId());
InventoryUtils.closeInventory(session, lecternContainer.getId(), false);
} else {
// 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)

View File

@ -91,7 +91,7 @@ public class LecternInventoryTranslator extends BaseInventoryTranslator {
ClientClickWindowButtonPacket packet = new ClientClickWindowButtonPacket(inventory.getId(), 3);
session.sendDownstreamPacket(packet);
session.setDroppingLecternBook(false);
InventoryUtils.closeInventory(session, inventory.getId());
InventoryUtils.closeInventory(session, inventory.getId(), false);
} else if (lecternContainer.getBlockEntityTag() == null) {
// If the method returns true, this is already handled for us
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
ClientCloseWindowPacket closeWindowPacket = new ClientCloseWindowPacket(lecternContainer.getId());
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.protocol.bedrock.data.inventory.ContainerType;
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.UpdateBlockPacket;
import org.geysermc.connector.inventory.Container;
@ -142,6 +143,11 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
public void closeInventory(GeyserSession session, Inventory inventory) {
if (((Container) inventory).isUsingRealBlock()) {
// 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;
}

View File

@ -37,10 +37,10 @@ public class SingleChestInventoryTranslator extends ChestInventoryTranslator {
public SingleChestInventoryTranslator(int size) {
super(size, 27);
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
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
return true;
}

View File

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

View File

@ -36,6 +36,6 @@ public class JavaCloseWindowTranslator extends PacketTranslator<ServerCloseWindo
@Override
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.
if (newTranslator == null) {
if (openInventory != null) {
InventoryUtils.closeInventory(session, openInventory.getId());
InventoryUtils.closeInventory(session, openInventory.getId(), true);
}
ClientCloseWindowPacket closeWindowPacket = new ClientCloseWindowPacket(packet.getWindowId());
session.sendDownstreamPacket(closeWindowPacket);
@ -63,7 +63,7 @@ public class JavaOpenWindowTranslator extends PacketTranslator<ServerOpenWindowP
Inventory newInventory = newTranslator.createInventory(name, packet.getWindowId(), packet.getType(), session.getPlayerInventory());
if (openInventory != null) {
InventoryUtils.closeInventory(session, openInventory.getId());
InventoryUtils.closeInventory(session, openInventory.getId(), true);
}
session.setInventoryTranslator(newTranslator);

View File

@ -39,11 +39,10 @@ import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket;
import com.nukkitx.protocol.bedrock.packet.PlayerHotbarPacket;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.common.ChatColor;
import org.geysermc.connector.inventory.GeyserItemStack;
import org.geysermc.connector.inventory.Inventory;
import org.geysermc.connector.inventory.PlayerInventory;
import org.geysermc.connector.inventory.*;
import org.geysermc.connector.network.session.GeyserSession;
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.item.ItemEntry;
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 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();
if (translator != null) {
session.setOpenInventory(inventory);
translator.prepareInventory(session, inventory);
//Ensure at least half a second passes between closing and opening a new window
//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) {
if (translator instanceof DoubleChestInventoryTranslator && !((Container) inventory).isUsingRealBlock()) {
GeyserConnector.getInstance().getGeneralThreadPool().schedule(() -> {
translator.openInventory(session, inventory);
translator.updateInventory(session, inventory);
}, delay, TimeUnit.MILLISECONDS);
session.addInventoryTask(() -> {
Inventory openInv = session.getOpenInventory();
if (openInv != null && openInv.getId() == inventory.getId()) {
translator.openInventory(session, inventory);
translator.updateInventory(session, inventory);
}
});
}, 200, TimeUnit.MILLISECONDS);
} else {
translator.openInventory(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);
updateCursor(session);
@ -86,7 +94,9 @@ public class InventoryUtils {
if (inventory != null) {
InventoryTranslator translator = session.getInventoryTranslator();
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.setOpenInventory(null);