mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Merge branch 'server-inventory' of https://github.com/GeyserMC/Geyser into server-inventory
This commit is contained in:
commit
9f1fa51cfc
11 changed files with 61 additions and 35 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue