forked from GeyserMC/Geyser
Inventory Fixes (#602)
* Fix edge case when shift clicking an output slot * Don't send window close packet if window is already closed * Limit amount of window close packets sent to the client Fixes hidden inventory bar bug * Restrict user from unusable chest inventory slots * Fix crafting table slot mappings * Always send cursor update
This commit is contained in:
parent
18891a22f1
commit
3d357af739
11 changed files with 149 additions and 36 deletions
|
@ -166,6 +166,9 @@ public class GeyserSession implements CommandSender {
|
||||||
@Setter
|
@Setter
|
||||||
private int craftSlot = 0;
|
private int craftSlot = 0;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
private long lastWindowCloseTime = 0;
|
||||||
|
|
||||||
private MinecraftProtocol protocol;
|
private MinecraftProtocol protocol;
|
||||||
|
|
||||||
public GeyserSession(GeyserConnector connector, BedrockServerSession bedrockServerSession) {
|
public GeyserSession(GeyserConnector connector, BedrockServerSession bedrockServerSession) {
|
||||||
|
|
|
@ -38,17 +38,23 @@ public class BedrockContainerCloseTranslator extends PacketTranslator<ContainerC
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void translate(ContainerClosePacket packet, GeyserSession session) {
|
public void translate(ContainerClosePacket packet, GeyserSession session) {
|
||||||
|
session.setLastWindowCloseTime(0);
|
||||||
byte windowId = packet.getWindowId();
|
byte windowId = packet.getWindowId();
|
||||||
|
Inventory openInventory = session.getInventoryCache().getOpenInventory();
|
||||||
if (windowId == -1) { //player inventory or crafting table
|
if (windowId == -1) { //player inventory or crafting table
|
||||||
Inventory openInventory = session.getInventoryCache().getOpenInventory();
|
|
||||||
if (openInventory != null) {
|
if (openInventory != null) {
|
||||||
windowId = (byte) openInventory.getId();
|
windowId = (byte) openInventory.getId();
|
||||||
} else {
|
} else {
|
||||||
windowId = 0;
|
windowId = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ClientCloseWindowPacket closeWindowPacket = new ClientCloseWindowPacket(windowId);
|
|
||||||
session.sendDownstreamPacket(closeWindowPacket);
|
if (windowId == 0 || (openInventory != null && openInventory.getId() == windowId)) {
|
||||||
InventoryUtils.closeInventory(session, windowId);
|
ClientCloseWindowPacket closeWindowPacket = new ClientCloseWindowPacket(windowId);
|
||||||
|
session.getDownstream().getSession().send(closeWindowPacket);
|
||||||
|
InventoryUtils.closeInventory(session, windowId);
|
||||||
|
} else if (openInventory != null && openInventory.getId() != windowId) {
|
||||||
|
InventoryUtils.openInventory(session, openInventory);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* 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.InventoryActionData;
|
||||||
|
import org.geysermc.connector.inventory.Inventory;
|
||||||
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
import org.geysermc.connector.network.translators.inventory.updater.ChestInventoryUpdater;
|
||||||
|
import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater;
|
||||||
|
import org.geysermc.connector.utils.InventoryUtils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public abstract class ChestInventoryTranslator extends BaseInventoryTranslator {
|
||||||
|
private final InventoryUpdater updater;
|
||||||
|
|
||||||
|
public ChestInventoryTranslator(int size, int paddedSize) {
|
||||||
|
super(size);
|
||||||
|
this.updater = new ChestInventoryUpdater(paddedSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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
|
||||||
|
public void translateActions(GeyserSession session, Inventory inventory, List<InventoryActionData> actions) {
|
||||||
|
for (InventoryActionData action : actions) {
|
||||||
|
if (action.getSource().getContainerId() == inventory.getId()) {
|
||||||
|
if (action.getSlot() >= size) {
|
||||||
|
updateInventory(session, inventory);
|
||||||
|
InventoryUtils.updateCursor(session);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.translateActions(session, inventory, actions);
|
||||||
|
}
|
||||||
|
}
|
|
@ -92,7 +92,10 @@ public class CraftingInventoryTranslator extends BaseInventoryTranslator {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int javaSlotToBedrock(int slot) {
|
public int javaSlotToBedrock(int slot) {
|
||||||
return slot == 0 ? 50 : slot + 31;
|
if (slot < size) {
|
||||||
|
return slot == 0 ? 50 : slot + 31;
|
||||||
|
}
|
||||||
|
return super.javaSlotToBedrock(slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -39,15 +39,13 @@ import org.geysermc.connector.network.translators.world.block.BlockTranslator;
|
||||||
import org.geysermc.connector.network.translators.inventory.updater.ChestInventoryUpdater;
|
import org.geysermc.connector.network.translators.inventory.updater.ChestInventoryUpdater;
|
||||||
import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater;
|
import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater;
|
||||||
|
|
||||||
public class DoubleChestInventoryTranslator extends BaseInventoryTranslator {
|
public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
|
||||||
private final int blockId;
|
private final int blockId;
|
||||||
private final InventoryUpdater updater;
|
|
||||||
|
|
||||||
public DoubleChestInventoryTranslator(int size) {
|
public DoubleChestInventoryTranslator(int size) {
|
||||||
super(size);
|
super(size, 54);
|
||||||
BlockState javaBlockState = BlockTranslator.getJavaBlockState("minecraft:chest[facing=north,type=single,waterlogged=false]");
|
BlockState javaBlockState = BlockTranslator.getJavaBlockState("minecraft:chest[facing=north,type=single,waterlogged=false]");
|
||||||
this.blockId = BlockTranslator.getBedrockBlockId(javaBlockState);
|
this.blockId = BlockTranslator.getBedrockBlockId(javaBlockState);
|
||||||
this.updater = new ChestInventoryUpdater(54);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -128,14 +126,4 @@ public class DoubleChestInventoryTranslator extends BaseInventoryTranslator {
|
||||||
blockPacket.setRuntimeId(BlockTranslator.getBedrockBlockId(realBlock));
|
blockPacket.setRuntimeId(BlockTranslator.getBedrockBlockId(realBlock));
|
||||||
session.sendUpstreamPacket(blockPacket);
|
session.sendUpstreamPacket(blockPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
@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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,11 +25,35 @@
|
||||||
|
|
||||||
package org.geysermc.connector.network.translators.inventory;
|
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 com.nukkitx.protocol.bedrock.data.ContainerType;
|
||||||
import org.geysermc.connector.network.translators.inventory.updater.ChestInventoryUpdater;
|
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 class SingleChestInventoryTranslator extends BlockInventoryTranslator {
|
|
||||||
public SingleChestInventoryTranslator(int size) {
|
public SingleChestInventoryTranslator(int size) {
|
||||||
super(size, "minecraft:chest[facing=north,type=single,waterlogged=false]", ContainerType.CONTAINER, new ChestInventoryUpdater(27));
|
super(size, 27);
|
||||||
|
BlockState javaBlockState = BlockTranslator.getJavaBlockState("minecraft:chest[facing=north,type=single,waterlogged=false]");
|
||||||
|
this.holder = new BlockInventoryHolder(BlockTranslator.getBedrockBlockId(javaBlockState), ContainerType.CONTAINER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void prepareInventory(GeyserSession session, Inventory inventory) {
|
||||||
|
holder.prepareInventory(this, session, inventory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void openInventory(GeyserSession session, Inventory inventory) {
|
||||||
|
holder.openInventory(this, session, inventory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void closeInventory(GeyserSession session, Inventory inventory) {
|
||||||
|
holder.closeInventory(this, session, inventory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,11 +187,12 @@ public class InventoryActionDataTranslator {
|
||||||
} else if (translator.getSlotType(javaSlot) == SlotType.OUTPUT) {
|
} else if (translator.getSlotType(javaSlot) == SlotType.OUTPUT) {
|
||||||
plan.add(Click.LEFT, javaSlot);
|
plan.add(Click.LEFT, javaSlot);
|
||||||
} else {
|
} else {
|
||||||
int cursorSlot = findTempSlot(inventory, session.getInventory().getCursor(), Collections.singletonList(javaSlot));
|
int cursorSlot = findTempSlot(inventory, session.getInventory().getCursor(), Collections.singletonList(javaSlot), false);
|
||||||
if (cursorSlot != -1) {
|
if (cursorSlot != -1) {
|
||||||
plan.add(Click.LEFT, cursorSlot);
|
plan.add(Click.LEFT, cursorSlot);
|
||||||
} else {
|
} else {
|
||||||
translator.updateInventory(session, inventory);
|
translator.updateInventory(session, inventory);
|
||||||
|
InventoryUtils.updateCursor(session);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
plan.add(Click.LEFT, javaSlot);
|
plan.add(Click.LEFT, javaSlot);
|
||||||
|
@ -245,11 +246,15 @@ public class InventoryActionDataTranslator {
|
||||||
|
|
||||||
int cursorSlot = -1;
|
int cursorSlot = -1;
|
||||||
if (session.getInventory().getCursor() != null) { //move cursor contents to a temporary slot
|
if (session.getInventory().getCursor() != null) { //move cursor contents to a temporary slot
|
||||||
cursorSlot = findTempSlot(inventory, session.getInventory().getCursor(), Arrays.asList(fromSlot, toSlot));
|
cursorSlot = findTempSlot(inventory,
|
||||||
|
session.getInventory().getCursor(),
|
||||||
|
Arrays.asList(fromSlot, toSlot),
|
||||||
|
translator.getSlotType(fromSlot) == SlotType.OUTPUT);
|
||||||
if (cursorSlot != -1) {
|
if (cursorSlot != -1) {
|
||||||
plan.add(Click.LEFT, cursorSlot);
|
plan.add(Click.LEFT, cursorSlot);
|
||||||
} else {
|
} else {
|
||||||
translator.updateInventory(session, inventory);
|
translator.updateInventory(session, inventory);
|
||||||
|
InventoryUtils.updateCursor(session);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -298,7 +303,7 @@ public class InventoryActionDataTranslator {
|
||||||
InventoryUtils.updateCursor(session);
|
InventoryUtils.updateCursor(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int findTempSlot(Inventory inventory, ItemStack item, List<Integer> slotBlacklist) {
|
private static int findTempSlot(Inventory inventory, ItemStack item, List<Integer> slotBlacklist, boolean emptyOnly) {
|
||||||
/*try and find a slot that can temporarily store the given item
|
/*try and find a slot that can temporarily store the given item
|
||||||
only look in the main inventory and hotbar
|
only look in the main inventory and hotbar
|
||||||
only slots that are empty or contain a different type of item are valid*/
|
only slots that are empty or contain a different type of item are valid*/
|
||||||
|
@ -314,6 +319,9 @@ public class InventoryActionDataTranslator {
|
||||||
ItemStack testItem = inventory.getItem(i);
|
ItemStack testItem = inventory.getItem(i);
|
||||||
boolean acceptable = true;
|
boolean acceptable = true;
|
||||||
if (testItem != null) {
|
if (testItem != null) {
|
||||||
|
if (emptyOnly) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
for (ItemStack blacklistItem : itemBlacklist) {
|
for (ItemStack blacklistItem : itemBlacklist) {
|
||||||
if (InventoryUtils.canStack(testItem, blacklistItem)) {
|
if (InventoryUtils.canStack(testItem, blacklistItem)) {
|
||||||
acceptable = false;
|
acceptable = false;
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
package org.geysermc.connector.network.translators.java.window;
|
package org.geysermc.connector.network.translators.java.window;
|
||||||
|
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.server.window.ServerCloseWindowPacket;
|
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.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;
|
||||||
|
@ -37,9 +36,7 @@ public class JavaCloseWindowTranslator extends PacketTranslator<ServerCloseWindo
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void translate(ServerCloseWindowPacket packet, GeyserSession session) {
|
public void translate(ServerCloseWindowPacket packet, GeyserSession session) {
|
||||||
ContainerClosePacket closePacket = new ContainerClosePacket();
|
InventoryUtils.closeWindow(session, packet.getWindowId());
|
||||||
closePacket.setWindowId((byte)packet.getWindowId());
|
|
||||||
session.sendUpstreamPacket(closePacket);
|
|
||||||
InventoryUtils.closeInventory(session, packet.getWindowId());
|
InventoryUtils.closeInventory(session, packet.getWindowId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,8 +38,6 @@ import org.geysermc.connector.network.translators.Translator;
|
||||||
import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
|
import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
|
||||||
import org.geysermc.connector.utils.InventoryUtils;
|
import org.geysermc.connector.utils.InventoryUtils;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
@Translator(packet = ServerOpenWindowPacket.class)
|
@Translator(packet = ServerOpenWindowPacket.class)
|
||||||
public class JavaOpenWindowTranslator extends PacketTranslator<ServerOpenWindowPacket> {
|
public class JavaOpenWindowTranslator extends PacketTranslator<ServerOpenWindowPacket> {
|
||||||
|
|
||||||
|
@ -80,8 +78,11 @@ public class JavaOpenWindowTranslator extends PacketTranslator<ServerOpenWindowP
|
||||||
if (openInventory != null) {
|
if (openInventory != null) {
|
||||||
InventoryTranslator openTranslator = InventoryTranslator.INVENTORY_TRANSLATORS.get(openInventory.getWindowType());
|
InventoryTranslator openTranslator = InventoryTranslator.INVENTORY_TRANSLATORS.get(openInventory.getWindowType());
|
||||||
if (!openTranslator.getClass().equals(newTranslator.getClass())) {
|
if (!openTranslator.getClass().equals(newTranslator.getClass())) {
|
||||||
|
InventoryUtils.closeWindow(session, openInventory.getId());
|
||||||
InventoryUtils.closeInventory(session, openInventory.getId());
|
InventoryUtils.closeInventory(session, openInventory.getId());
|
||||||
GeyserConnector.getInstance().getGeneralThreadPool().schedule(() -> InventoryUtils.openInventory(session, newInventory), 500, TimeUnit.MILLISECONDS);
|
session.getInventoryCache().setOpenInventory(newInventory);
|
||||||
|
//The new window will be opened when the bedrock client sends the
|
||||||
|
//window close confirmation in BedrockContainerCloseTranslator
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,8 +41,6 @@ public class JavaSetSlotTranslator extends PacketTranslator<ServerSetSlotPacket>
|
||||||
@Override
|
@Override
|
||||||
public void translate(ServerSetSlotPacket packet, GeyserSession session) {
|
public void translate(ServerSetSlotPacket packet, GeyserSession session) {
|
||||||
if (packet.getWindowId() == 255 && packet.getSlot() == -1) { //cursor
|
if (packet.getWindowId() == 255 && packet.getSlot() == -1) { //cursor
|
||||||
if (Objects.equals(session.getInventory().getCursor(), packet.getItem()))
|
|
||||||
return;
|
|
||||||
if (session.getCraftSlot() != 0)
|
if (session.getCraftSlot() != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ import com.nukkitx.nbt.CompoundTagBuilder;
|
||||||
import com.nukkitx.nbt.tag.StringTag;
|
import com.nukkitx.nbt.tag.StringTag;
|
||||||
import com.nukkitx.protocol.bedrock.data.ContainerId;
|
import com.nukkitx.protocol.bedrock.data.ContainerId;
|
||||||
import com.nukkitx.protocol.bedrock.data.ItemData;
|
import com.nukkitx.protocol.bedrock.data.ItemData;
|
||||||
|
import com.nukkitx.protocol.bedrock.packet.ContainerClosePacket;
|
||||||
import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket;
|
import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket;
|
||||||
import org.geysermc.common.ChatColor;
|
import org.geysermc.common.ChatColor;
|
||||||
import org.geysermc.connector.GeyserConnector;
|
import org.geysermc.connector.GeyserConnector;
|
||||||
|
@ -69,19 +70,34 @@ public class InventoryUtils {
|
||||||
public static void closeInventory(GeyserSession session, int windowId) {
|
public static void closeInventory(GeyserSession session, int windowId) {
|
||||||
if (windowId != 0) {
|
if (windowId != 0) {
|
||||||
Inventory inventory = session.getInventoryCache().getInventories().get(windowId);
|
Inventory inventory = session.getInventoryCache().getInventories().get(windowId);
|
||||||
if (inventory != null) {
|
Inventory openInventory = session.getInventoryCache().getOpenInventory();
|
||||||
|
session.getInventoryCache().uncacheInventory(windowId);
|
||||||
|
if (inventory != null && openInventory != null && inventory.getId() == openInventory.getId()) {
|
||||||
InventoryTranslator translator = InventoryTranslator.INVENTORY_TRANSLATORS.get(inventory.getWindowType());
|
InventoryTranslator translator = InventoryTranslator.INVENTORY_TRANSLATORS.get(inventory.getWindowType());
|
||||||
translator.closeInventory(session, inventory);
|
translator.closeInventory(session, inventory);
|
||||||
session.getInventoryCache().uncacheInventory(windowId);
|
|
||||||
session.getInventoryCache().setOpenInventory(null);
|
session.getInventoryCache().setOpenInventory(null);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Inventory inventory = session.getInventory();
|
Inventory inventory = session.getInventory();
|
||||||
InventoryTranslator translator = InventoryTranslator.INVENTORY_TRANSLATORS.get(inventory.getWindowType());
|
InventoryTranslator translator = InventoryTranslator.INVENTORY_TRANSLATORS.get(inventory.getWindowType());
|
||||||
translator.updateInventory(session, inventory);
|
translator.updateInventory(session, inventory);
|
||||||
}
|
}
|
||||||
|
|
||||||
session.setCraftSlot(0);
|
session.setCraftSlot(0);
|
||||||
session.getInventory().setCursor(null);
|
session.getInventory().setCursor(null);
|
||||||
|
updateCursor(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void closeWindow(GeyserSession session, int windowId) {
|
||||||
|
//Spamming close window packets can bug the client
|
||||||
|
if (System.currentTimeMillis() - session.getLastWindowCloseTime() > 500) {
|
||||||
|
ContainerClosePacket closePacket = new ContainerClosePacket();
|
||||||
|
closePacket.setWindowId((byte) windowId);
|
||||||
|
session.sendUpstreamPacket(closePacket);
|
||||||
|
session.setLastWindowCloseTime(System.currentTimeMillis());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void updateCursor(GeyserSession session) {
|
public static void updateCursor(GeyserSession session) {
|
||||||
|
|
Loading…
Reference in a new issue