3
0
Mirror von https://github.com/GeyserMC/Geyser.git synchronisiert 2024-11-03 14:50:19 +01:00

Start work on using the world block for inventories

Dieser Commit ist enthalten in:
Camotoy 2021-01-30 16:05:27 -05:00
Ursprung 4a8d93752b
Commit 454896a7ad
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 7EEFB66FE798081F
15 geänderte Dateien mit 195 neuen und 42 gelöschten Zeilen

Datei anzeigen

@ -27,6 +27,7 @@ package org.geysermc.connector.inventory;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
import lombok.Setter;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.inventory.InventoryTranslator; import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
@ -38,6 +39,12 @@ public class Container extends Inventory {
private final PlayerInventory playerInventory; private final PlayerInventory playerInventory;
private final int containerSize; private final int containerSize;
/**
* Whether we are using a real block when opening this inventory.
*/
@Setter
private boolean isUsingRealBlock = false;
public Container(String title, int id, int size, PlayerInventory playerInventory) { public Container(String title, int id, int size, PlayerInventory playerInventory) {
super(title, id, size); super(title, id, size);
this.playerInventory = playerInventory; this.playerInventory = playerInventory;

Datei anzeigen

@ -0,0 +1,41 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.connector.inventory;
import lombok.Getter;
import lombok.Setter;
public class Generic3X3Container extends Container {
/**
* Whether we need to set the container type as {@link com.nukkitx.protocol.bedrock.data.inventory.ContainerType#DROPPER}
*/
@Getter @Setter
private boolean isDropper = false;
public Generic3X3Container(String title, int id, int size, PlayerInventory playerInventory) {
super(title, id, size, playerInventory);
}
}

Datei anzeigen

@ -38,7 +38,6 @@ import com.github.steveice10.mc.protocol.data.SubProtocol;
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
import com.github.steveice10.mc.protocol.data.game.recipe.Recipe; import com.github.steveice10.mc.protocol.data.game.recipe.Recipe;
import com.github.steveice10.mc.protocol.data.game.statistic.Statistic; import com.github.steveice10.mc.protocol.data.game.statistic.Statistic;
import com.github.steveice10.mc.protocol.data.game.window.VillagerTrade;
import com.github.steveice10.mc.protocol.packet.handshake.client.HandshakePacket; import com.github.steveice10.mc.protocol.packet.handshake.client.HandshakePacket;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPositionPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPositionPacket;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPositionRotationPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPositionRotationPacket;
@ -73,10 +72,10 @@ import lombok.Setter;
import org.geysermc.common.window.CustomFormWindow; import org.geysermc.common.window.CustomFormWindow;
import org.geysermc.common.window.FormWindow; import org.geysermc.common.window.FormWindow;
import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.entity.Tickable;
import org.geysermc.connector.command.CommandSender; import org.geysermc.connector.command.CommandSender;
import org.geysermc.connector.common.AuthType; import org.geysermc.connector.common.AuthType;
import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.entity.Tickable;
import org.geysermc.connector.entity.player.SessionPlayerEntity; import org.geysermc.connector.entity.player.SessionPlayerEntity;
import org.geysermc.connector.entity.player.SkullPlayerEntity; import org.geysermc.connector.entity.player.SkullPlayerEntity;
import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.inventory.Inventory;
@ -231,7 +230,15 @@ public class GeyserSession implements CommandSender {
* Initialized as (0, 0, 0) so it is always not-null. * Initialized as (0, 0, 0) so it is always not-null.
*/ */
@Setter @Setter
private Vector3i lastInteractionPosition = Vector3i.ZERO; private Vector3i lastInteractionBlockPosition = Vector3i.ZERO;
/**
* Stores the position of the player the last time they interacted.
* Used to verify that the player did not move since their last interaction. <br>
* Initialized as (0, 0, 0) so it is always not-null.
*/
@Setter
private Vector3f lastInteractionPlayerPosition = Vector3f.ZERO;
@Setter @Setter
private Entity ridingVehicleEntity; private Entity ridingVehicleEntity;
@ -239,15 +246,13 @@ public class GeyserSession implements CommandSender {
@Setter @Setter
private long lastWindowCloseTime = 0; private long lastWindowCloseTime = 0;
@Setter
private VillagerTrade[] villagerTrades;
@Setter @Setter
private long lastInteractedVillagerEid; private long lastInteractedVillagerEid;
@Setter @Setter
private Int2ObjectMap<Recipe> craftingRecipes; private Int2ObjectMap<Recipe> craftingRecipes;
private final Set<String> unlockedRecipes; private final Set<String> unlockedRecipes;
private AtomicInteger lastRecipeNetId; private final AtomicInteger lastRecipeNetId;
/** /**
* Saves a list of all stonecutter recipes, for use in a stonecutter inventory. * Saves a list of all stonecutter recipes, for use in a stonecutter inventory.

Datei anzeigen

@ -117,8 +117,9 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
// Check to make sure the client isn't spamming interaction // Check to make sure the client isn't spamming interaction
// Based on Nukkit 1.0, with changes to ensure holding down still works // Based on Nukkit 1.0, with changes to ensure holding down still works
boolean hasAlreadyClicked = System.currentTimeMillis() - session.getLastInteractionTime() < 110.0 && boolean hasAlreadyClicked = System.currentTimeMillis() - session.getLastInteractionTime() < 110.0 &&
packet.getBlockPosition().distanceSquared(session.getLastInteractionPosition()) < 0.00001; packet.getBlockPosition().distanceSquared(session.getLastInteractionBlockPosition()) < 0.00001;
session.setLastInteractionPosition(packet.getBlockPosition()); session.setLastInteractionBlockPosition(packet.getBlockPosition());
session.setLastInteractionPlayerPosition(session.getPlayerEntity().getPosition());
if (hasAlreadyClicked) { if (hasAlreadyClicked) {
break; break;
} else { } else {

Datei anzeigen

@ -38,12 +38,14 @@ import org.geysermc.connector.network.translators.PacketTranslator;
import org.geysermc.connector.network.translators.Translator; import org.geysermc.connector.network.translators.Translator;
import org.geysermc.connector.utils.InventoryUtils; import org.geysermc.connector.utils.InventoryUtils;
/**
* Used to translate moving pages, or closing the inventory
*/
@Translator(packet = LecternUpdatePacket.class) @Translator(packet = LecternUpdatePacket.class)
public class BedrockLecternUpdateTranslator extends PacketTranslator<LecternUpdatePacket> { public class BedrockLecternUpdateTranslator extends PacketTranslator<LecternUpdatePacket> {
@Override @Override
public void translate(LecternUpdatePacket packet, GeyserSession session) { public void translate(LecternUpdatePacket packet, GeyserSession session) {
session.getConnector().getLogger().error(packet.toString());
if (packet.isDroppingBook()) { if (packet.isDroppingBook()) {
// Bedrock drops the book outside of the GUI. Java drops it in the GUI // Bedrock drops the book outside of the GUI. Java drops it in the GUI
// So, we enter the GUI and then drop it! :) // So, we enter the GUI and then drop it! :)

Datei anzeigen

@ -33,7 +33,6 @@ import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapedRecipeData;
import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapelessRecipeData; import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapelessRecipeData;
import com.github.steveice10.mc.protocol.data.game.window.WindowType; import com.github.steveice10.mc.protocol.data.game.window.WindowType;
import com.nukkitx.protocol.bedrock.data.inventory.ContainerSlotType; import com.nukkitx.protocol.bedrock.data.inventory.ContainerSlotType;
import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
import com.nukkitx.protocol.bedrock.data.inventory.StackRequestSlotInfoData; import com.nukkitx.protocol.bedrock.data.inventory.StackRequestSlotInfoData;
import com.nukkitx.protocol.bedrock.data.inventory.stackrequestactions.*; import com.nukkitx.protocol.bedrock.data.inventory.stackrequestactions.*;
import com.nukkitx.protocol.bedrock.packet.ItemStackRequestPacket; import com.nukkitx.protocol.bedrock.packet.ItemStackRequestPacket;
@ -94,8 +93,8 @@ public abstract class InventoryTranslator {
put(WindowType.STONECUTTER, new StonecutterInventoryTranslator()); put(WindowType.STONECUTTER, new StonecutterInventoryTranslator());
/* Generics */ /* Generics */
put(WindowType.GENERIC_3X3, new GenericBlockInventoryTranslator(9, "minecraft:dispenser[facing=north,triggered=false]", ContainerType.DISPENSER)); put(WindowType.GENERIC_3X3, new Generic3X3InventoryTranslator());
put(WindowType.HOPPER, new GenericBlockInventoryTranslator(5, "minecraft:hopper[enabled=false,facing=down]", ContainerType.HOPPER)); put(WindowType.HOPPER, new HopperInventoryTranslator());
/* Lectern */ /* Lectern */
put(WindowType.LECTERN, new LecternInventoryTranslator()); put(WindowType.LECTERN, new LecternInventoryTranslator());

Datei anzeigen

@ -26,39 +26,70 @@
package org.geysermc.connector.network.translators.inventory.holder; package org.geysermc.connector.network.translators.inventory.holder;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
import com.google.common.collect.Sets;
import com.nukkitx.math.vector.Vector3i; import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.nbt.NbtMap; import com.nukkitx.nbt.NbtMap;
import com.nukkitx.protocol.bedrock.data.inventory.ContainerType; import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket;
import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket; import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket;
import lombok.AllArgsConstructor; import org.geysermc.connector.inventory.Container;
import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.inventory.Inventory;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.inventory.InventoryTranslator; import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
import org.geysermc.connector.network.translators.world.block.BlockTranslator; import org.geysermc.connector.network.translators.world.block.BlockTranslator;
import java.util.Collections;
import java.util.Set;
/** /**
* Manages the fake block we implement for each inventory. * Manages the fake block we implement for each inventory, should we need to.
* This class will attempt to use a real block first, if possible.
*/ */
@AllArgsConstructor
public class BlockInventoryHolder extends InventoryHolder { public class BlockInventoryHolder extends InventoryHolder {
private final int blockId; /**
* The default Bedrock block ID to use as a fake block
*/
private final int defaultBedrockBlockId;
private final ContainerType containerType; private final ContainerType containerType;
private final Set<String> validBlocks;
public BlockInventoryHolder(String javaBlockIdentifier, ContainerType containerType, String... validBlocks) {
int javaBlockState = BlockTranslator.getJavaBlockState(javaBlockIdentifier);
this.defaultBedrockBlockId = BlockTranslator.getBedrockBlockId(javaBlockState);
this.containerType = containerType;
if (validBlocks != null) {
this.validBlocks = Sets.newHashSet(validBlocks);
this.validBlocks.add(javaBlockIdentifier.split("\\[")[0]);
} else {
this.validBlocks = Collections.singleton(javaBlockIdentifier.split("\\[")[0]);
}
}
@Override @Override
public void prepareInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) { public void prepareInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) {
//TODO: Improve on this (for example, multiple block states). We need this for the beacon. // Check to see if there is an existing block we can use that the player just selected.
if (BlockTranslator.getBedrockBlockId(session.getConnector().getWorldManager().getBlockAt(session, session.getLastInteractionPosition())) == blockId) { // First, verify that the player's position has not changed, so we don't try to select a block wildly out of range.
inventory.setHolderPosition(session.getLastInteractionPosition()); // (This could be a virtual inventory that the player is opening)
if (session.getLastInteractionPlayerPosition().equals(session.getPlayerEntity().getPosition())) {
// Then, check to see if the interacted block is valid for this inventory by ensuring the block state identifier is valid
int javaBlockId = session.getConnector().getWorldManager().getBlockAt(session, session.getLastInteractionBlockPosition());
String javaBlockString = BlockTranslator.getJavaIdBlockMap().inverse().getOrDefault(javaBlockId, "minecraft:air").split("\\[")[0];
if (this.validBlocks.contains(javaBlockString)) {
// We can safely use this block
inventory.setHolderPosition(session.getLastInteractionBlockPosition());
((Container) inventory).setUsingRealBlock(true);
return; return;
} }
}
// Otherwise, time to conjure up a fake block!
Vector3i position = session.getPlayerEntity().getPosition().toInt(); Vector3i position = session.getPlayerEntity().getPosition().toInt();
position = position.add(Vector3i.UP); position = position.add(Vector3i.UP);
UpdateBlockPacket blockPacket = new UpdateBlockPacket(); UpdateBlockPacket blockPacket = new UpdateBlockPacket();
blockPacket.setDataLayer(0); blockPacket.setDataLayer(0);
blockPacket.setBlockPosition(position); blockPacket.setBlockPosition(position);
blockPacket.setRuntimeId(blockId); blockPacket.setRuntimeId(defaultBedrockBlockId);
blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY); blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
session.sendUpstreamPacket(blockPacket); session.sendUpstreamPacket(blockPacket);
inventory.setHolderPosition(position); inventory.setHolderPosition(position);
@ -86,10 +117,12 @@ public class BlockInventoryHolder extends InventoryHolder {
@Override @Override
public void closeInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) { public void closeInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) {
Vector3i holderPos = inventory.getHolderPosition(); if (((Container) inventory).isUsingRealBlock()) {
if (holderPos.equals(session.getLastInteractionPosition())) { // No need to reset a block since we didn't change any blocks
return; return;
} }
Vector3i holderPos = inventory.getHolderPosition();
Position pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ()); Position pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ());
int realBlock = session.getConnector().getWorldManager().getBlockAt(session, pos.getX(), pos.getY(), pos.getZ()); int realBlock = session.getConnector().getWorldManager().getBlockAt(session, pos.getX(), pos.getY(), pos.getZ());
UpdateBlockPacket blockPacket = new UpdateBlockPacket(); UpdateBlockPacket blockPacket = new UpdateBlockPacket();

Datei anzeigen

@ -31,7 +31,6 @@ import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.inventory.holder.BlockInventoryHolder; import org.geysermc.connector.network.translators.inventory.holder.BlockInventoryHolder;
import org.geysermc.connector.network.translators.inventory.holder.InventoryHolder; import org.geysermc.connector.network.translators.inventory.holder.InventoryHolder;
import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater; import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater;
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
/** /**
* Provided as a base for any inventory that requires a block for opening it * Provided as a base for any inventory that requires a block for opening it
@ -45,11 +44,12 @@ public abstract class AbstractBlockInventoryTranslator extends BaseInventoryTran
* @param javaBlockIdentifier a Java block identifier that is used as a temporary block * @param javaBlockIdentifier a Java block identifier that is used as a temporary block
* @param containerType the container type of this inventory * @param containerType the container type of this inventory
* @param updater updater * @param updater updater
* @param additionalValidBlocks any other block identifiers that can safely use this inventory without a fake block
*/ */
public AbstractBlockInventoryTranslator(int size, String javaBlockIdentifier, ContainerType containerType, InventoryUpdater updater) { public AbstractBlockInventoryTranslator(int size, String javaBlockIdentifier, ContainerType containerType, InventoryUpdater updater,
String... additionalValidBlocks) {
super(size); super(size);
int javaBlockState = BlockTranslator.getJavaBlockState(javaBlockIdentifier); this.holder = new BlockInventoryHolder(javaBlockIdentifier, containerType, additionalValidBlocks);
this.holder = new BlockInventoryHolder(BlockTranslator.getBedrockBlockId(javaBlockState), containerType);
this.updater = updater; this.updater = updater;
} }

Datei anzeigen

@ -48,7 +48,8 @@ import org.geysermc.connector.network.translators.item.ItemTranslator;
public class AnvilInventoryTranslator extends AbstractBlockInventoryTranslator { public class AnvilInventoryTranslator extends AbstractBlockInventoryTranslator {
public AnvilInventoryTranslator() { public AnvilInventoryTranslator() {
super(3, "minecraft:anvil[facing=north]", ContainerType.ANVIL, UIInventoryUpdater.INSTANCE); super(3, "minecraft:anvil[facing=north]", ContainerType.ANVIL, UIInventoryUpdater.INSTANCE,
"minecraft:chipped_anvil", "minecraft:damaged_anvil");
} }
/* 1.16.100 support start */ /* 1.16.100 support start */

Datei anzeigen

@ -0,0 +1,48 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.connector.network.translators.inventory.translators;
import com.github.steveice10.mc.protocol.data.game.window.WindowType;
import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
import org.geysermc.connector.inventory.Generic3X3Container;
import org.geysermc.connector.inventory.Inventory;
import org.geysermc.connector.inventory.PlayerInventory;
import org.geysermc.connector.network.translators.inventory.updater.UIInventoryUpdater;
/**
* Droppers and dispensers
*/
public class Generic3X3InventoryTranslator extends AbstractBlockInventoryTranslator {
//TODO allow droppers to use their own block - this requires changing the ContainerType to DROPPER
public Generic3X3InventoryTranslator() {
super(9, "minecraft:dispenser[facing=north,triggered=false]", ContainerType.DISPENSER, UIInventoryUpdater.INSTANCE);
}
@Override
public Inventory createInventory(String name, int windowId, WindowType windowType, PlayerInventory playerInventory) {
return new Generic3X3Container(name, windowId, this.size, playerInventory);
}
}

Datei anzeigen

@ -28,14 +28,14 @@ package org.geysermc.connector.network.translators.inventory.translators;
import com.nukkitx.protocol.bedrock.data.inventory.ContainerSlotType; import com.nukkitx.protocol.bedrock.data.inventory.ContainerSlotType;
import com.nukkitx.protocol.bedrock.data.inventory.ContainerType; import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
import org.geysermc.connector.network.translators.inventory.BedrockContainerSlot; import org.geysermc.connector.network.translators.inventory.BedrockContainerSlot;
import org.geysermc.connector.network.translators.inventory.updater.ContainerInventoryUpdater; import org.geysermc.connector.network.translators.inventory.updater.UIInventoryUpdater;
/** /**
* Implemented on top of any block that does not have special properties implemented * Implemented on top of any block that does not have special properties implemented
*/ */
public class GenericBlockInventoryTranslator extends AbstractBlockInventoryTranslator { public class HopperInventoryTranslator extends AbstractBlockInventoryTranslator {
public GenericBlockInventoryTranslator(int size, String javaBlockIdentifier, ContainerType containerType) { public HopperInventoryTranslator() {
super(size, javaBlockIdentifier, containerType, ContainerInventoryUpdater.INSTANCE); super(5, "minecraft:hopper[enabled=false,facing=down]", ContainerType.HOPPER, UIInventoryUpdater.INSTANCE);
} }
@Override @Override

Datei anzeigen

@ -98,7 +98,7 @@ public class LecternInventoryTranslator extends BaseInventoryTranslator {
CompoundTag tag = geyserItemStack.getNbt(); CompoundTag tag = geyserItemStack.getNbt();
if (tag != null) { if (tag != null) {
// Position has to be the last interacted position... right? // Position has to be the last interacted position... right?
Vector3i position = session.getLastInteractionPosition(); Vector3i position = session.getLastInteractionBlockPosition();
// shouldRefresh means that we should boot out the client on our side because their lectern GUI isn't updated yet // shouldRefresh means that we should boot out the client on our side because their lectern GUI isn't updated yet
boolean shouldRefresh = !session.getConnector().getWorldManager().shouldExpectLecternHandled() && !session.getLecternCache().contains(position); boolean shouldRefresh = !session.getConnector().getWorldManager().shouldExpectLecternHandled() && !session.getLecternCache().contains(position);
int pagesSize = ((ListTag) tag.get("pages")).size(); int pagesSize = ((ListTag) tag.get("pages")).size();
@ -124,7 +124,6 @@ public class LecternInventoryTranslator extends BaseInventoryTranslator {
ClientCloseWindowPacket closeWindowPacket = new ClientCloseWindowPacket(lecternContainer.getId()); ClientCloseWindowPacket closeWindowPacket = new ClientCloseWindowPacket(lecternContainer.getId());
session.sendDownstreamPacket(closeWindowPacket); session.sendDownstreamPacket(closeWindowPacket);
InventoryUtils.closeInventory(session, inventory.getId()); InventoryUtils.closeInventory(session, inventory.getId());
session.getConnector().getLogger().warning("Closing inventory");
} }
} }
} }

Datei anzeigen

@ -32,28 +32,41 @@ import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket;
import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket; import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket;
import org.geysermc.connector.inventory.Container;
import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.inventory.Inventory;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.world.block.BlockTranslator; import org.geysermc.connector.network.translators.world.block.BlockTranslator;
public class DoubleChestInventoryTranslator extends ChestInventoryTranslator { public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
private final int blockId; private final int defaultBedrockBlockId;
public DoubleChestInventoryTranslator(int size) { public DoubleChestInventoryTranslator(int size) {
super(size, 54); super(size, 54);
int javaBlockState = BlockTranslator.getJavaBlockState("minecraft:chest[facing=north,type=single,waterlogged=false]"); int javaBlockState = BlockTranslator.getJavaBlockState("minecraft:chest[facing=north,type=single,waterlogged=false]");
this.blockId = BlockTranslator.getBedrockBlockId(javaBlockState); this.defaultBedrockBlockId = BlockTranslator.getBedrockBlockId(javaBlockState);
} }
@Override @Override
public void prepareInventory(GeyserSession session, Inventory inventory) { public void prepareInventory(GeyserSession session, Inventory inventory) {
// See BlockInventoryHolder - same concept there except we're also dealing with a specific block state
if (session.getLastInteractionPlayerPosition().equals(session.getPlayerEntity().getPosition())) {
int javaBlockId = session.getConnector().getWorldManager().getBlockAt(session, session.getLastInteractionBlockPosition());
String[] javaBlockString = BlockTranslator.getJavaIdBlockMap().inverse().getOrDefault(javaBlockId, "minecraft:air").split("\\[");
if (javaBlockString.length > 1 && (javaBlockString[0].equals("minecraft:chest") || javaBlockString[0].equals("minecraft:trapped_chest"))
&& !javaBlockString[1].contains("type=single")) {
inventory.setHolderPosition(session.getLastInteractionBlockPosition());
((Container) inventory).setUsingRealBlock(true);
return;
}
}
Vector3i position = session.getPlayerEntity().getPosition().toInt().add(Vector3i.UP); Vector3i position = session.getPlayerEntity().getPosition().toInt().add(Vector3i.UP);
Vector3i pairPosition = position.add(Vector3i.UNIT_X); Vector3i pairPosition = position.add(Vector3i.UNIT_X);
UpdateBlockPacket blockPacket = new UpdateBlockPacket(); UpdateBlockPacket blockPacket = new UpdateBlockPacket();
blockPacket.setDataLayer(0); blockPacket.setDataLayer(0);
blockPacket.setBlockPosition(position); blockPacket.setBlockPosition(position);
blockPacket.setRuntimeId(blockId); blockPacket.setRuntimeId(defaultBedrockBlockId);
blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY); blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
session.sendUpstreamPacket(blockPacket); session.sendUpstreamPacket(blockPacket);
@ -73,7 +86,7 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
blockPacket = new UpdateBlockPacket(); blockPacket = new UpdateBlockPacket();
blockPacket.setDataLayer(0); blockPacket.setDataLayer(0);
blockPacket.setBlockPosition(pairPosition); blockPacket.setBlockPosition(pairPosition);
blockPacket.setRuntimeId(blockId); blockPacket.setRuntimeId(defaultBedrockBlockId);
blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY); blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
session.sendUpstreamPacket(blockPacket); session.sendUpstreamPacket(blockPacket);
@ -105,6 +118,11 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
@Override @Override
public void closeInventory(GeyserSession session, Inventory inventory) { public void closeInventory(GeyserSession session, Inventory inventory) {
if (((Container) inventory).isUsingRealBlock()) {
// No need to reset a block since we didn't change any blocks
return;
}
Vector3i holderPos = inventory.getHolderPosition(); Vector3i holderPos = inventory.getHolderPosition();
Position pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ()); Position pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ());
int realBlock = session.getConnector().getWorldManager().getBlockAt(session, pos.getX(), pos.getY(), pos.getZ()); int realBlock = session.getConnector().getWorldManager().getBlockAt(session, pos.getX(), pos.getY(), pos.getZ());

Datei anzeigen

@ -30,15 +30,14 @@ import org.geysermc.connector.inventory.Inventory;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.inventory.holder.BlockInventoryHolder; import org.geysermc.connector.network.translators.inventory.holder.BlockInventoryHolder;
import org.geysermc.connector.network.translators.inventory.holder.InventoryHolder; import org.geysermc.connector.network.translators.inventory.holder.InventoryHolder;
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
public class SingleChestInventoryTranslator extends ChestInventoryTranslator { public class SingleChestInventoryTranslator extends ChestInventoryTranslator {
private final InventoryHolder holder; private final InventoryHolder holder;
public SingleChestInventoryTranslator(int size) { public SingleChestInventoryTranslator(int size) {
super(size, 27); super(size, 27);
int javaBlockState = BlockTranslator.getJavaBlockState("minecraft:chest[facing=north,type=single,waterlogged=false]"); this.holder = new BlockInventoryHolder("minecraft:chest[facing=north,type=single,waterlogged=false]", ContainerType.CONTAINER,
this.holder = new BlockInventoryHolder(BlockTranslator.getBedrockBlockId(javaBlockState), ContainerType.CONTAINER); "minecraft:chest", "minecraft:ender_chest", "minecraft:trapped_chest");
} }
@Override @Override

Datei anzeigen

@ -93,7 +93,7 @@ public class JavaBlockChangeTranslator extends PacketTranslator<ServerBlockChang
} }
private void checkInteract(GeyserSession session, ServerBlockChangePacket packet) { private void checkInteract(GeyserSession session, ServerBlockChangePacket packet) {
Vector3i lastInteractPos = session.getLastInteractionPosition(); Vector3i lastInteractPos = session.getLastInteractionBlockPosition();
if (lastInteractPos == null || !session.isInteracting()) { if (lastInteractPos == null || !session.isInteracting()) {
return; return;
} }