Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-12-26 00:00:41 +01:00
Use the real block for opening inventory when possible
Dieser Commit ist enthalten in:
Ursprung
aaeca23f54
Commit
78337830c6
@ -38,6 +38,11 @@ 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.
|
||||||
|
*/
|
||||||
|
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;
|
||||||
@ -66,4 +71,14 @@ public class Container extends Inventory {
|
|||||||
public int getSize() {
|
public int getSize() {
|
||||||
return this.containerSize;
|
return this.containerSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will be overwritten for droppers.
|
||||||
|
*
|
||||||
|
* @param usingRealBlock whether this container is using a real container or not
|
||||||
|
* @param javaBlockId the Java block string of the block, if real
|
||||||
|
*/
|
||||||
|
public void setUsingRealBlock(boolean usingRealBlock, String javaBlockId) {
|
||||||
|
isUsingRealBlock = usingRealBlock;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.inventory;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
public class Generic3X3Container extends Container {
|
||||||
|
/**
|
||||||
|
* Whether we need to set the container type as {@link com.nukkitx.protocol.bedrock.data.inventory.ContainerType#DROPPER}
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
private boolean isDropper = false;
|
||||||
|
|
||||||
|
public Generic3X3Container(String title, int id, int size, PlayerInventory playerInventory) {
|
||||||
|
super(title, id, size, playerInventory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUsingRealBlock(boolean usingRealBlock, String javaBlockId) {
|
||||||
|
super.setUsingRealBlock(usingRealBlock, javaBlockId);
|
||||||
|
if (usingRealBlock) {
|
||||||
|
isDropper = javaBlockId.startsWith("minecraft:dropper");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
@ -234,7 +233,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;
|
||||||
@ -242,15 +249,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.
|
||||||
|
@ -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 {
|
||||||
|
@ -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! :)
|
||||||
|
@ -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());
|
||||||
|
@ -26,43 +26,79 @@
|
|||||||
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)
|
||||||
return;
|
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, javaBlockString);
|
||||||
|
setCustomName(session, session.getLastInteractionBlockPosition(), inventory);
|
||||||
|
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);
|
||||||
|
|
||||||
|
setCustomName(session, position, inventory);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setCustomName(GeyserSession session, Vector3i position, Inventory inventory) {
|
||||||
NbtMap tag = NbtMap.builder()
|
NbtMap tag = NbtMap.builder()
|
||||||
.putInt("x", position.getX())
|
.putInt("x", position.getX())
|
||||||
.putInt("y", position.getY())
|
.putInt("y", position.getY())
|
||||||
@ -86,10 +122,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();
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* 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.ContainerSlotType;
|
||||||
|
import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
|
||||||
|
import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
|
||||||
|
import org.geysermc.connector.inventory.Generic3X3Container;
|
||||||
|
import org.geysermc.connector.inventory.Inventory;
|
||||||
|
import org.geysermc.connector.inventory.PlayerInventory;
|
||||||
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
import org.geysermc.connector.network.translators.inventory.BedrockContainerSlot;
|
||||||
|
import org.geysermc.connector.network.translators.inventory.updater.ContainerInventoryUpdater;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Droppers and dispensers
|
||||||
|
*/
|
||||||
|
public class Generic3X3InventoryTranslator extends AbstractBlockInventoryTranslator {
|
||||||
|
|
||||||
|
public Generic3X3InventoryTranslator() {
|
||||||
|
super(9, "minecraft:dispenser[facing=north,triggered=false]", ContainerType.DISPENSER, ContainerInventoryUpdater.INSTANCE,
|
||||||
|
"minecraft:dropper");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Inventory createInventory(String name, int windowId, WindowType windowType, PlayerInventory playerInventory) {
|
||||||
|
return new Generic3X3Container(name, windowId, this.size, playerInventory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void openInventory(GeyserSession session, Inventory inventory) {
|
||||||
|
ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket();
|
||||||
|
containerOpenPacket.setId((byte) inventory.getId());
|
||||||
|
containerOpenPacket.setType(((Generic3X3Container) inventory).isDropper() ? ContainerType.DROPPER : ContainerType.DISPENSER);
|
||||||
|
containerOpenPacket.setBlockPosition(inventory.getHolderPosition());
|
||||||
|
containerOpenPacket.setUniqueEntityId(inventory.getHolderId());
|
||||||
|
session.sendUpstreamPacket(containerOpenPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BedrockContainerSlot javaSlotToBedrockContainer(int javaSlot) {
|
||||||
|
if (javaSlot < this.size) {
|
||||||
|
return new BedrockContainerSlot(ContainerSlotType.CONTAINER, javaSlot);
|
||||||
|
}
|
||||||
|
return super.javaSlotToBedrockContainer(javaSlot);
|
||||||
|
}
|
||||||
|
}
|
@ -33,9 +33,9 @@ import org.geysermc.connector.network.translators.inventory.updater.ContainerInv
|
|||||||
/**
|
/**
|
||||||
* 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, ContainerInventoryUpdater.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
@ -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");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,32 +28,66 @@ package org.geysermc.connector.network.translators.inventory.translators.chest;
|
|||||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
|
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
|
||||||
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.nbt.NbtMapBuilder;
|
||||||
import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
|
import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
|
||||||
import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket;
|
import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket;
|
||||||
import com.nukkitx.protocol.bedrock.packet.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.BlockStateValues;
|
||||||
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
|
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
|
||||||
|
import org.geysermc.connector.network.translators.world.block.DoubleChestValue;
|
||||||
|
import org.geysermc.connector.network.translators.world.block.entity.DoubleChestBlockEntityTranslator;
|
||||||
|
|
||||||
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, javaBlockString[0]);
|
||||||
|
|
||||||
|
NbtMapBuilder tag = NbtMap.builder()
|
||||||
|
.putString("id", "Chest")
|
||||||
|
.putInt("x", session.getLastInteractionBlockPosition().getX())
|
||||||
|
.putInt("y", session.getLastInteractionBlockPosition().getY())
|
||||||
|
.putInt("z", session.getLastInteractionBlockPosition().getZ())
|
||||||
|
.putString("CustomName", inventory.getTitle())
|
||||||
|
.putString("id", "Chest");
|
||||||
|
|
||||||
|
DoubleChestValue chestValue = BlockStateValues.getDoubleChestValues().get(javaBlockId);
|
||||||
|
DoubleChestBlockEntityTranslator.translateChestValue(tag, chestValue,
|
||||||
|
session.getLastInteractionBlockPosition().getX(), session.getLastInteractionBlockPosition().getZ());
|
||||||
|
|
||||||
|
BlockEntityDataPacket dataPacket = new BlockEntityDataPacket();
|
||||||
|
dataPacket.setData(tag.build());
|
||||||
|
dataPacket.setBlockPosition(session.getLastInteractionBlockPosition());
|
||||||
|
session.sendUpstreamPacket(dataPacket);
|
||||||
|
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 +107,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 +139,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());
|
||||||
|
@ -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:ender_chest", "minecraft:trapped_chest");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -57,29 +57,41 @@ public class DoubleChestBlockEntityTranslator extends BlockEntityTranslator impl
|
|||||||
if (chestValues != null) {
|
if (chestValues != null) {
|
||||||
int x = (int) tag.getValue().get("x").getValue();
|
int x = (int) tag.getValue().get("x").getValue();
|
||||||
int z = (int) tag.getValue().get("z").getValue();
|
int z = (int) tag.getValue().get("z").getValue();
|
||||||
// Calculate the position of the other chest based on the Java block state
|
translateChestValue(builder, chestValues, x, z);
|
||||||
if (chestValues.isFacingEast) {
|
}
|
||||||
if (chestValues.isDirectionPositive) {
|
}
|
||||||
// East
|
|
||||||
z = z + (chestValues.isLeft ? 1 : -1);
|
/**
|
||||||
} else {
|
* Add Bedrock block entity tags to a NbtMap based on Java properties
|
||||||
// West
|
*
|
||||||
z = z + (chestValues.isLeft ? -1 : 1);
|
* @param builder the NbtMapBuilder to apply properties to
|
||||||
}
|
* @param chestValues the position properties of this double chest
|
||||||
|
* @param x the x position of this chest pair
|
||||||
|
* @param z the z position of this chest pair
|
||||||
|
*/
|
||||||
|
public static void translateChestValue(NbtMapBuilder builder, DoubleChestValue chestValues, int x, int z) {
|
||||||
|
// Calculate the position of the other chest based on the Java block state
|
||||||
|
if (chestValues.isFacingEast) {
|
||||||
|
if (chestValues.isDirectionPositive) {
|
||||||
|
// East
|
||||||
|
z = z + (chestValues.isLeft ? 1 : -1);
|
||||||
} else {
|
} else {
|
||||||
if (chestValues.isDirectionPositive) {
|
// West
|
||||||
// South
|
z = z + (chestValues.isLeft ? -1 : 1);
|
||||||
x = x + (chestValues.isLeft ? -1 : 1);
|
|
||||||
} else {
|
|
||||||
// North
|
|
||||||
x = x + (chestValues.isLeft ? 1 : -1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
builder.put("pairx", x);
|
} else {
|
||||||
builder.put("pairz", z);
|
if (chestValues.isDirectionPositive) {
|
||||||
if (!chestValues.isLeft) {
|
// South
|
||||||
builder.put("pairlead", (byte) 1);
|
x = x + (chestValues.isLeft ? -1 : 1);
|
||||||
|
} else {
|
||||||
|
// North
|
||||||
|
x = x + (chestValues.isLeft ? 1 : -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
builder.put("pairx", x);
|
||||||
|
builder.put("pairz", z);
|
||||||
|
if (!chestValues.isLeft) {
|
||||||
|
builder.put("pairlead", (byte) 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren