mirror of
https://github.com/GeyserMC/Geyser.git
synced 2025-04-17 19:12:14 +02:00
compiles
This commit is contained in:
parent
e1abfe8dce
commit
68c2c00561
63 changed files with 594 additions and 404 deletions
core/src/main/java/org/geysermc/geyser
command
inventory
AnvilContainer.javaBeaconContainer.javaCartographyContainer.javaContainer.javaCrafterContainer.javaEnchantingContainer.javaGeneric3X3Container.javaInventory.javaInventoryHolder.javaLecternContainer.javaMerchantContainer.javaPlayerInventory.javaStonecutterContainer.java
click
holder
updater
session
translator
inventory
AbstractBlockInventoryTranslator.javaAnvilInventoryTranslator.javaBaseInventoryTranslator.javaBeaconInventoryTranslator.javaBundleInventoryTranslator.javaCartographyInventoryTranslator.javaCrafterInventoryTranslator.javaEnchantingInventoryTranslator.javaGeneric3X3InventoryTranslator.javaInventoryTranslator.javaLecternInventoryTranslator.javaMerchantInventoryTranslator.javaPlayerInventoryTranslator.javaStonecutterInventoryTranslator.java
chest
protocol
bedrock
BedrockBookEditTranslator.javaBedrockContainerCloseTranslator.javaBedrockFilterTextTranslator.javaBedrockInventoryTransactionTranslator.javaBedrockItemStackRequestTranslator.javaBedrockLecternUpdateTranslator.javaBedrockToggleCrafterSlotRequestTranslator.java
entity
java
entity
inventory
JavaContainerCloseTranslator.javaJavaContainerSetContentTranslator.javaJavaContainerSetDataTranslator.javaJavaContainerSetSlotTranslator.javaJavaHorseScreenOpenTranslator.javaJavaMerchantOffersTranslator.javaJavaOpenBookTranslator.javaJavaOpenScreenTranslator.javaJavaSetPlayerInventoryTranslator.java
util
|
@ -45,6 +45,7 @@ import org.geysermc.geyser.api.util.TriState;
|
|||
import org.geysermc.geyser.command.defaults.AdvancedTooltipsCommand;
|
||||
import org.geysermc.geyser.command.defaults.AdvancementsCommand;
|
||||
import org.geysermc.geyser.command.defaults.ConnectionTestCommand;
|
||||
import org.geysermc.geyser.command.defaults.DebugCommand;
|
||||
import org.geysermc.geyser.command.defaults.DumpCommand;
|
||||
import org.geysermc.geyser.command.defaults.ExtensionsCommand;
|
||||
import org.geysermc.geyser.command.defaults.HelpCommand;
|
||||
|
@ -163,6 +164,7 @@ public class CommandRegistry implements EventRegistrar {
|
|||
registerBuiltInCommand(new AdvancedTooltipsCommand("tooltips", "geyser.commands.advancedtooltips.desc", "geyser.command.tooltips"));
|
||||
registerBuiltInCommand(new ConnectionTestCommand(geyser, "connectiontest", "geyser.commands.connectiontest.desc", "geyser.command.connectiontest"));
|
||||
registerBuiltInCommand(new PingCommand("ping", "geyser.commands.ping.desc", "geyser.command.ping"));
|
||||
registerBuiltInCommand(new DebugCommand("debug", "", "", TriState.TRUE, false, false));
|
||||
if (this.geyser.getPlatformType() == PlatformType.STANDALONE) {
|
||||
registerBuiltInCommand(new StopCommand(geyser, "stop", "geyser.commands.stop.desc", "geyser.command.stop"));
|
||||
}
|
||||
|
|
|
@ -51,6 +51,6 @@ public class AdvancedTooltipsCommand extends GeyserCommand {
|
|||
+ MinecraftLocale.getLocaleString("debug.prefix", session.locale())
|
||||
+ " " + ChatColor.RESET
|
||||
+ MinecraftLocale.getLocaleString("debug.advanced_tooltips." + onOrOff, session.locale()));
|
||||
session.getPlayerInventory().updateInventory();
|
||||
session.getPlayerInventoryHolder().updateInventory();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 2025 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.geyser.command.defaults;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.api.util.TriState;
|
||||
import org.geysermc.geyser.command.GeyserCommand;
|
||||
import org.geysermc.geyser.command.GeyserCommandSource;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.chest.SingleChestInventoryTranslator;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
|
||||
public class DebugCommand extends GeyserCommand {
|
||||
|
||||
public DebugCommand(@NonNull String name, @NonNull String description, @NonNull String permission, @Nullable TriState permissionDefault, boolean playerOnly, boolean bedrockOnly) {
|
||||
super(name, description, permission, permissionDefault, playerOnly, bedrockOnly);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandContext<GeyserCommandSource> context) {
|
||||
GeyserSession session = GeyserImpl.getInstance().getSessionManager().getAllSessions().get(0);
|
||||
|
||||
if (session != null) {
|
||||
|
||||
var holder = session.getOpenInventory();
|
||||
if (holder != null && holder.translator() instanceof SingleChestInventoryTranslator) {
|
||||
for (int i = 0; i <= holder.inventory().getSize(); i++) {
|
||||
int bedrockSlot = holder.translator().javaSlotToBedrock(i);
|
||||
GeyserImpl.getInstance().getLogger().info("java/bedrock slot: " + bedrockSlot);
|
||||
InventorySlotPacket slotPacket = new InventorySlotPacket();
|
||||
slotPacket.setContainerId(ContainerId.INVENTORY);
|
||||
slotPacket.setSlot(bedrockSlot);
|
||||
slotPacket.setItem(ItemData.builder()
|
||||
.count(bedrockSlot)
|
||||
.definition(session.getItemMappings().getStoredItems().glassBottle().getBedrockDefinition())
|
||||
.build());
|
||||
session.sendUpstreamPacket(slotPacket);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -30,7 +30,6 @@ import lombok.Setter;
|
|||
import net.kyori.adventure.text.Component;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentTypes;
|
||||
|
@ -41,7 +40,7 @@ import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.S
|
|||
* the expected level cost for AnvilInventoryUpdater
|
||||
*/
|
||||
@Getter @Setter
|
||||
public class AnvilContainer extends Container<AnvilContainer> {
|
||||
public class AnvilContainer extends Container {
|
||||
/**
|
||||
* Stores the level cost received as a window property from Java
|
||||
*/
|
||||
|
@ -63,8 +62,8 @@ public class AnvilContainer extends Container<AnvilContainer> {
|
|||
|
||||
private int lastTargetSlot = -1;
|
||||
|
||||
public AnvilContainer(GeyserSession session, String title, int id, int size, ContainerType containerType, PlayerInventory playerInventory, InventoryTranslator<AnvilContainer> translator) {
|
||||
super(session, title, id, size, containerType, playerInventory, translator);
|
||||
public AnvilContainer(GeyserSession session, String title, int id, int size, ContainerType containerType) {
|
||||
super(session, title, id, size, containerType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,19 +25,18 @@
|
|||
|
||||
package org.geysermc.geyser.inventory;
|
||||
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class BeaconContainer extends Container<BeaconContainer> {
|
||||
public class BeaconContainer extends Container {
|
||||
private int primaryId;
|
||||
private int secondaryId;
|
||||
|
||||
public BeaconContainer(GeyserSession session, String title, int id, int size, ContainerType containerType, PlayerInventory playerInventory, InventoryTranslator<BeaconContainer> translator) {
|
||||
super(session, title, id, size, containerType, playerInventory, translator);
|
||||
public BeaconContainer(GeyserSession session, String title, int id, int size, ContainerType containerType) {
|
||||
super(session, title, id, size, containerType);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,11 +26,10 @@
|
|||
package org.geysermc.geyser.inventory;
|
||||
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
|
||||
|
||||
public class CartographyContainer extends Container<CartographyContainer> {
|
||||
public CartographyContainer(GeyserSession session, String title, int id, int size, ContainerType containerType, PlayerInventory playerInventory, InventoryTranslator<CartographyContainer> translator) {
|
||||
super(session, title, id, size, containerType, playerInventory, translator);
|
||||
public class CartographyContainer extends Container {
|
||||
public CartographyContainer(GeyserSession session, String title, int id, int size, ContainerType containerType) {
|
||||
super(session, title, id, size, containerType);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ import org.jetbrains.annotations.Range;
|
|||
* Combination of {@link Inventory} and {@link PlayerInventory}
|
||||
*/
|
||||
@Getter
|
||||
public class Container<Type extends Container<Type>> extends Inventory<Type> {
|
||||
public class Container extends Inventory {
|
||||
protected final PlayerInventory playerInventory;
|
||||
private final int containerSize;
|
||||
|
||||
|
@ -46,9 +46,9 @@ public class Container<Type extends Container<Type>> extends Inventory<Type> {
|
|||
*/
|
||||
private boolean isUsingRealBlock = false;
|
||||
|
||||
public Container(GeyserSession session, String title, int id, int size, ContainerType containerType, PlayerInventory playerInventory, InventoryTranslator<Type> translator) {
|
||||
super(session, title, id, size, containerType, translator);
|
||||
this.playerInventory = playerInventory;
|
||||
public Container(GeyserSession session, String title, int id, int size, ContainerType containerType) {
|
||||
super(session, title, id, size, containerType);
|
||||
this.playerInventory = session.getPlayerInventory();
|
||||
this.containerSize = this.size + InventoryTranslator.PLAYER_INVENTORY_SIZE;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ import org.geysermc.geyser.GeyserImpl;
|
|||
import org.jetbrains.annotations.Range;
|
||||
|
||||
@Getter
|
||||
public class CrafterContainer extends Container<CrafterContainer> {
|
||||
public class CrafterContainer extends Container {
|
||||
private GeyserItemStack resultItem = GeyserItemStack.EMPTY;
|
||||
|
||||
@Setter
|
||||
|
@ -48,8 +48,8 @@ public class CrafterContainer extends Container<CrafterContainer> {
|
|||
*/
|
||||
private short disabledSlotsMask = 0;
|
||||
|
||||
public CrafterContainer(GeyserSession session, String title, int id, int size, ContainerType containerType, PlayerInventory playerInventory, InventoryTranslator<CrafterContainer> translator) {
|
||||
super(session, title, id, size, containerType, playerInventory, translator);
|
||||
public CrafterContainer(GeyserSession session, String title, int id, int size, ContainerType containerType) {
|
||||
super(session, title, id, size, containerType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -26,13 +26,12 @@
|
|||
package org.geysermc.geyser.inventory;
|
||||
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.EnchantOptionData;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class EnchantingContainer extends Container<EnchantingContainer> {
|
||||
public class EnchantingContainer extends Container {
|
||||
/**
|
||||
* A cache of what Bedrock sees
|
||||
*/
|
||||
|
@ -42,8 +41,8 @@ public class EnchantingContainer extends Container<EnchantingContainer> {
|
|||
*/
|
||||
private final GeyserEnchantOption[] geyserEnchantOptions;
|
||||
|
||||
public EnchantingContainer(GeyserSession session, String title, int id, int size, ContainerType containerType, PlayerInventory playerInventory, InventoryTranslator<EnchantingContainer> translator) {
|
||||
super(session, title, id, size, containerType, playerInventory, translator);
|
||||
public EnchantingContainer(GeyserSession session, String title, int id, int size, ContainerType containerType) {
|
||||
super(session, title, id, size, containerType);
|
||||
|
||||
enchantOptions = new EnchantOptionData[3];
|
||||
geyserEnchantOptions = new GeyserEnchantOption[3];
|
||||
|
|
|
@ -30,20 +30,19 @@ import org.geysermc.geyser.level.block.Blocks;
|
|||
import org.geysermc.geyser.level.block.type.Block;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.Generic3X3InventoryTranslator;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
|
||||
|
||||
@Getter
|
||||
public class Generic3X3Container extends Container<Generic3X3Container> {
|
||||
public class Generic3X3Container extends Container {
|
||||
/**
|
||||
* Whether we need to set the container type as {@link org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType#DROPPER}.
|
||||
* <p>
|
||||
* Used at {@link Generic3X3InventoryTranslator#openInventory(GeyserSession, Inventory)}
|
||||
* Used at {@link Generic3X3InventoryTranslator#openInventory(GeyserSession, Generic3X3Container)}
|
||||
*/
|
||||
private boolean isDropper = false;
|
||||
|
||||
public Generic3X3Container(GeyserSession session, String title, int id, int size, ContainerType containerType, PlayerInventory playerInventory, InventoryTranslator<Generic3X3Container> translator) {
|
||||
super(session, title, id, size, containerType, playerInventory, translator);
|
||||
public Generic3X3Container(GeyserSession session, String title, int id, int size, ContainerType containerType) {
|
||||
super(session, title, id, size, containerType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -35,7 +35,6 @@ import org.geysermc.geyser.GeyserImpl;
|
|||
import org.geysermc.geyser.inventory.click.ClickPlan;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.geyser.translator.item.ItemTranslator;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentTypes;
|
||||
|
@ -44,7 +43,7 @@ import org.jetbrains.annotations.Range;
|
|||
import java.util.Arrays;
|
||||
|
||||
@ToString
|
||||
public abstract class Inventory<Type extends Inventory<Type>> {
|
||||
public abstract class Inventory {
|
||||
@Getter
|
||||
protected final int javaId;
|
||||
|
||||
|
@ -95,44 +94,24 @@ public abstract class Inventory<Type extends Inventory<Type>> {
|
|||
@Setter
|
||||
protected long holderId = -1;
|
||||
|
||||
/**
|
||||
* Whether this inventory is currently pending.
|
||||
* It can be pending if this inventory was opened while another inventory was still open,
|
||||
* or because opening this inventory takes more time (e.g. virtual inventories).
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean pending = false;
|
||||
|
||||
/**
|
||||
* Whether this inventory is currently shown to the Bedrock player.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean displayed = false;
|
||||
private boolean displayed;
|
||||
|
||||
/**
|
||||
* The translator for this inventory. Stored here to avoid de-syncs of the inventory and current translator.
|
||||
*/
|
||||
@Getter
|
||||
private final InventoryTranslator<Type> translator;
|
||||
|
||||
@Getter
|
||||
private final GeyserSession session;
|
||||
|
||||
protected Inventory(GeyserSession session, int id, int size, ContainerType containerType, InventoryTranslator<Type> translator) {
|
||||
this(session, "Inventory", id, size, containerType, translator);
|
||||
protected Inventory(GeyserSession session, int id, int size, ContainerType containerType) {
|
||||
this(session, "Inventory", id, size, containerType);
|
||||
}
|
||||
|
||||
protected Inventory(GeyserSession session, String title, int javaId, int size, ContainerType containerType, InventoryTranslator<Type> translator) {
|
||||
protected Inventory(GeyserSession session, String title, int javaId, int size, ContainerType containerType) {
|
||||
this.title = title;
|
||||
this.javaId = javaId;
|
||||
this.size = size;
|
||||
this.containerType = containerType;
|
||||
this.items = new GeyserItemStack[size];
|
||||
Arrays.fill(items, GeyserItemStack.EMPTY);
|
||||
this.translator = translator;
|
||||
this.session = session;
|
||||
|
||||
// This is to prevent conflicts with special bedrock inventory IDs.
|
||||
// The vanilla java server only sends an ID between 1 and 100 when opening an inventory,
|
||||
|
@ -144,7 +123,7 @@ public abstract class Inventory<Type extends Inventory<Type>> {
|
|||
// Java wouldn't - e.g. for virtual chest menus that switch pages.
|
||||
// And, well, we want to avoid reusing Bedrock inventory id's that are currently being used in a closing inventory;
|
||||
// so to be safe we just deviate in that case as well.
|
||||
if ((session.getOpenInventory() != null && session.getOpenInventory().getBedrockId() == bedrockId) || session.isClosingInventory()) {
|
||||
if ((session.getOpenInventory() != null && session.getOpenInventory().bedrockId() == bedrockId) || session.isClosingInventory()) {
|
||||
this.bedrockId += 1;
|
||||
}
|
||||
}
|
||||
|
@ -214,36 +193,4 @@ public abstract class Inventory<Type extends Inventory<Type>> {
|
|||
public boolean shouldConfirmContainerClose() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper methods to avoid using the wrong translator to update specific inventories.
|
||||
*/
|
||||
|
||||
public void updateInventory() {
|
||||
this.translator.updateInventory(session, (Type) this);
|
||||
}
|
||||
|
||||
public void updateProperty(int rawProperty, int value) {
|
||||
this.translator.updateProperty(session, (Type) this, rawProperty, value);
|
||||
}
|
||||
|
||||
public void updateSlot(int slot) {
|
||||
this.translator.updateSlot(session, (Type) this, slot);
|
||||
}
|
||||
|
||||
public void openInventory() {
|
||||
this.translator.openInventory(session, (Type) this);
|
||||
}
|
||||
|
||||
public void closeInventory() {
|
||||
this.translator.closeInventory(session, (Type) this);
|
||||
}
|
||||
|
||||
public boolean requiresOpeningDelay() {
|
||||
return this.translator.requiresOpeningDelay(session, (Type) this);
|
||||
}
|
||||
|
||||
public boolean prepareInventory() {
|
||||
return this.translator.prepareInventory(session, (Type) this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* Copyright (c) 2025 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.geyser.inventory;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequest;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A helper class storing the current inventory, translator, and session.
|
||||
*/
|
||||
@Accessors(fluent = true)
|
||||
@Getter
|
||||
public final class InventoryHolder<T extends Inventory> {
|
||||
private final GeyserSession session;
|
||||
private final T inventory;
|
||||
private final InventoryTranslator<T> translator;
|
||||
|
||||
/**
|
||||
* Whether this inventory is currently pending.
|
||||
* It can be pending if this inventory was opened while another inventory was still open,
|
||||
* or because opening this inventory takes more time (e.g. virtual inventories).
|
||||
*/
|
||||
@Setter
|
||||
private boolean pending;
|
||||
|
||||
/**
|
||||
* Stores the number of attempts to open virtual inventories.
|
||||
* Capped at 3, and isn't used in ideal circumstances.
|
||||
* Used to resolve <a href="https://github.com/GeyserMC/Geyser/issues/5426">container closing issues.</a>
|
||||
*/
|
||||
@Setter
|
||||
private int containerOpenAttempts;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public InventoryHolder(GeyserSession session, Inventory newInventory, InventoryTranslator<? extends Inventory> newTranslator) {
|
||||
this.session = session;
|
||||
this.inventory = (T) newInventory;
|
||||
this.translator = (InventoryTranslator<T>) newTranslator;
|
||||
}
|
||||
|
||||
public void markCurrent() {
|
||||
this.session.setOpenInventory(this);
|
||||
}
|
||||
|
||||
public boolean shouldSetPending() {
|
||||
return session.isClosingInventory() || !session.getUpstream().isInitialized() || session.getPendingOrCurrentBedrockInventoryId() != -1;
|
||||
}
|
||||
|
||||
public boolean shouldConfirmClose(boolean confirm) {
|
||||
return confirm && inventory.isDisplayed() && !pending && !(inventory instanceof LecternContainer);
|
||||
}
|
||||
|
||||
public void inheritFromExisting(InventoryHolder<? extends Inventory> existing) {
|
||||
inventory.setBedrockId(existing.inventory.getBedrockId());
|
||||
|
||||
// Also mirror other properties - in case we're e.g. dealing with a pending virtual inventory
|
||||
this.pending = existing.pending();
|
||||
inventory.setDisplayed(existing.inventory().isDisplayed());
|
||||
inventory.setHolderPosition(existing.inventory().getHolderPosition());
|
||||
inventory.setHolderId(existing.inventory().getHolderId());
|
||||
this.markCurrent();
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper methods to avoid using the wrong translator to update specific inventories.
|
||||
*/
|
||||
|
||||
public void updateInventory() {
|
||||
this.translator.updateInventory(session, inventory);
|
||||
}
|
||||
|
||||
public void updateProperty(int rawProperty, int value) {
|
||||
this.translator.updateProperty(session, inventory, rawProperty, value);
|
||||
}
|
||||
|
||||
public void updateSlot(int slot) {
|
||||
this.translator.updateSlot(session, inventory, slot);
|
||||
}
|
||||
|
||||
public void openInventory() {
|
||||
if (session.getOpenInventory() != this) {
|
||||
throw new IllegalStateException("Inventory is not open!");
|
||||
}
|
||||
this.translator.openInventory(session, inventory);
|
||||
this.pending = false;
|
||||
this.inventory.setDisplayed(true);
|
||||
}
|
||||
|
||||
public void closeInventory() {
|
||||
if (session.getOpenInventory() != this) {
|
||||
throw new IllegalStateException("Inventory is not open!");
|
||||
}
|
||||
this.translator.closeInventory(session, inventory);
|
||||
session.getContainerOutputFuture().cancel(true);
|
||||
}
|
||||
|
||||
public boolean requiresOpeningDelay() {
|
||||
return this.translator.requiresOpeningDelay(session, inventory);
|
||||
}
|
||||
|
||||
public boolean prepareInventory() {
|
||||
return this.translator.prepareInventory(session, inventory);
|
||||
}
|
||||
|
||||
public void translateRequests(List<ItemStackRequest> requests) {
|
||||
this.translator.translateRequests(session, inventory, requests);
|
||||
}
|
||||
|
||||
public void checkNetId(ItemStackRequestSlotData data) {
|
||||
this.translator.checkNetId(session, inventory, data);
|
||||
}
|
||||
|
||||
public GeyserSession session() {
|
||||
return session;
|
||||
}
|
||||
|
||||
public T inventory() {
|
||||
return inventory;
|
||||
}
|
||||
|
||||
public InventoryTranslator<T> translator() {
|
||||
return translator;
|
||||
}
|
||||
|
||||
public void incrementContainerOpenAttempts() {
|
||||
this.containerOpenAttempts++;
|
||||
}
|
||||
|
||||
public int javaId() {
|
||||
return inventory.getJavaId();
|
||||
}
|
||||
|
||||
public int bedrockId() {
|
||||
return inventory.getBedrockId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InventoryHolder[" +
|
||||
"session=" + session + ", " +
|
||||
"inventory=" + inventory + ", " +
|
||||
"translator=" + translator + ']';
|
||||
}
|
||||
}
|
|
@ -31,12 +31,11 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||
import org.cloudburstmc.math.vector.Vector3i;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.java.inventory.JavaOpenBookTranslator;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
|
||||
|
||||
@Getter
|
||||
public class LecternContainer extends Container<LecternContainer> {
|
||||
public class LecternContainer extends Container {
|
||||
@Setter
|
||||
private int currentBedrockPage = 0;
|
||||
@Setter
|
||||
|
@ -46,8 +45,8 @@ public class LecternContainer extends Container<LecternContainer> {
|
|||
|
||||
private boolean isBookInPlayerInventory = false;
|
||||
|
||||
public LecternContainer(GeyserSession session, String title, int id, int size, ContainerType containerType, PlayerInventory playerInventory, InventoryTranslator<LecternContainer> translator) {
|
||||
super(session, title, id, size, containerType, playerInventory, translator);
|
||||
public LecternContainer(GeyserSession session, String title, int id, int size, ContainerType containerType) {
|
||||
super(session, title, id, size, containerType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -30,7 +30,6 @@ import lombok.Setter;
|
|||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.geysermc.geyser.entity.type.Entity;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.inventory.VillagerTrade;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.inventory.ClientboundMerchantOffersPacket;
|
||||
|
@ -38,7 +37,7 @@ import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.inventory.C
|
|||
import java.util.List;
|
||||
|
||||
@Setter
|
||||
public class MerchantContainer extends Container<MerchantContainer> {
|
||||
public class MerchantContainer extends Container {
|
||||
@Getter
|
||||
private Entity villager;
|
||||
private List<VillagerTrade> villagerTrades;
|
||||
|
@ -47,8 +46,8 @@ public class MerchantContainer extends Container<MerchantContainer> {
|
|||
@Getter
|
||||
private int tradeExperience;
|
||||
|
||||
public MerchantContainer(GeyserSession session, String title, int id, int size, ContainerType containerType, PlayerInventory playerInventory, InventoryTranslator<MerchantContainer> translator) {
|
||||
super(session, title, id, size, containerType, playerInventory, translator);
|
||||
public MerchantContainer(GeyserSession session, String title, int id, int size, ContainerType containerType) {
|
||||
super(session, title, id, size, containerType);
|
||||
}
|
||||
|
||||
public void onTradeSelected(GeyserSession session, int slot) {
|
||||
|
|
|
@ -31,12 +31,11 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
|
||||
import org.jetbrains.annotations.Range;
|
||||
|
||||
@Getter
|
||||
public class PlayerInventory extends Inventory<PlayerInventory> {
|
||||
public class PlayerInventory extends Inventory {
|
||||
/**
|
||||
* Stores the held item slot, starting at index 0.
|
||||
* Add 36 in order to get the network item slot.
|
||||
|
@ -48,7 +47,7 @@ public class PlayerInventory extends Inventory<PlayerInventory> {
|
|||
private GeyserItemStack cursor = GeyserItemStack.EMPTY;
|
||||
|
||||
public PlayerInventory(GeyserSession session) {
|
||||
super(session, 0, 46, null, InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR);
|
||||
super(session, 0, 46, null);
|
||||
heldItemSlot = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,19 +29,18 @@ import lombok.Getter;
|
|||
import lombok.Setter;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
public class StonecutterContainer extends Container<StonecutterContainer> {
|
||||
public class StonecutterContainer extends Container {
|
||||
/**
|
||||
* The button that has currently been pressed Java-side
|
||||
*/
|
||||
private int stonecutterButton = -1;
|
||||
|
||||
public StonecutterContainer(GeyserSession session, String title, int id, int size, ContainerType containerType, PlayerInventory playerInventory, InventoryTranslator<StonecutterContainer> translator) {
|
||||
super(session, title, id, size, containerType, playerInventory, translator);
|
||||
public StonecutterContainer(GeyserSession session, String title, int id, int size, ContainerType containerType) {
|
||||
super(session, title, id, size, containerType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -66,11 +66,11 @@ public final class ClickPlan {
|
|||
private boolean executionBegan;
|
||||
|
||||
private final GeyserSession session;
|
||||
private final InventoryTranslator translator;
|
||||
private final InventoryTranslator<?> translator;
|
||||
private final Inventory inventory;
|
||||
private final int gridSize;
|
||||
|
||||
public ClickPlan(GeyserSession session, InventoryTranslator translator, Inventory inventory) {
|
||||
public ClickPlan(GeyserSession session, InventoryTranslator<?> translator, Inventory inventory) {
|
||||
this.session = session;
|
||||
this.translator = translator;
|
||||
this.inventory = inventory;
|
||||
|
|
|
@ -90,8 +90,8 @@ public class BlockInventoryHolder extends InventoryHolder {
|
|||
if (Objects.equals(position, previous.getHolderPosition())) {
|
||||
return true;
|
||||
} else {
|
||||
GeyserImpl.getInstance().getLogger().debug(session, "Not reusing inventory (%s) due to virtual block holder changing (%s -> %s)!",
|
||||
InventoryUtils.debugInventory(container), previous.getHolderPosition(), position);
|
||||
GeyserImpl.getInstance().getLogger().debug(session, "Not reusing inventory due to virtual block holder changing (%s -> %s)!",
|
||||
previous.getHolderPosition(), position);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
|
|||
private static final int MAX_LEVEL_COST = 40;
|
||||
|
||||
@Override
|
||||
public void updateInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) {
|
||||
public void updateInventory(InventoryTranslator<?> translator, GeyserSession session, Inventory inventory) {
|
||||
super.updateInventory(translator, session, inventory);
|
||||
AnvilContainer anvilContainer = (AnvilContainer) inventory;
|
||||
updateInventoryState(session, anvilContainer);
|
||||
|
@ -82,7 +82,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean updateSlot(InventoryTranslator translator, GeyserSession session, Inventory inventory, int javaSlot) {
|
||||
public boolean updateSlot(InventoryTranslator<?> translator, GeyserSession session, Inventory inventory, int javaSlot) {
|
||||
if (super.updateSlot(translator, session, inventory, javaSlot))
|
||||
return true;
|
||||
AnvilContainer anvilContainer = (AnvilContainer) inventory;
|
||||
|
@ -151,7 +151,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
|
|||
return 0;
|
||||
}
|
||||
|
||||
private void updateTargetSlot(InventoryTranslator translator, GeyserSession session, AnvilContainer anvilContainer, int slot) {
|
||||
private void updateTargetSlot(InventoryTranslator<?> translator, GeyserSession session, AnvilContainer anvilContainer, int slot) {
|
||||
ItemData itemData = anvilContainer.getItem(slot).getItemData(session);
|
||||
itemData = hijackRepairCost(session, anvilContainer, itemData);
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ public class ChestInventoryUpdater extends InventoryUpdater {
|
|||
private final int paddedSize;
|
||||
|
||||
@Override
|
||||
public void updateInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) {
|
||||
public void updateInventory(InventoryTranslator<?> translator, GeyserSession session, Inventory inventory) {
|
||||
super.updateInventory(translator, session, inventory);
|
||||
|
||||
List<ItemData> bedrockItems = new ArrayList<>(paddedSize);
|
||||
|
@ -65,7 +65,7 @@ public class ChestInventoryUpdater extends InventoryUpdater {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean updateSlot(InventoryTranslator translator, GeyserSession session, Inventory inventory, int javaSlot) {
|
||||
public boolean updateSlot(InventoryTranslator<?> translator, GeyserSession session, Inventory inventory, int javaSlot) {
|
||||
if (super.updateSlot(translator, session, inventory, javaSlot))
|
||||
return true;
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ public class ContainerInventoryUpdater extends InventoryUpdater {
|
|||
public static final ContainerInventoryUpdater INSTANCE = new ContainerInventoryUpdater();
|
||||
|
||||
@Override
|
||||
public void updateInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) {
|
||||
public void updateInventory(InventoryTranslator<?> translator, GeyserSession session, Inventory inventory) {
|
||||
super.updateInventory(translator, session, inventory);
|
||||
|
||||
ItemData[] bedrockItems = new ItemData[translator.size];
|
||||
|
@ -53,7 +53,7 @@ public class ContainerInventoryUpdater extends InventoryUpdater {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean updateSlot(InventoryTranslator translator, GeyserSession session, Inventory inventory, int javaSlot) {
|
||||
public boolean updateSlot(InventoryTranslator<?> translator, GeyserSession session, Inventory inventory, int javaSlot) {
|
||||
if (super.updateSlot(translator, session, inventory, javaSlot))
|
||||
return true;
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ public class CrafterInventoryUpdater extends InventoryUpdater {
|
|||
public static final CrafterInventoryUpdater INSTANCE = new CrafterInventoryUpdater();
|
||||
|
||||
@Override
|
||||
public void updateInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) {
|
||||
public void updateInventory(InventoryTranslator<?> translator, GeyserSession session, Inventory inventory) {
|
||||
ItemData[] bedrockItems;
|
||||
InventoryContentPacket contentPacket;
|
||||
|
||||
|
@ -74,7 +74,7 @@ public class CrafterInventoryUpdater extends InventoryUpdater {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean updateSlot(InventoryTranslator translator, GeyserSession session, Inventory inventory, int javaSlot) {
|
||||
public boolean updateSlot(InventoryTranslator<?> translator, GeyserSession session, Inventory inventory, int javaSlot) {
|
||||
int containerId;
|
||||
if (javaSlot < CrafterInventoryTranslator.GRID_SIZE || javaSlot == CrafterInventoryTranslator.JAVA_RESULT_SLOT) {
|
||||
// Parts of the Crafter UI
|
||||
|
|
|
@ -38,7 +38,7 @@ public class HorseInventoryUpdater extends InventoryUpdater {
|
|||
public static final HorseInventoryUpdater INSTANCE = new HorseInventoryUpdater();
|
||||
|
||||
@Override
|
||||
public void updateInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) {
|
||||
public void updateInventory(InventoryTranslator<?> translator, GeyserSession session, Inventory inventory) {
|
||||
super.updateInventory(translator, session, inventory);
|
||||
|
||||
ItemData[] bedrockItems = new ItemData[translator.size];
|
||||
|
@ -53,7 +53,7 @@ public class HorseInventoryUpdater extends InventoryUpdater {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean updateSlot(InventoryTranslator translator, GeyserSession session, Inventory inventory, int javaSlot) {
|
||||
public boolean updateSlot(InventoryTranslator<?> translator, GeyserSession session, Inventory inventory, int javaSlot) {
|
||||
if (super.updateSlot(translator, session, inventory, javaSlot))
|
||||
return true;
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
|||
import java.util.Arrays;
|
||||
|
||||
public class InventoryUpdater {
|
||||
public void updateInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) {
|
||||
public void updateInventory(InventoryTranslator<?> translator, GeyserSession session, Inventory inventory) {
|
||||
ItemData[] bedrockItems = new ItemData[36];
|
||||
for (int i = 0; i < 36; i++) {
|
||||
final int offset = i < 9 ? 27 : -9;
|
||||
|
@ -48,7 +48,7 @@ public class InventoryUpdater {
|
|||
session.sendUpstreamPacket(contentPacket);
|
||||
}
|
||||
|
||||
public boolean updateSlot(InventoryTranslator translator, GeyserSession session, Inventory inventory, int javaSlot) {
|
||||
public boolean updateSlot(InventoryTranslator<?> translator, GeyserSession session, Inventory inventory, int javaSlot) {
|
||||
if (javaSlot >= translator.size) {
|
||||
InventorySlotPacket slotPacket = new InventorySlotPacket();
|
||||
slotPacket.setContainerId(ContainerId.INVENTORY);
|
||||
|
|
|
@ -35,7 +35,7 @@ public class UIInventoryUpdater extends InventoryUpdater {
|
|||
public static final UIInventoryUpdater INSTANCE = new UIInventoryUpdater();
|
||||
|
||||
@Override
|
||||
public void updateInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) {
|
||||
public void updateInventory(InventoryTranslator<?> translator, GeyserSession session, Inventory inventory) {
|
||||
super.updateInventory(translator, session, inventory);
|
||||
|
||||
for (int i = 0; i < translator.size; i++) {
|
||||
|
@ -51,7 +51,7 @@ public class UIInventoryUpdater extends InventoryUpdater {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean updateSlot(InventoryTranslator translator, GeyserSession session, Inventory inventory, int javaSlot) {
|
||||
public boolean updateSlot(InventoryTranslator<?> translator, GeyserSession session, Inventory inventory, int javaSlot) {
|
||||
if (super.updateSlot(translator, session, inventory, javaSlot))
|
||||
return true;
|
||||
|
||||
|
|
|
@ -138,6 +138,7 @@ import org.geysermc.geyser.erosion.GeyserboundHandshakePacketHandler;
|
|||
import org.geysermc.geyser.event.type.SessionDisconnectEventImpl;
|
||||
import org.geysermc.geyser.impl.camera.CameraDefinitions;
|
||||
import org.geysermc.geyser.impl.camera.GeyserCameraData;
|
||||
import org.geysermc.geyser.inventory.InventoryHolder;
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.inventory.PlayerInventory;
|
||||
import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
|
||||
|
@ -175,6 +176,8 @@ import org.geysermc.geyser.session.cache.WorldBorder;
|
|||
import org.geysermc.geyser.session.cache.WorldCache;
|
||||
import org.geysermc.geyser.session.cache.registry.JavaRegistries;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.geyser.translator.inventory.PlayerInventoryTranslator;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
import org.geysermc.geyser.util.ChunkUtils;
|
||||
import org.geysermc.geyser.util.EntityUtils;
|
||||
|
@ -290,10 +293,10 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||
*/
|
||||
private boolean isInWorldBorderWarningArea = false;
|
||||
|
||||
private final PlayerInventory playerInventory;
|
||||
private final InventoryHolder<PlayerInventory> playerInventoryHolder;
|
||||
|
||||
@Setter
|
||||
private @Nullable Inventory<?> openInventory;
|
||||
private @Nullable InventoryHolder<? extends Inventory> openInventory;
|
||||
|
||||
@Setter
|
||||
private boolean closingInventory;
|
||||
|
@ -534,7 +537,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||
|
||||
/**
|
||||
* Stores whether the Java server requested the player inventory to be closed.
|
||||
* Used to prevent our hacky player inventory closing workaround in {@link org.geysermc.geyser.translator.inventory.PlayerInventoryTranslator#closeInventory(GeyserSession, Inventory)}
|
||||
* Used to prevent our hacky player inventory closing workaround in {@link PlayerInventoryTranslator#closeInventory(GeyserSession, PlayerInventory)}
|
||||
* to run when the closing is initated by the Bedrock client.
|
||||
*/
|
||||
@Setter
|
||||
|
@ -681,15 +684,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||
@Setter
|
||||
private int stepTicks = 0;
|
||||
|
||||
/*
|
||||
* Stores the number of attempts to open virtual inventories.
|
||||
* Capped at 3, and isn't used in ideal circumstances.
|
||||
* Used to resolve https://github.com/GeyserMC/Geyser/issues/5426
|
||||
*/
|
||||
@Setter
|
||||
private int containerOpenAttempts;
|
||||
|
||||
|
||||
public GeyserSession(GeyserImpl geyser, BedrockServerSession bedrockServerSession, EventLoop tickEventLoop) {
|
||||
this.geyser = geyser;
|
||||
this.upstream = new UpstreamSession(bedrockServerSession);
|
||||
|
@ -723,7 +717,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||
this.playerEntity = new SessionPlayerEntity(this);
|
||||
collisionManager.updatePlayerBoundingBox(this.playerEntity.getPosition());
|
||||
|
||||
this.playerInventory = new PlayerInventory(this);
|
||||
this.playerInventoryHolder = new InventoryHolder<>(this, new PlayerInventory(this), InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR);
|
||||
this.openInventory = null;
|
||||
this.craftingRecipes = new Int2ObjectOpenHashMap<>();
|
||||
this.javaToBedrockRecipeIds = new Int2ObjectOpenHashMap<>();
|
||||
|
@ -1239,10 +1233,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||
worldTicks++;
|
||||
}
|
||||
|
||||
public void setAuthenticationData(AuthData authData) {
|
||||
this.authData = authData;
|
||||
}
|
||||
|
||||
public void startSneaking() {
|
||||
// Toggle the shield, if there is no ongoing arm animation
|
||||
// This matches Bedrock Edition behavior as of 1.18.12
|
||||
|
@ -1332,8 +1322,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||
|
||||
public void setClientData(BedrockClientData data) {
|
||||
this.clientData = data;
|
||||
this.inputCache.setInputMode(
|
||||
org.cloudburstmc.protocol.bedrock.data.InputMode.values()[data.getCurrentInputMode().ordinal()]);
|
||||
this.inputCache.setInputMode(org.cloudburstmc.protocol.bedrock.data.InputMode.values()[data.getCurrentInputMode().ordinal()]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1356,9 +1345,9 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||
* blocking and sends a packet to the Java server.
|
||||
*/
|
||||
private boolean attemptToBlock() {
|
||||
if (playerInventory.getItemInHand().asItem() == Items.SHIELD) {
|
||||
if (playerInventoryHolder.inventory().getItemInHand().asItem() == Items.SHIELD) {
|
||||
useItem(Hand.MAIN_HAND);
|
||||
} else if (playerInventory.getOffhand().asItem() == Items.SHIELD) {
|
||||
} else if (playerInventoryHolder.inventory().getOffhand().asItem() == Items.SHIELD) {
|
||||
useItem(Hand.OFF_HAND);
|
||||
} else {
|
||||
// No blocking
|
||||
|
@ -1507,6 +1496,10 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||
return true;
|
||||
}
|
||||
|
||||
public PlayerInventory getPlayerInventory() {
|
||||
return this.playerInventoryHolder.inventory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendForm(@NonNull FormBuilder<?, ?, ?> formBuilder) {
|
||||
formCache.showForm(formBuilder.build());
|
||||
|
|
|
@ -83,8 +83,11 @@ public abstract class AbstractBlockInventoryTranslator<Type extends Container> e
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean canReuseInventory(GeyserSession session, @NonNull Type container, @NonNull Inventory previous) {
|
||||
if (super.canReuseInventory(session, container, previous) && previous instanceof Container previousContainer) {
|
||||
public boolean canReuseInventory(GeyserSession session, @NonNull Inventory newInventory, @NonNull Inventory previous) {
|
||||
if (super.canReuseInventory(session, newInventory, previous)
|
||||
&& newInventory instanceof Container container
|
||||
&& previous instanceof Container previousContainer
|
||||
) {
|
||||
return holder.canReuseContainer(session, container, previousContainer);
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -35,7 +35,6 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action
|
|||
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemStackResponse;
|
||||
import org.geysermc.geyser.inventory.AnvilContainer;
|
||||
import org.geysermc.geyser.inventory.BedrockContainerSlot;
|
||||
import org.geysermc.geyser.inventory.PlayerInventory;
|
||||
import org.geysermc.geyser.inventory.updater.AnvilInventoryUpdater;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
@ -101,8 +100,8 @@ public class AnvilInventoryTranslator extends AbstractBlockInventoryTranslator<A
|
|||
}
|
||||
|
||||
@Override
|
||||
public AnvilContainer createInventory(GeyserSession session, String name, int windowId, ContainerType containerType, PlayerInventory playerInventory) {
|
||||
return new AnvilContainer(session, name, windowId, this.size, containerType, playerInventory, this);
|
||||
public AnvilContainer createInventory(GeyserSession session, String name, int windowId, ContainerType containerType) {
|
||||
return new AnvilContainer(session, name, windowId, this.size, containerType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -90,8 +90,8 @@ public abstract class BaseInventoryTranslator<Type extends Container> extends In
|
|||
}
|
||||
|
||||
@Override
|
||||
public Type createInventory(GeyserSession session, String name, int windowId, ContainerType containerType, PlayerInventory playerInventory) {
|
||||
public Type createInventory(GeyserSession session, String name, int windowId, ContainerType containerType) {
|
||||
//noinspection unchecked
|
||||
return (Type) new Container(session, name, windowId, this.size, containerType, playerInventory, this);
|
||||
return (Type) new Container(session, name, windowId, this.size, containerType);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,6 @@ import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket;
|
|||
import org.geysermc.geyser.inventory.BeaconContainer;
|
||||
import org.geysermc.geyser.inventory.BedrockContainerSlot;
|
||||
import org.geysermc.geyser.inventory.Container;
|
||||
import org.geysermc.geyser.inventory.PlayerInventory;
|
||||
import org.geysermc.geyser.inventory.holder.BlockInventoryHolder;
|
||||
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
|
@ -143,8 +142,8 @@ public class BeaconInventoryTranslator extends AbstractBlockInventoryTranslator<
|
|||
}
|
||||
|
||||
@Override
|
||||
public BeaconContainer createInventory(GeyserSession session, String name, int windowId, ContainerType containerType, PlayerInventory playerInventory) {
|
||||
return new BeaconContainer(session, name, windowId, this.size, containerType, playerInventory, this);
|
||||
public BeaconContainer createInventory(GeyserSession session, String name, int windowId, ContainerType containerType) {
|
||||
return new BeaconContainer(session, name, windowId, this.size, containerType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -56,7 +56,7 @@ public final class BundleInventoryTranslator {
|
|||
* @return a processed bundle interaction, or null to resume normal transaction handling.
|
||||
*/
|
||||
@Nullable
|
||||
static ItemStackResponse handleBundle(GeyserSession session, InventoryTranslator translator, Inventory inventory, ItemStackRequest request, boolean sendCreativePackets) {
|
||||
static <T extends Inventory> ItemStackResponse handleBundle(GeyserSession session, InventoryTranslator<T> translator, T inventory, ItemStackRequest request, boolean sendCreativePackets) {
|
||||
TransferItemStackRequestAction action = null;
|
||||
for (ItemStackRequestAction requestAction : request.getActions()) {
|
||||
if (requestAction instanceof SwapAction swapAction) {
|
||||
|
|
|
@ -86,8 +86,8 @@ public class CartographyInventoryTranslator extends AbstractBlockInventoryTransl
|
|||
}
|
||||
|
||||
@Override
|
||||
public CartographyContainer createInventory(GeyserSession session, String name, int windowId, ContainerType containerType, PlayerInventory playerInventory) {
|
||||
return new CartographyContainer(session, name, windowId, this.size, containerType, playerInventory, this);
|
||||
public CartographyContainer createInventory(GeyserSession session, String name, int windowId, ContainerType containerType) {
|
||||
return new CartographyContainer(session, name, windowId, this.size, containerType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -137,9 +137,9 @@ public class CrafterInventoryTranslator extends AbstractBlockInventoryTranslator
|
|||
}
|
||||
|
||||
@Override
|
||||
public CrafterContainer createInventory(GeyserSession session, String name, int windowId, ContainerType containerType, PlayerInventory playerInventory) {
|
||||
public CrafterContainer createInventory(GeyserSession session, String name, int windowId, ContainerType containerType) {
|
||||
// Java sends the triggered and slot bits incrementally through properties, which we store here
|
||||
return new CrafterContainer(session, name, windowId, this.size, containerType, playerInventory, this);
|
||||
return new CrafterContainer(session, name, windowId, this.size, containerType);
|
||||
}
|
||||
|
||||
private static void updateBlockEntity(GeyserSession session, CrafterContainer container) {
|
||||
|
|
|
@ -167,8 +167,8 @@ public class EnchantingInventoryTranslator extends AbstractBlockInventoryTransla
|
|||
}
|
||||
|
||||
@Override
|
||||
public EnchantingContainer createInventory(GeyserSession session, String name, int windowId, ContainerType containerType, PlayerInventory playerInventory) {
|
||||
return new EnchantingContainer(session, name, windowId, this.size, containerType, playerInventory, this);
|
||||
public EnchantingContainer createInventory(GeyserSession session, String name, int windowId, ContainerType containerType) {
|
||||
return new EnchantingContainer(session, name, windowId, this.size, containerType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -29,7 +29,6 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
|
|||
import org.cloudburstmc.protocol.bedrock.packet.ContainerOpenPacket;
|
||||
import org.geysermc.geyser.inventory.BedrockContainerSlot;
|
||||
import org.geysermc.geyser.inventory.Generic3X3Container;
|
||||
import org.geysermc.geyser.inventory.PlayerInventory;
|
||||
import org.geysermc.geyser.inventory.updater.ContainerInventoryUpdater;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
@ -45,8 +44,8 @@ public class Generic3X3InventoryTranslator extends AbstractBlockInventoryTransla
|
|||
}
|
||||
|
||||
@Override
|
||||
public Generic3X3Container createInventory(GeyserSession session, String name, int windowId, ContainerType containerType, PlayerInventory playerInventory) {
|
||||
return new Generic3X3Container(session, name, windowId, this.size, containerType, playerInventory, this);
|
||||
public Generic3X3Container createInventory(GeyserSession session, String name, int windowId, ContainerType containerType) {
|
||||
return new Generic3X3Container(session, name, windowId, this.size, containerType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -145,44 +145,76 @@ public abstract class InventoryTranslator<Type extends Inventory> {
|
|||
/**
|
||||
* Whether a new inventory should be prepared - or if we can re-use the previous one.
|
||||
*/
|
||||
public boolean canReuseInventory(GeyserSession session, @NonNull Type inventory, @NonNull Inventory previous) {
|
||||
public boolean canReuseInventory(GeyserSession session, @NonNull Inventory inventory, @NonNull Inventory previous) {
|
||||
// Filter for mismatches that require a new inventory.
|
||||
if (inventory.getContainerType() == null || previous.getContainerType() == null
|
||||
|| !Objects.equals(inventory.getContainerType(), previous.getContainerType())
|
||||
if (inventory.getContainerType() == null || previous.getContainerType() == null ||
|
||||
!Objects.equals(inventory.getContainerType(), previous.getContainerType()) ||
|
||||
!Objects.equals(inventory.getTitle(), previous.getTitle()) ||
|
||||
inventory.getSize() != previous.getSize()
|
||||
) {
|
||||
GeyserImpl.getInstance().getLogger().debug(session, "Not reusing inventory (%s) due to type change! ", InventoryUtils.debugInventory(inventory));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (inventory.getSize() != previous.getSize()) {
|
||||
GeyserImpl.getInstance().getLogger().debug(session, "Not reusing inventory (%s) due to size change! ", InventoryUtils.debugInventory(inventory));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Objects.equals(inventory.getTitle(), previous.getTitle())) {
|
||||
GeyserImpl.getInstance().getLogger().debug(session, "Not reusing inventory (%s) due to title change! ", InventoryUtils.debugInventory(inventory));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (previous.getHolderId() == -1 && previous.getHolderPosition() == Vector3i.ZERO) {
|
||||
GeyserImpl.getInstance().getLogger().debug(session, "Not reusing inventory (%s) since the old was not initialized! ", InventoryUtils.debugInventory(inventory));
|
||||
return false;
|
||||
}
|
||||
|
||||
// We can likely reuse the inventory!
|
||||
return true;
|
||||
// Finally, ensure that the previous inventory has been initialized
|
||||
return previous.getHolderId() != -1 || previous.getHolderPosition() != Vector3i.ZERO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the inventory before opening it. Bedrock requires the inventory to "exist" before opening it - that can be
|
||||
* either a real block (e.g. chest), or an entity (e.g. horse)
|
||||
* @return whether the inventory was successfully prepared
|
||||
*/
|
||||
public abstract boolean prepareInventory(GeyserSession session, Type inventory);
|
||||
|
||||
/**
|
||||
* Opens the previously prepared inventory.
|
||||
*/
|
||||
public abstract void openInventory(GeyserSession session, Type inventory);
|
||||
|
||||
/**
|
||||
* Closes the inventory, and if necessary, cleans up the prepared inventory.
|
||||
*/
|
||||
public abstract void closeInventory(GeyserSession session, Type inventory);
|
||||
|
||||
/**
|
||||
* Updates a property in the inventory.
|
||||
*/
|
||||
public abstract void updateProperty(GeyserSession session, Type inventory, int key, int value);
|
||||
|
||||
/**
|
||||
* Updates the inventory by re-sending items for all slots of the inventory.
|
||||
*/
|
||||
public abstract void updateInventory(GeyserSession session, Type inventory);
|
||||
|
||||
/**
|
||||
* Updates a specific slot by re-sending the item.
|
||||
*/
|
||||
public abstract void updateSlot(GeyserSession session, Type inventory, int slot);
|
||||
|
||||
/**
|
||||
* Converts the Bedrock slot to the corresponding Java slot.
|
||||
*/
|
||||
public abstract int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData);
|
||||
|
||||
/**
|
||||
* Converts a Java slot to the corresponding Bedrock slot.
|
||||
*/
|
||||
public abstract int javaSlotToBedrock(int javaSlot);
|
||||
|
||||
/**
|
||||
* Converts a Java slot to the corresponding Bedrock container and slot
|
||||
*/
|
||||
public abstract BedrockContainerSlot javaSlotToBedrockContainer(int javaSlot);
|
||||
|
||||
/**
|
||||
* Returns the slot type for a Java slot id
|
||||
*/
|
||||
public abstract SlotType getSlotType(int javaSlot);
|
||||
public abstract Type createInventory(GeyserSession session, String name, int windowId, ContainerType containerType, PlayerInventory playerInventory);
|
||||
|
||||
/**
|
||||
* Creates a new inventory.
|
||||
*/
|
||||
public abstract Type createInventory(GeyserSession session, String name, int windowId, ContainerType containerType);
|
||||
|
||||
/**
|
||||
* Used for crafting-related transactions. Will override in PlayerInventoryTranslator and CraftingInventoryTranslator.
|
||||
|
|
|
@ -33,7 +33,6 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
|
|||
import org.geysermc.erosion.util.LecternUtils;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.inventory.LecternContainer;
|
||||
import org.geysermc.geyser.inventory.PlayerInventory;
|
||||
import org.geysermc.geyser.inventory.updater.ContainerInventoryUpdater;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
import org.geysermc.geyser.level.block.property.Properties;
|
||||
|
@ -132,7 +131,7 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator
|
|||
public void updateSlot(GeyserSession session, LecternContainer container, int slot) {
|
||||
// If we're not in a real lectern, the Java server thinks we are still in the player inventory.
|
||||
if (container.isBookInPlayerInventory()) {
|
||||
InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR.updateSlot(session, session.getPlayerInventory(), slot);
|
||||
session.getPlayerInventoryHolder().updateSlot(slot);
|
||||
return;
|
||||
}
|
||||
super.updateSlot(session, container, slot);
|
||||
|
@ -198,7 +197,7 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator
|
|||
}
|
||||
|
||||
@Override
|
||||
public LecternContainer createInventory(GeyserSession session, String name, int windowId, ContainerType containerType, PlayerInventory playerInventory) {
|
||||
return new LecternContainer(session, name, windowId, this.size + playerInventory.getSize(), containerType, playerInventory, this);
|
||||
public LecternContainer createInventory(GeyserSession session, String name, int windowId, ContainerType containerType) {
|
||||
return new LecternContainer(session, name, windowId, this.size, containerType);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -164,7 +164,8 @@ public class MerchantInventoryTranslator extends BaseInventoryTranslator<Merchan
|
|||
// so we need to work around that with the delay. Specifically they force a window refresh after a
|
||||
// trade packet has been sent.
|
||||
session.scheduleInEventLoop(() -> {
|
||||
if (session.getOpenInventory() instanceof MerchantContainer merchantInventory) {
|
||||
InventoryHolder<? extends Inventory> holder = session.getOpenInventory();
|
||||
if (holder != null && holder.inventory() instanceof MerchantContainer merchantInventory) {
|
||||
merchantInventory.onTradeSelected(session, tradeChoice);
|
||||
// Ignore output since we don't want to send a delayed response packet back to the client
|
||||
translateRequest(session, inventory, request);
|
||||
|
@ -191,7 +192,7 @@ public class MerchantInventoryTranslator extends BaseInventoryTranslator<Merchan
|
|||
}
|
||||
|
||||
@Override
|
||||
public MerchantContainer createInventory(GeyserSession session, String name, int windowId, ContainerType containerType, PlayerInventory playerInventory) {
|
||||
return new MerchantContainer(session, name, windowId, this.size, containerType, playerInventory, this);
|
||||
public MerchantContainer createInventory(GeyserSession session, String name, int windowId, ContainerType containerType) {
|
||||
return new MerchantContainer(session, name, windowId, this.size, containerType);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -570,12 +570,12 @@ public class PlayerInventoryTranslator extends InventoryTranslator<PlayerInvento
|
|||
}
|
||||
|
||||
@Override
|
||||
public PlayerInventory createInventory(GeyserSession session, String name, int windowId, ContainerType containerType, PlayerInventory playerInventory) {
|
||||
public PlayerInventory createInventory(GeyserSession session, String name, int windowId, ContainerType containerType) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canReuseInventory(GeyserSession session, @NonNull PlayerInventory inventory, @NonNull Inventory previous) {
|
||||
public boolean canReuseInventory(GeyserSession session, @NonNull Inventory inventory, @NonNull Inventory previous) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -122,8 +122,8 @@ public class StonecutterInventoryTranslator extends AbstractBlockInventoryTransl
|
|||
}
|
||||
|
||||
@Override
|
||||
public StonecutterContainer createInventory(GeyserSession session, String name, int windowId, ContainerType containerType, PlayerInventory playerInventory) {
|
||||
return new StonecutterContainer(session, name, windowId, this.size, containerType, playerInventory, this);
|
||||
public StonecutterContainer createInventory(GeyserSession session, String name, int windowId, ContainerType containerType) {
|
||||
return new StonecutterContainer(session, name, windowId, this.size, containerType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -68,8 +68,9 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
|
|||
* Mirrors {@link BlockInventoryHolder#canReuseContainer(GeyserSession, Container, Container)}
|
||||
*/
|
||||
@Override
|
||||
public boolean canReuseInventory(GeyserSession session, @NonNull Container container, @NonNull Inventory oldInventory) {
|
||||
if (!super.canReuseInventory(session, container, oldInventory) ||
|
||||
public boolean canReuseInventory(GeyserSession session, @NonNull Inventory newInventory, @NonNull Inventory oldInventory) {
|
||||
if (!super.canReuseInventory(session, newInventory, oldInventory) ||
|
||||
!(newInventory instanceof Container) ||
|
||||
!(oldInventory instanceof Container previous)
|
||||
) {
|
||||
return false;
|
||||
|
@ -85,8 +86,8 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
|
|||
if (Objects.equals(position, previous.getHolderPosition())) {
|
||||
return true;
|
||||
} else {
|
||||
GeyserImpl.getInstance().getLogger().debug(session, "Not reusing inventory (%s) due to virtual block holder changing (%s -> %s)!",
|
||||
InventoryUtils.debugInventory(container), previous.getHolderPosition(), position);
|
||||
GeyserImpl.getInstance().getLogger().debug(session, "Not reusing inventory due to virtual block holder changing (%s -> %s)!",
|
||||
previous.getHolderPosition(), position);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ public class BedrockBookEditTranslator extends PacketTranslator<BookEditPacket>
|
|||
|
||||
// Update local copy
|
||||
session.getPlayerInventory().setItem(36 + session.getPlayerInventory().getHeldItemSlot(), GeyserItemStack.from(bookItem), session);
|
||||
session.getPlayerInventory().updateInventory();
|
||||
session.getPlayerInventoryHolder().updateInventory();
|
||||
|
||||
String title;
|
||||
if (packet.getAction() == BookEditPacket.Action.SIGN_BOOK) {
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.cloudburstmc.protocol.bedrock.packet.ContainerClosePacket;
|
|||
import org.cloudburstmc.protocol.bedrock.packet.NetworkStackLatencyPacket;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.inventory.InventoryHolder;
|
||||
import org.geysermc.geyser.inventory.MerchantContainer;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.MerchantInventoryTranslator;
|
||||
|
@ -54,17 +55,18 @@ public class BedrockContainerCloseTranslator extends PacketTranslator<ContainerC
|
|||
session.setClosingInventory(false);
|
||||
|
||||
// 1.21.70: Bedrock can reject opening inventories - in those cases it replies with -1
|
||||
Inventory openInventory = session.getOpenInventory();
|
||||
if (bedrockId == -1 && openInventory != null) {
|
||||
InventoryHolder<? extends Inventory> holder = session.getOpenInventory();
|
||||
if (bedrockId == -1 && holder != null) {
|
||||
// 1.16.200 - window ID is always -1 sent from Bedrock for merchant containers
|
||||
if (openInventory.getTranslator() instanceof MerchantInventoryTranslator) {
|
||||
bedrockId = (byte) openInventory.getBedrockId();
|
||||
} else if (openInventory.getBedrockId() == session.getPendingOrCurrentBedrockInventoryId()) {
|
||||
if (holder.translator() instanceof MerchantInventoryTranslator) {
|
||||
bedrockId = (byte) holder.bedrockId();
|
||||
} else if (holder.bedrockId() == session.getPendingOrCurrentBedrockInventoryId()) {
|
||||
// If virtual inventories are opened too quickly, they can be occasionally rejected
|
||||
// We just try and queue a new one.
|
||||
// Before making another attempt to re-open, let's make sure we actually need this inventory open.
|
||||
if (session.getContainerOpenAttempts() < 3) {
|
||||
openInventory.setPending(true);
|
||||
if (holder.containerOpenAttempts() < 3) {
|
||||
holder.incrementContainerOpenAttempts();
|
||||
holder.pending(true);
|
||||
|
||||
session.scheduleInEventLoop(() -> {
|
||||
NetworkStackLatencyPacket latencyPacket = new NetworkStackLatencyPacket();
|
||||
|
@ -82,19 +84,18 @@ public class BedrockContainerCloseTranslator extends PacketTranslator<ContainerC
|
|||
}
|
||||
|
||||
session.setPendingOrCurrentBedrockInventoryId(-1);
|
||||
session.setContainerOpenAttempts(0);
|
||||
closeCurrentOrOpenPending(session, bedrockId, openInventory);
|
||||
closeCurrentOrOpenPending(session, bedrockId, holder);
|
||||
}
|
||||
|
||||
private void closeCurrentOrOpenPending(GeyserSession session, byte bedrockId, Inventory openInventory) {
|
||||
if (openInventory != null) {
|
||||
if (bedrockId == openInventory.getBedrockId()) {
|
||||
InventoryUtils.sendJavaContainerClose(session, openInventory);
|
||||
InventoryUtils.closeInventory(session, openInventory.getJavaId(), false);
|
||||
} else if (openInventory.isPending()) {
|
||||
InventoryUtils.displayInventory(session, openInventory);
|
||||
private void closeCurrentOrOpenPending(GeyserSession session, byte bedrockId, InventoryHolder<? extends Inventory> holder) {
|
||||
if (holder != null) {
|
||||
if (bedrockId == holder.bedrockId()) {
|
||||
InventoryUtils.sendJavaContainerClose(holder);
|
||||
InventoryUtils.closeInventory(session, holder.javaId(), false);
|
||||
} else if (holder.pending()) {
|
||||
InventoryUtils.displayInventory(holder);
|
||||
|
||||
if (openInventory instanceof MerchantContainer merchantContainer && merchantContainer.getPendingOffersPacket() != null) {
|
||||
if (holder.inventory() instanceof MerchantContainer merchantContainer && merchantContainer.getPendingOffersPacket() != null) {
|
||||
JavaMerchantOffersTranslator.openMerchant(session, merchantContainer.getPendingOffersPacket(), merchantContainer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ package org.geysermc.geyser.translator.protocol.bedrock;
|
|||
import org.cloudburstmc.protocol.bedrock.packet.FilterTextPacket;
|
||||
import org.geysermc.geyser.inventory.AnvilContainer;
|
||||
import org.geysermc.geyser.inventory.CartographyContainer;
|
||||
import org.geysermc.geyser.inventory.InventoryHolder;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
|
@ -41,14 +42,15 @@ public class BedrockFilterTextTranslator extends PacketTranslator<FilterTextPack
|
|||
|
||||
@Override
|
||||
public void translate(GeyserSession session, FilterTextPacket packet) {
|
||||
if (session.getOpenInventory() instanceof CartographyContainer) {
|
||||
InventoryHolder<?> holder = session.getOpenInventory();
|
||||
if (holder != null && holder.inventory() instanceof CartographyContainer) {
|
||||
// We don't want to be able to rename in the cartography table
|
||||
return;
|
||||
}
|
||||
packet.setFromServer(true);
|
||||
if (session.getOpenInventory() instanceof AnvilContainer anvilContainer) {
|
||||
if (holder != null && holder.inventory() instanceof AnvilContainer anvilContainer) {
|
||||
packet.setText(anvilContainer.checkForRename(session, packet.getText()));
|
||||
anvilContainer.updateSlot(1);
|
||||
holder.updateSlot(1);
|
||||
}
|
||||
session.sendUpstreamPacket(packet);
|
||||
}
|
||||
|
|
|
@ -70,7 +70,6 @@ import org.geysermc.geyser.registry.BlockRegistries;
|
|||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.cache.SkullCache;
|
||||
import org.geysermc.geyser.skin.FakeHeadProvider;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.geyser.translator.item.ItemTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
|
@ -363,7 +362,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
|||
}
|
||||
case 1 -> {
|
||||
if (isIncorrectHeldItem(session, packet)) {
|
||||
InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR.updateSlot(session, session.getPlayerInventory(), session.getPlayerInventory().getOffsetForHotbar(packet.getHotbarSlot()));
|
||||
session.getPlayerInventoryHolder().updateSlot(session.getPlayerInventory().getOffsetForHotbar(packet.getHotbarSlot()));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -580,7 +579,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
|||
session.sendUpstreamPacket(updateWaterPacket);
|
||||
|
||||
// Reset the item in hand to prevent "missing" blocks
|
||||
InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR.updateSlot(session, session.getPlayerInventory(), session.getPlayerInventory().getHeldItemSlot()); // TODO test
|
||||
session.getPlayerInventoryHolder().updateSlot(session.getPlayerInventory().getHeldItemSlot()); // TODO test
|
||||
}
|
||||
|
||||
private boolean isIncorrectHeldItem(GeyserSession session, InventoryTransactionPacket packet) {
|
||||
|
@ -601,7 +600,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
|||
// Update the player's inventory to remove any items added by the client itself
|
||||
PlayerInventory playerInventory = session.getPlayerInventory();
|
||||
int heldItemSlot = playerInventory.getOffsetForHotbar(packet.getHotbarSlot());
|
||||
InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR.updateSlot(session, playerInventory, heldItemSlot);
|
||||
session.getPlayerInventoryHolder().updateSlot(heldItemSlot);
|
||||
GeyserItemStack itemStack = playerInventory.getItem(heldItemSlot);
|
||||
if (itemStack.getAmount() > 1) {
|
||||
if (itemStack.asItem() == Items.BUCKET || itemStack.asItem() == Items.GLASS_BOTTLE) {
|
||||
|
@ -614,7 +613,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
|||
slot = playerInventory.getOffsetForHotbar(slot);
|
||||
}
|
||||
if (playerInventory.getItem(slot).isEmpty()) {
|
||||
InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR.updateSlot(session, playerInventory, slot);
|
||||
session.getPlayerInventoryHolder().updateSlot(slot);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
package org.geysermc.geyser.translator.protocol.bedrock;
|
||||
|
||||
import org.cloudburstmc.protocol.bedrock.packet.ItemStackRequestPacket;
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.inventory.InventoryHolder;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
|
@ -39,10 +39,10 @@ public class BedrockItemStackRequestTranslator extends PacketTranslator<ItemStac
|
|||
|
||||
@Override
|
||||
public void translate(GeyserSession session, ItemStackRequestPacket packet) {
|
||||
Inventory<?> inventory = session.getOpenInventory();
|
||||
if (inventory == null)
|
||||
InventoryHolder<?> holder = session.getOpenInventory();
|
||||
if (holder == null)
|
||||
return;
|
||||
|
||||
inventory.getTranslator().translateRequests(session, inventory, packet.getRequests());
|
||||
holder.translateRequests(packet.getRequests());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
package org.geysermc.geyser.translator.protocol.bedrock;
|
||||
|
||||
import org.cloudburstmc.protocol.bedrock.packet.LecternUpdatePacket;
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.inventory.InventoryHolder;
|
||||
import org.geysermc.geyser.inventory.LecternContainer;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
|
@ -43,14 +43,15 @@ public class BedrockLecternUpdateTranslator extends PacketTranslator<LecternUpda
|
|||
@Override
|
||||
public void translate(GeyserSession session, LecternUpdatePacket packet) {
|
||||
// Bedrock wants to either move a page or exit
|
||||
if (!(session.getOpenInventory() instanceof LecternContainer lecternContainer)) {
|
||||
InventoryHolder<?> holder = session.getOpenInventory();
|
||||
if (holder == null || !(holder.inventory() instanceof LecternContainer lecternContainer)) {
|
||||
session.getGeyser().getLogger().debug("Expected lectern but it wasn't open!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (lecternContainer.getCurrentBedrockPage() == packet.getPage()) {
|
||||
// The same page means Bedrock is closing the window
|
||||
InventoryUtils.sendJavaContainerClose(session, lecternContainer);
|
||||
InventoryUtils.sendJavaContainerClose(holder);
|
||||
InventoryUtils.closeInventory(session, lecternContainer.getJavaId(), false);
|
||||
} else {
|
||||
// Each "page" Bedrock gives to us actually represents two pages (think opening a book and seeing two pages)
|
||||
|
@ -61,8 +62,7 @@ public class BedrockLecternUpdateTranslator extends PacketTranslator<LecternUpda
|
|||
// So, fun fact: We need to separately handle fake lecterns!
|
||||
// Since those are not actually a real lectern... the Java server won't respond to our requests.
|
||||
if (!lecternContainer.isUsingRealBlock()) {
|
||||
Inventory inventory = session.getOpenInventory();
|
||||
inventory.getTranslator().updateProperty(session, inventory, 0, newJavaPage);
|
||||
holder.updateProperty(0, newJavaPage);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ public class BedrockToggleCrafterSlotRequestTranslator extends PacketTranslator<
|
|||
|
||||
@Override
|
||||
public void translate(GeyserSession session, ToggleCrafterSlotRequestPacket packet) {
|
||||
if (!(session.getOpenInventory() instanceof CrafterContainer container)) {
|
||||
if (session.getOpenInventory() == null || !(session.getOpenInventory().inventory() instanceof CrafterContainer container)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,13 +25,13 @@
|
|||
|
||||
package org.geysermc.geyser.translator.protocol.bedrock.entity;
|
||||
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundSelectTradePacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket;
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.inventory.InventoryHolder;
|
||||
import org.geysermc.geyser.inventory.MerchantContainer;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundSelectTradePacket;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
@ -52,8 +52,8 @@ public class BedrockEntityEventTranslator extends PacketTranslator<EntityEventPa
|
|||
session.sendDownstreamGamePacket(selectTradePacket);
|
||||
|
||||
session.scheduleInEventLoop(() -> {
|
||||
Inventory openInventory = session.getOpenInventory();
|
||||
if (openInventory instanceof MerchantContainer merchantInventory) {
|
||||
InventoryHolder<?> openInventory = session.getOpenInventory();
|
||||
if (openInventory != null && openInventory.inventory() instanceof MerchantContainer merchantInventory) {
|
||||
merchantInventory.onTradeSelected(session, packet.getData());
|
||||
}
|
||||
}, 100, TimeUnit.MILLISECONDS);
|
||||
|
|
|
@ -128,7 +128,7 @@ public class BedrockInteractTranslator extends PacketTranslator<InteractPacket>
|
|||
ServerboundPlayerCommandPacket openVehicleWindowPacket = new ServerboundPlayerCommandPacket(session.getPlayerEntity().getEntityId(), PlayerState.OPEN_VEHICLE_INVENTORY);
|
||||
session.sendDownstreamGamePacket(openVehicleWindowPacket);
|
||||
} else {
|
||||
InventoryUtils.openInventory(session, session.getPlayerInventory());
|
||||
InventoryUtils.openInventory(session.getPlayerInventoryHolder());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ public class BedrockSetPlayerInventoryOptionsTranslator extends PacketTranslator
|
|||
|
||||
// This should ensure that we never send these packets when the player inventory is opened while in creative
|
||||
// Java edition can't craft in the 2x2 grid in creative, and subsequently doesn't have a recipe book
|
||||
if (session.getGameMode() == GameMode.CREATIVE && session.getPlayerInventory() == session.getOpenInventory()) {
|
||||
if (session.getGameMode() == GameMode.CREATIVE && session.getPlayerInventoryHolder() == session.getOpenInventory()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,6 @@ import org.geysermc.geyser.entity.type.living.monster.CreakingEntity;
|
|||
import org.geysermc.geyser.entity.type.living.monster.WardenEntity;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
import org.geysermc.geyser.util.InventoryUtils;
|
||||
|
@ -186,7 +185,7 @@ public class JavaEntityEventTranslator extends PacketTranslator<ClientboundEntit
|
|||
|
||||
if (totemItemWorkaround) {
|
||||
// Reset the item again
|
||||
InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR.updateSlot(session, session.getPlayerInventory(), 45);
|
||||
session.getPlayerInventoryHolder().updateSlot(45);
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
package org.geysermc.geyser.translator.protocol.java.inventory;
|
||||
|
||||
import org.geysermc.geyser.inventory.InventoryHolder;
|
||||
import org.geysermc.geyser.inventory.PlayerInventory;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
|
@ -39,7 +40,8 @@ public class JavaContainerCloseTranslator extends PacketTranslator<ClientboundCo
|
|||
public void translate(GeyserSession session, ClientboundContainerClosePacket packet) {
|
||||
// Sometimes the server can request a window close of ID 0... when the window isn't even open
|
||||
// Don't confirm in this instance
|
||||
session.setServerRequestedClosePlayerInventory(packet.getContainerId() == 0 && session.getOpenInventory() instanceof PlayerInventory);
|
||||
InventoryUtils.closeInventory(session, packet.getContainerId(), (session.getOpenInventory() != null && session.getOpenInventory().getJavaId() == packet.getContainerId()));
|
||||
InventoryHolder<?> holder = session.getOpenInventory();
|
||||
session.setServerRequestedClosePlayerInventory(packet.getContainerId() == 0 && holder != null && holder.inventory() instanceof PlayerInventory);
|
||||
InventoryUtils.closeInventory(session, packet.getContainerId(), (holder != null && holder.javaId() == packet.getContainerId()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,9 +28,8 @@ package org.geysermc.geyser.translator.protocol.java.inventory;
|
|||
import org.geysermc.geyser.GeyserLogger;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.inventory.InventoryHolder;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.geyser.translator.inventory.PlayerInventoryTranslator;
|
||||
import org.geysermc.geyser.translator.inventory.SmithingInventoryTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
|
@ -42,10 +41,12 @@ public class JavaContainerSetContentTranslator extends PacketTranslator<Clientbo
|
|||
|
||||
@Override
|
||||
public void translate(GeyserSession session, ClientboundContainerSetContentPacket packet) {
|
||||
Inventory<?> inventory = InventoryUtils.getInventory(session, packet.getContainerId());
|
||||
if (inventory == null)
|
||||
InventoryHolder<?> holder = InventoryUtils.getInventory(session, packet.getContainerId());
|
||||
if (holder == null)
|
||||
return;
|
||||
|
||||
Inventory inventory = holder.inventory();
|
||||
|
||||
int inventorySize = inventory.getSize();
|
||||
for (int i = 0; i < packet.getItems().length; i++) {
|
||||
if (i >= inventorySize) {
|
||||
|
@ -56,7 +57,7 @@ public class JavaContainerSetContentTranslator extends PacketTranslator<Clientbo
|
|||
logger.debug(packet);
|
||||
logger.debug(inventory);
|
||||
}
|
||||
updateInventory(session, inventory, packet.getContainerId());
|
||||
holder.updateInventory();
|
||||
// 1.18.1 behavior: the previous items will be correctly set, but the state ID and carried item will not
|
||||
// as this produces a stack trace on the client.
|
||||
// If Java processes this correctly in the future, we can revert this behavior
|
||||
|
@ -68,7 +69,7 @@ public class JavaContainerSetContentTranslator extends PacketTranslator<Clientbo
|
|||
inventory.setItem(i, newItem, session);
|
||||
}
|
||||
|
||||
updateInventory(session, inventory, packet.getContainerId());
|
||||
holder.updateInventory();
|
||||
|
||||
int stateId = packet.getStateId();
|
||||
session.setEmulatePost1_16Logic(stateId > 0 || stateId != inventory.getStateId());
|
||||
|
@ -79,25 +80,15 @@ public class JavaContainerSetContentTranslator extends PacketTranslator<Clientbo
|
|||
session.getPlayerInventory().setCursor(cursor, session);
|
||||
InventoryUtils.updateCursor(session);
|
||||
|
||||
if (InventoryUtils.getInventoryTranslator(session) instanceof SmithingInventoryTranslator) {
|
||||
if (holder.translator() instanceof SmithingInventoryTranslator) {
|
||||
// On 1.21.1, the recipe output is sometimes only updated here.
|
||||
// This can be replicated with shift-clicking the last item into the smithing table.
|
||||
// It seems that something in Via 5.1.1 causes 1.21.3 clients - even Java ones -
|
||||
// to make the server send a slot update.
|
||||
// That plus shift-clicking means that the state ID becomes outdated and forces
|
||||
// a complete inventory update.
|
||||
JavaContainerSetSlotTranslator.updateSmithingTableOutput(session, SmithingInventoryTranslator.OUTPUT,
|
||||
packet.getItems()[SmithingInventoryTranslator.OUTPUT], inventory);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateInventory(GeyserSession session, Inventory<?> inventory, int containerId) {
|
||||
InventoryTranslator<?> translator = InventoryUtils.getInventoryTranslator(session);
|
||||
if (containerId == 0 && !(translator instanceof PlayerInventoryTranslator)) {
|
||||
// In rare cases, the window ID can still be 0 but Java treats it as valid
|
||||
session.getPlayerInventory().updateInventory();
|
||||
} else {
|
||||
inventory.updateInventory();
|
||||
JavaContainerSetSlotTranslator.updateSmithingTableOutput(SmithingInventoryTranslator.OUTPUT,
|
||||
packet.getItems()[SmithingInventoryTranslator.OUTPUT], holder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
package org.geysermc.geyser.translator.protocol.java.inventory;
|
||||
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.inventory.InventoryHolder;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
|
@ -37,7 +37,7 @@ public class JavaContainerSetDataTranslator extends PacketTranslator<Clientbound
|
|||
|
||||
@Override
|
||||
public void translate(GeyserSession session, ClientboundContainerSetDataPacket packet) {
|
||||
Inventory inventory = InventoryUtils.getInventory(session, packet.getContainerId());
|
||||
InventoryHolder<?> inventory = InventoryUtils.getInventory(session, packet.getContainerId());
|
||||
if (inventory == null)
|
||||
return;
|
||||
|
||||
|
|
|
@ -34,15 +34,13 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.ItemDescripto
|
|||
import org.cloudburstmc.protocol.bedrock.packet.CraftingDataPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket;
|
||||
import org.geysermc.geyser.GeyserLogger;
|
||||
import org.geysermc.geyser.inventory.Container;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.inventory.InventoryHolder;
|
||||
import org.geysermc.geyser.inventory.recipe.GeyserShapedRecipe;
|
||||
import org.geysermc.geyser.inventory.recipe.GeyserSmithingRecipe;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.geyser.translator.inventory.PlayerInventoryTranslator;
|
||||
import org.geysermc.geyser.translator.inventory.SmithingInventoryTranslator;
|
||||
import org.geysermc.geyser.translator.item.ItemTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
|
@ -63,16 +61,18 @@ import java.util.concurrent.TimeUnit;
|
|||
@Translator(packet = ClientboundContainerSetSlotPacket.class)
|
||||
public class JavaContainerSetSlotTranslator extends PacketTranslator<ClientboundContainerSetSlotPacket> {
|
||||
|
||||
// TODO
|
||||
@Override
|
||||
public void translate(GeyserSession session, ClientboundContainerSetSlotPacket packet) {
|
||||
//TODO: support window id -2, should update player inventory
|
||||
//TODO: ^ I think this is outdated.
|
||||
Inventory<?> inventory = InventoryUtils.getInventory(session, packet.getContainerId());
|
||||
if (inventory == null) {
|
||||
InventoryHolder<?> holder = InventoryUtils.getInventory(session, packet.getContainerId());
|
||||
if (holder == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
InventoryTranslator<?> translator = InventoryUtils.getInventoryTranslator(session);
|
||||
Inventory inventory = holder.inventory();
|
||||
|
||||
int slot = packet.getSlot();
|
||||
if (slot >= inventory.getSize()) {
|
||||
GeyserLogger logger = session.getGeyser().getLogger();
|
||||
|
@ -86,23 +86,17 @@ public class JavaContainerSetSlotTranslator extends PacketTranslator<Clientbound
|
|||
return;
|
||||
}
|
||||
|
||||
if (translator instanceof SmithingInventoryTranslator) {
|
||||
updateSmithingTableOutput(session, slot, packet.getItem(), (Container<?>) inventory);
|
||||
if (holder.translator() instanceof SmithingInventoryTranslator) {
|
||||
updateSmithingTableOutput(slot, packet.getItem(), holder);
|
||||
} else {
|
||||
updateCraftingGrid(session, slot, packet.getItem(), inventory, translator);
|
||||
updateCraftingGrid(slot, packet.getItem(), holder);
|
||||
}
|
||||
|
||||
GeyserItemStack newItem = GeyserItemStack.from(packet.getItem());
|
||||
session.getBundleCache().initialize(newItem);
|
||||
if (packet.getContainerId() == 0 && !(translator instanceof PlayerInventoryTranslator)) {
|
||||
// In rare cases, the window ID can still be 0 but Java treats it as valid
|
||||
// This behavior still exists as of Java Edition 1.21.2, despite the new packet
|
||||
session.getPlayerInventory().setItem(slot, newItem, session);
|
||||
InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR.updateSlot(session, session.getPlayerInventory(), slot);
|
||||
} else {
|
||||
inventory.setItem(slot, newItem, session);
|
||||
translator.updateSlot(session, inventory, slot);
|
||||
}
|
||||
|
||||
holder.inventory().setItem(slot, newItem, session);
|
||||
holder.updateSlot(slot);
|
||||
|
||||
// Intentional behavior here below the cursor; Minecraft 1.18.1 also does this.
|
||||
int stateId = packet.getStateId();
|
||||
|
@ -113,18 +107,20 @@ public class JavaContainerSetSlotTranslator extends PacketTranslator<Clientbound
|
|||
/**
|
||||
* Checks for a changed output slot in the crafting grid, and ensures Bedrock sees the recipe.
|
||||
*/
|
||||
private static void updateCraftingGrid(GeyserSession session, int slot, ItemStack item, Inventory inventory, InventoryTranslator translator) {
|
||||
private static void updateCraftingGrid(int slot, ItemStack item, InventoryHolder<? extends Inventory> holder) {
|
||||
// Check if it's the crafting grid result slot.
|
||||
if (slot != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if there is any crafting grid.
|
||||
int gridSize = translator.getGridSize();
|
||||
int gridSize = holder.translator().getGridSize();
|
||||
if (gridSize == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
GeyserSession session = holder.session();
|
||||
|
||||
// Only process the most recent crafting grid result, and cancel the previous one.
|
||||
if (session.getContainerOutputFuture() != null) {
|
||||
session.getContainerOutputFuture().cancel(false);
|
||||
|
@ -141,7 +137,7 @@ public class JavaContainerSetSlotTranslator extends PacketTranslator<Clientbound
|
|||
int firstCol = -1, width = -1;
|
||||
for (int row = 0; row < gridDimensions; row++) {
|
||||
for (int col = 0; col < gridDimensions; col++) {
|
||||
if (!inventory.getItem(col + (row * gridDimensions) + 1).isEmpty()) {
|
||||
if (!holder.inventory().getItem(col + (row * gridDimensions) + 1).isEmpty()) {
|
||||
if (firstRow == -1) {
|
||||
firstRow = row;
|
||||
firstCol = col;
|
||||
|
@ -162,7 +158,7 @@ public class JavaContainerSetSlotTranslator extends PacketTranslator<Clientbound
|
|||
height += -firstRow + 1;
|
||||
width += -firstCol + 1;
|
||||
|
||||
if (InventoryUtils.getValidRecipe(session, item, inventory::getItem, gridDimensions, firstRow,
|
||||
if (InventoryUtils.getValidRecipe(session, item, holder.inventory()::getItem, gridDimensions, firstRow,
|
||||
height, firstCol, width) != null) {
|
||||
// Recipe is already present on the client; don't send packet
|
||||
return;
|
||||
|
@ -177,7 +173,7 @@ public class JavaContainerSetSlotTranslator extends PacketTranslator<Clientbound
|
|||
int index = 0;
|
||||
for (int row = firstRow; row < height + firstRow; row++) {
|
||||
for (int col = firstCol; col < width + firstCol; col++) {
|
||||
GeyserItemStack geyserItemStack = inventory.getItem(col + (row * gridDimensions) + 1);
|
||||
GeyserItemStack geyserItemStack = holder.inventory().getItem(col + (row * gridDimensions) + 1);
|
||||
ingredients[index] = geyserItemStack.getItemData(session);
|
||||
javaIngredients.add(geyserItemStack.asSlotDisplay());
|
||||
|
||||
|
@ -224,10 +220,11 @@ public class JavaContainerSetSlotTranslator extends PacketTranslator<Clientbound
|
|||
}, 150, TimeUnit.MILLISECONDS));
|
||||
}
|
||||
|
||||
static void updateSmithingTableOutput(GeyserSession session, int slot, ItemStack output, Container<?> inventory) {
|
||||
static void updateSmithingTableOutput(int slot, ItemStack output, InventoryHolder<?> holder) {
|
||||
if (slot != SmithingInventoryTranslator.OUTPUT) {
|
||||
return;
|
||||
}
|
||||
GeyserSession session = holder.session();
|
||||
|
||||
// Only process the most recent output result, and cancel the previous one.
|
||||
if (session.getContainerOutputFuture() != null) {
|
||||
|
@ -238,6 +235,7 @@ public class JavaContainerSetSlotTranslator extends PacketTranslator<Clientbound
|
|||
return;
|
||||
}
|
||||
|
||||
Inventory inventory = holder.inventory();
|
||||
session.setContainerOutputFuture(session.scheduleInEventLoop(() -> {
|
||||
GeyserItemStack template = inventory.getItem(SmithingInventoryTranslator.TEMPLATE);
|
||||
if (template.asItem() != Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE) {
|
||||
|
@ -284,11 +282,11 @@ public class JavaContainerSetSlotTranslator extends PacketTranslator<Clientbound
|
|||
// Just set one of the slots to air, then right back to its proper item.
|
||||
InventorySlotPacket slotPacket = new InventorySlotPacket();
|
||||
slotPacket.setContainerId(ContainerId.UI);
|
||||
slotPacket.setSlot(InventoryUtils.getInventoryTranslator(session).javaSlotToBedrock(SmithingInventoryTranslator.MATERIAL));
|
||||
slotPacket.setSlot(holder.translator().javaSlotToBedrock(SmithingInventoryTranslator.MATERIAL));
|
||||
slotPacket.setItem(ItemData.AIR);
|
||||
session.sendUpstreamPacket(slotPacket);
|
||||
|
||||
session.getOpenInventory().updateSlot(SmithingInventoryTranslator.MATERIAL);
|
||||
holder.updateSlot(SmithingInventoryTranslator.MATERIAL);
|
||||
}, 150, TimeUnit.MILLISECONDS));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.geysermc.geyser.entity.type.living.animal.horse.LlamaEntity;
|
|||
import org.geysermc.geyser.entity.type.living.animal.horse.SkeletonHorseEntity;
|
||||
import org.geysermc.geyser.entity.type.living.animal.horse.ZombieHorseEntity;
|
||||
import org.geysermc.geyser.inventory.Container;
|
||||
import org.geysermc.geyser.inventory.InventoryHolder;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.geyser.translator.inventory.horse.DonkeyInventoryTranslator;
|
||||
|
@ -119,7 +120,7 @@ public class JavaHorseScreenOpenTranslator extends PacketTranslator<ClientboundH
|
|||
// but everything is still indexed the same.
|
||||
int slotCount = 2; // Don't depend on slot count sent from server
|
||||
|
||||
InventoryTranslator inventoryTranslator;
|
||||
InventoryTranslator<Container> inventoryTranslator;
|
||||
if (entity instanceof LlamaEntity llamaEntity) {
|
||||
if (entity.getFlag(EntityFlag.CHESTED)) {
|
||||
slotCount += llamaEntity.getStrength() * 3;
|
||||
|
@ -153,6 +154,7 @@ public class JavaHorseScreenOpenTranslator extends PacketTranslator<ClientboundH
|
|||
updateEquipPacket.setTag(builder.build());
|
||||
session.sendUpstreamPacket(updateEquipPacket);
|
||||
|
||||
InventoryUtils.openInventory(session, new Container(session, entity.getNametag(), packet.getContainerId(), slotCount, null, session.getPlayerInventory(), inventoryTranslator));
|
||||
Container container = new Container(session, entity.getNametag(), packet.getContainerId(), slotCount, null);
|
||||
InventoryUtils.openInventory(new InventoryHolder<>(session, container, inventoryTranslator));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
package org.geysermc.geyser.translator.protocol.java.inventory;
|
||||
|
||||
import org.geysermc.geyser.inventory.InventoryHolder;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.inventory.VillagerTrade;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
||||
|
@ -56,13 +57,18 @@ public class JavaMerchantOffersTranslator extends PacketTranslator<ClientboundMe
|
|||
|
||||
@Override
|
||||
public void translate(GeyserSession session, ClientboundMerchantOffersPacket packet) {
|
||||
Inventory openInventory = session.getOpenInventory();
|
||||
if (!(openInventory instanceof MerchantContainer merchantInventory && openInventory.getJavaId() == packet.getContainerId())) {
|
||||
InventoryHolder<?> holder = session.getOpenInventory();
|
||||
if (holder == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Inventory inventory = holder.inventory();
|
||||
if (!(inventory instanceof MerchantContainer merchantInventory && inventory.getJavaId() == packet.getContainerId())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// No previous inventory was closed -> no need of queuing the merchant inventory
|
||||
if (!openInventory.isPending()) {
|
||||
if (!holder.pending()) {
|
||||
openMerchant(session, packet, merchantInventory);
|
||||
return;
|
||||
}
|
||||
|
@ -94,7 +100,7 @@ public class JavaMerchantOffersTranslator extends PacketTranslator<ClientboundMe
|
|||
updateTradePacket.setTradeTier(packet.getVillagerLevel() - 1);
|
||||
updateTradePacket.setContainerId((short) packet.getContainerId());
|
||||
updateTradePacket.setContainerType(ContainerType.TRADE);
|
||||
updateTradePacket.setDisplayName(session.getOpenInventory().getTitle());
|
||||
updateTradePacket.setDisplayName(merchantInventory.getTitle());
|
||||
updateTradePacket.setSize(0);
|
||||
updateTradePacket.setNewTradingUi(true);
|
||||
updateTradePacket.setUsingEconomyTrade(true);
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
package org.geysermc.geyser.translator.protocol.java.inventory;
|
||||
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.inventory.InventoryHolder;
|
||||
import org.geysermc.geyser.inventory.LecternContainer;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
@ -60,20 +60,21 @@ public class JavaOpenBookTranslator extends PacketTranslator<ClientboundOpenBook
|
|||
}
|
||||
|
||||
if (stack.asItem().equals(Items.WRITTEN_BOOK)) {
|
||||
Inventory openInventory = session.getOpenInventory();
|
||||
InventoryHolder<?> openInventory = session.getOpenInventory();
|
||||
if (openInventory != null) {
|
||||
InventoryUtils.closeInventory(session, openInventory.getJavaId(), true);
|
||||
InventoryUtils.sendJavaContainerClose(session, openInventory);
|
||||
InventoryUtils.closeInventory(session, openInventory.javaId(), true);
|
||||
InventoryUtils.sendJavaContainerClose(openInventory);
|
||||
}
|
||||
|
||||
InventoryTranslator translator = InventoryTranslator.inventoryTranslator(ContainerType.LECTERN);
|
||||
//noinspection unchecked
|
||||
InventoryTranslator<LecternContainer> translator = (InventoryTranslator<LecternContainer>) InventoryTranslator.inventoryTranslator(ContainerType.LECTERN);
|
||||
Objects.requireNonNull(translator, "could not find lectern inventory translator!");
|
||||
|
||||
// Should never be null
|
||||
Objects.requireNonNull(translator, "lectern translator must exist");
|
||||
Inventory inventory = translator.createInventory(session, "", FAKE_LECTERN_WINDOW_ID, ContainerType.LECTERN, session.getPlayerInventory());
|
||||
((LecternContainer) inventory).setFakeLecternBook(stack, session);
|
||||
InventoryUtils.openInventory(session, inventory);
|
||||
LecternContainer container = translator.createInventory(session, "", FAKE_LECTERN_WINDOW_ID, ContainerType.LECTERN);
|
||||
container.setFakeLecternBook(stack, session);
|
||||
InventoryUtils.openInventory(new InventoryHolder<>(session, container, translator));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ package org.geysermc.geyser.translator.protocol.java.inventory;
|
|||
import net.kyori.adventure.text.Component;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.inventory.InventoryHolder;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.geyser.translator.inventory.OldSmithingTableTranslator;
|
||||
|
@ -51,8 +52,8 @@ public class JavaOpenScreenTranslator extends PacketTranslator<ClientboundOpenSc
|
|||
return;
|
||||
}
|
||||
|
||||
InventoryTranslator newTranslator;
|
||||
Inventory openInventory = session.getOpenInventory();
|
||||
InventoryTranslator<? extends Inventory> newTranslator;
|
||||
InventoryHolder<? extends Inventory> currentInventory = session.getOpenInventory();
|
||||
|
||||
// Hack: ViaVersion translates the old (pre 1.20) smithing table to a anvil (does not work for Bedrock). We can detect this and translate it back to a smithing table.
|
||||
// (Implementation note: used to be a furnace. Was changed sometime before 1.21.2)
|
||||
|
@ -64,8 +65,8 @@ public class JavaOpenScreenTranslator extends PacketTranslator<ClientboundOpenSc
|
|||
|
||||
// No translator exists for this window type. Close all windows and return.
|
||||
if (newTranslator == null) {
|
||||
if (openInventory != null) {
|
||||
InventoryUtils.closeInventory(session, openInventory.getJavaId(), true);
|
||||
if (currentInventory != null) {
|
||||
InventoryUtils.closeInventory(session, currentInventory.javaId(), true);
|
||||
}
|
||||
|
||||
ServerboundContainerClosePacket closeWindowPacket = new ServerboundContainerClosePacket(packet.getContainerId());
|
||||
|
@ -75,35 +76,26 @@ public class JavaOpenScreenTranslator extends PacketTranslator<ClientboundOpenSc
|
|||
|
||||
String name = MessageTranslator.convertMessage(packet.getTitle(), session.locale());
|
||||
|
||||
Inventory newInventory = newTranslator.createInventory(session, name, packet.getContainerId(), packet.getType(), session.getPlayerInventory());
|
||||
if (openInventory != null) {
|
||||
var newInventory = newTranslator.createInventory(session, name, packet.getContainerId(), packet.getType());
|
||||
InventoryHolder<? extends Inventory> newInventoryHolder = new InventoryHolder<>(session, newInventory, newTranslator);
|
||||
if (currentInventory != null) {
|
||||
// Attempt to re-use existing open inventories, if possible.
|
||||
// Pending inventories are also considered, as a Java server can re-request the same inventory.
|
||||
if (newTranslator.canReuseInventory(session, newInventory, openInventory)) {
|
||||
// Use the same Bedrock id
|
||||
newInventory.setBedrockId(openInventory.getBedrockId());
|
||||
|
||||
// Also mirror other properties - in case we're e.g. dealing with a pending virtual inventory
|
||||
boolean pending = openInventory.isPending();
|
||||
newInventory.setDisplayed(openInventory.isDisplayed());
|
||||
newInventory.setPending(pending);
|
||||
newInventory.setHolderPosition(openInventory.getHolderPosition());
|
||||
newInventory.setHolderId(openInventory.getHolderId());
|
||||
session.setOpenInventory(newInventory);
|
||||
|
||||
GeyserImpl.getInstance().getLogger().debug(session, "Able to reuse current inventory. Is current pending? %s", pending);
|
||||
if (newTranslator.canReuseInventory(session, newInventory, currentInventory.inventory())) {
|
||||
newInventoryHolder.inheritFromExisting(currentInventory);
|
||||
GeyserImpl.getInstance().getLogger().debug(session, "Able to reuse current inventory. Is current pending? %s", currentInventory.pending());
|
||||
|
||||
// If the current inventory is still pending, it'll be updated once open
|
||||
if (newInventory.isDisplayed()) {
|
||||
newTranslator.updateInventory(session, newInventory);
|
||||
newInventoryHolder.updateInventory();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
InventoryUtils.closeInventory(session, openInventory.getJavaId(), true);
|
||||
InventoryUtils.closeInventory(session, currentInventory.javaId(), true);
|
||||
}
|
||||
|
||||
InventoryUtils.openInventory(session, newInventory);
|
||||
InventoryUtils.openInventory(newInventoryHolder);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ package org.geysermc.geyser.translator.protocol.java.inventory;
|
|||
import org.geysermc.geyser.GeyserLogger;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.inventory.ClientboundSetPlayerInventoryPacket;
|
||||
|
@ -58,6 +57,6 @@ public class JavaSetPlayerInventoryTranslator extends PacketTranslator<Clientbou
|
|||
GeyserItemStack newItem = GeyserItemStack.from(packet.getContents());
|
||||
session.getBundleCache().initialize(newItem);
|
||||
session.getPlayerInventory().setItem(slot, newItem, session);
|
||||
InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR.updateSlot(session, session.getPlayerInventory(), slot);
|
||||
session.getPlayerInventoryHolder().updateSlot(slot);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
package org.geysermc.geyser.util;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.math.vector.Vector3i;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
|
@ -39,6 +38,7 @@ import org.cloudburstmc.protocol.bedrock.packet.NetworkStackLatencyPacket;
|
|||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.inventory.InventoryHolder;
|
||||
import org.geysermc.geyser.inventory.LecternContainer;
|
||||
import org.geysermc.geyser.inventory.click.Click;
|
||||
import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
|
||||
|
@ -54,7 +54,6 @@ import org.geysermc.geyser.session.cache.registry.JavaRegistries;
|
|||
import org.geysermc.geyser.session.cache.tags.Tag;
|
||||
import org.geysermc.geyser.text.ChatColor;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.CompositeSlotDisplay;
|
||||
|
@ -94,20 +93,20 @@ public class InventoryUtils {
|
|||
* The main entrypoint to open an inventory. It will mark inventories as pending when the client isn't ready to
|
||||
* open the new inventory yet.
|
||||
*
|
||||
* @param session the geyser session
|
||||
* @param inventory the new inventory to open
|
||||
* @param holder the new inventory to open
|
||||
*/
|
||||
public static void openInventory(GeyserSession session, Inventory<?> inventory) {
|
||||
session.setOpenInventory(inventory);
|
||||
if (session.isClosingInventory() || !session.getUpstream().isInitialized() || session.getPendingOrCurrentBedrockInventoryId() != -1) {
|
||||
public static void openInventory(InventoryHolder<?> holder) {
|
||||
holder.markCurrent();
|
||||
if (holder.shouldSetPending()) {
|
||||
// Wait for close confirmation from client before opening the new inventory.
|
||||
// Handled in BedrockContainerCloseTranslator
|
||||
// or - client hasn't yet loaded in; wait until inventory is shown
|
||||
inventory.setPending(true);
|
||||
GeyserImpl.getInstance().getLogger().debug(session, "Inventory (%s) set pending: closing inv? %s, pending inv id? %s", debugInventory(inventory), session.isClosingInventory(), session.getPendingOrCurrentBedrockInventoryId());
|
||||
holder.pending(true);
|
||||
GeyserImpl.getInstance().getLogger().debug(holder.session(), "Inventory (%s) set pending: closing inv? %s, pending inv id? %s",
|
||||
debugInventory(holder), holder.session().isClosingInventory(), holder.session().getPendingOrCurrentBedrockInventoryId());
|
||||
return;
|
||||
}
|
||||
displayInventory(session, inventory);
|
||||
displayInventory(holder);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -116,71 +115,57 @@ public class InventoryUtils {
|
|||
* occurred in the time. For example, a queued virtual inventory might be "outdated", so we wouldn't open it.
|
||||
*/
|
||||
public static void openPendingInventory(GeyserSession session) {
|
||||
Inventory<?> currentInventory = session.getOpenInventory();
|
||||
if (currentInventory == null || !currentInventory.isPending()) {
|
||||
InventoryHolder<?> holder = session.getOpenInventory();
|
||||
if (holder == null || !holder.pending()) {
|
||||
session.setPendingOrCurrentBedrockInventoryId(-1);
|
||||
GeyserImpl.getInstance().getLogger().debug(session, "No pending inventory, not opening an inventory! Current inventory: %s", debugInventory(currentInventory));
|
||||
GeyserImpl.getInstance().getLogger().debug(session, "No pending inventory, not opening an inventory! Current inventory: %s", debugInventory(holder));
|
||||
return;
|
||||
}
|
||||
|
||||
// Current inventory isn't null! Let's see if we need to open it.
|
||||
if (currentInventory.getBedrockId() == session.getPendingOrCurrentBedrockInventoryId()) {
|
||||
GeyserImpl.getInstance().getLogger().debug(session, "Attempting to open currently delayed inventory with matching bedrock id! " + currentInventory.getBedrockId());
|
||||
openAndUpdateInventory(session, currentInventory);
|
||||
if (holder.inventory().getBedrockId() == session.getPendingOrCurrentBedrockInventoryId()) {
|
||||
GeyserImpl.getInstance().getLogger().debug(session, "Attempting to open currently delayed inventory with matching bedrock id! " + holder.bedrockId());
|
||||
openAndUpdateInventory(holder);
|
||||
return;
|
||||
}
|
||||
|
||||
GeyserImpl.getInstance().getLogger().debug(session, "Opening any pending inventory! " + debugInventory(currentInventory));
|
||||
displayInventory(session, currentInventory);
|
||||
GeyserImpl.getInstance().getLogger().debug(session, "Opening any pending inventory! " + debugInventory(holder));
|
||||
displayInventory(holder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares and displays the current inventory. If necessary, it will queue the opening of virtual inventories.
|
||||
* @param inventory the inventory to display
|
||||
* @param holder the inventory to display
|
||||
*/
|
||||
public static void displayInventory(GeyserSession session, Inventory<?> inventory) {
|
||||
InventoryTranslator<?> translator = inventory.getTranslator();
|
||||
if (inventory.prepareInventory()) {
|
||||
session.setPendingOrCurrentBedrockInventoryId(inventory.getBedrockId());
|
||||
if (inventory.requiresOpeningDelay()) {
|
||||
inventory.setPending(true);
|
||||
public static void displayInventory(InventoryHolder<?> holder) {
|
||||
if (holder.prepareInventory()) {
|
||||
holder.session().setPendingOrCurrentBedrockInventoryId(holder.bedrockId());
|
||||
if (holder.requiresOpeningDelay()) {
|
||||
holder.pending(true);
|
||||
|
||||
NetworkStackLatencyPacket latencyPacket = new NetworkStackLatencyPacket();
|
||||
latencyPacket.setFromServer(true);
|
||||
latencyPacket.setTimestamp(MAGIC_VIRTUAL_INVENTORY_HACK);
|
||||
session.sendUpstreamPacket(latencyPacket);
|
||||
holder.session().sendUpstreamPacket(latencyPacket);
|
||||
|
||||
GeyserImpl.getInstance().getLogger().debug(session, "Queuing virtual inventory (%s)", debugInventory(inventory));
|
||||
GeyserImpl.getInstance().getLogger().debug(holder.session(), "Queuing virtual inventory (%s)", debugInventory(holder));
|
||||
} else {
|
||||
openAndUpdateInventory(session, inventory);
|
||||
openAndUpdateInventory(holder);
|
||||
}
|
||||
} else {
|
||||
// Can occur if we e.g. did not find a spot to put a fake container in
|
||||
session.setPendingOrCurrentBedrockInventoryId(-1);
|
||||
sendJavaContainerClose(session, inventory);
|
||||
session.setOpenInventory(null);
|
||||
holder.session().setPendingOrCurrentBedrockInventoryId(-1);
|
||||
sendJavaContainerClose(holder);
|
||||
holder.session().setOpenInventory(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens and updates an inventory, and resets no longer used inventory variables.
|
||||
* Opens and updates an inventory
|
||||
*/
|
||||
public static void openAndUpdateInventory(GeyserSession session, Inventory<?> inventory) {
|
||||
inventory.openInventory();
|
||||
inventory.updateInventory();
|
||||
inventory.setDisplayed(true);
|
||||
inventory.setPending(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current inventory translator.
|
||||
*/
|
||||
public static @NonNull InventoryTranslator<?> getInventoryTranslator(GeyserSession session) {
|
||||
Inventory<?> inventory = session.getOpenInventory();
|
||||
if (inventory == null) {
|
||||
return InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR;
|
||||
}
|
||||
return inventory.getTranslator();
|
||||
public static void openAndUpdateInventory(InventoryHolder<?> holder) {
|
||||
holder.openInventory();
|
||||
holder.updateInventory();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -193,41 +178,43 @@ public class InventoryUtils {
|
|||
session.getPlayerInventory().setCursor(GeyserItemStack.EMPTY, session);
|
||||
updateCursor(session);
|
||||
|
||||
Inventory<?> inventory = getInventory(session, javaId);
|
||||
if (inventory != null) {
|
||||
inventory.closeInventory();
|
||||
if (confirm && inventory.isDisplayed() && !inventory.isPending()
|
||||
&& !(inventory instanceof LecternContainer) // Closing lecterns is not followed with a close confirmation
|
||||
) {
|
||||
InventoryHolder<?> holder = getInventory(session, javaId);
|
||||
if (holder != null) {
|
||||
holder.closeInventory();
|
||||
if (holder.shouldConfirmClose(confirm)) {
|
||||
session.setClosingInventory(true);
|
||||
}
|
||||
session.getBundleCache().onInventoryClose(inventory);
|
||||
GeyserImpl.getInstance().getLogger().debug(session, "Closed inventory: (java id: %s/bedrock id: %s), waiting on confirm? %s", inventory.getJavaId(), inventory.getBedrockId(), session.isClosingInventory());
|
||||
session.getBundleCache().onInventoryClose(holder.inventory());
|
||||
GeyserImpl.getInstance().getLogger().debug(session, "Closed inventory: (java id: %s/bedrock id: %s), waiting on confirm? %s", holder.javaId(), holder.bedrockId(), session.isClosingInventory());
|
||||
}
|
||||
|
||||
session.setOpenInventory(null);
|
||||
}
|
||||
|
||||
public static @Nullable Inventory<?> getInventory(GeyserSession session, int javaId) {
|
||||
/**
|
||||
* A util method to get the an inventory based on a Java id. This is used over
|
||||
* {@link GeyserSession#getOpenInventory()} when needing to account for player inventories instead of just the open inventory.
|
||||
*/
|
||||
public static @Nullable InventoryHolder<?> getInventory(GeyserSession session, int javaId) {
|
||||
InventoryHolder<?> holder = session.getOpenInventory();
|
||||
if (javaId == 0) {
|
||||
// ugly hack: lecterns aren't their own inventory on Java, and can hence be closed with e.g. an id of 0
|
||||
if (session.getOpenInventory() instanceof LecternContainer) {
|
||||
if (holder != null && holder.inventory() instanceof LecternContainer) {
|
||||
return session.getOpenInventory();
|
||||
}
|
||||
return session.getPlayerInventory();
|
||||
return session.getPlayerInventoryHolder();
|
||||
} else {
|
||||
Inventory<?> openInventory = session.getOpenInventory();
|
||||
if (openInventory != null && javaId == openInventory.getJavaId()) {
|
||||
return openInventory;
|
||||
if (holder != null && javaId == holder.javaId()) {
|
||||
return holder;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendJavaContainerClose(GeyserSession session, Inventory<?> inventory) {
|
||||
if (inventory.shouldConfirmContainerClose()) {
|
||||
ServerboundContainerClosePacket closeWindowPacket = new ServerboundContainerClosePacket(inventory.getJavaId());
|
||||
session.sendDownstreamGamePacket(closeWindowPacket);
|
||||
public static void sendJavaContainerClose(InventoryHolder<? extends Inventory> holder) {
|
||||
if (holder.inventory().shouldConfirmContainerClose()) {
|
||||
ServerboundContainerClosePacket closeWindowPacket = new ServerboundContainerClosePacket(holder.inventory().getJavaId());
|
||||
holder.session().sendDownstreamGamePacket(closeWindowPacket);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -486,17 +473,18 @@ public class InventoryUtils {
|
|||
return true;
|
||||
}
|
||||
|
||||
public static String debugInventory(@Nullable Inventory<?> inventory) {
|
||||
if (inventory == null) {
|
||||
public static String debugInventory(@Nullable InventoryHolder<? extends Inventory> holder) {
|
||||
if (holder == null) {
|
||||
return "null";
|
||||
}
|
||||
Inventory inventory = holder.inventory();
|
||||
|
||||
String inventoryType = inventory.getContainerType() != null ?
|
||||
inventory.getContainerType().name() : "null";
|
||||
|
||||
return inventory.getClass().getSimpleName() + ": javaId=" + inventory.getJavaId() +
|
||||
", bedrockId=" + inventory.getBedrockId() + ", size=" + inventory.getSize() +
|
||||
", type=" + inventoryType + ", pending=" + inventory.isPending() +
|
||||
", displayed=" + inventory.isPending() + ", delayed=" + inventory.isPending();
|
||||
", type=" + inventoryType + ", pending=" + holder.pending() +
|
||||
", displayed=" + inventory.isDisplayed();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ public class LoginEncryptionUtils {
|
|||
}
|
||||
|
||||
IdentityData extraData = result.identityClaims().extraData;
|
||||
session.setAuthenticationData(new AuthData(extraData.displayName, extraData.identity, extraData.xuid));
|
||||
session.setAuthData(new AuthData(extraData.displayName, extraData.identity, extraData.xuid));
|
||||
session.setCertChainData(certChainData);
|
||||
|
||||
PublicKey identityPublicKey = result.identityClaims().parsedIdentityPublicKey();
|
||||
|
|
Loading…
Add table
Reference in a new issue