mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Use entities for single chest inventories, check if a block for server-side opened inventories can be placed either above or below, otherwise, close the inventory (same logic as with inventory translator found)
This commit is contained in:
parent
2c5c72f85f
commit
fda66e83b9
11 changed files with 132 additions and 42 deletions
|
@ -35,6 +35,7 @@ import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
|
|||
import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket;
|
||||
import org.geysermc.geyser.inventory.Container;
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.level.BedrockDimension;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
|
@ -70,7 +71,7 @@ public class BlockInventoryHolder extends InventoryHolder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void prepareInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) {
|
||||
public boolean prepareInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) {
|
||||
// Check to see if there is an existing block we can use that the player just selected.
|
||||
// First, verify that the player's position has not changed, so we don't try to select a block wildly out of range.
|
||||
// (This could be a virtual inventory that the player is opening)
|
||||
|
@ -83,13 +84,25 @@ public class BlockInventoryHolder extends InventoryHolder {
|
|||
inventory.setHolderPosition(session.getLastInteractionBlockPosition());
|
||||
((Container) inventory).setUsingRealBlock(true, javaBlockString[0]);
|
||||
setCustomName(session, session.getLastInteractionBlockPosition(), inventory, javaBlockId);
|
||||
return;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a fake block can be placed, either above the player or beneath.
|
||||
BedrockDimension dimension = session.getChunkCache().getBedrockDimension();
|
||||
int minY = dimension.minY(), maxY = minY + dimension.height();
|
||||
Vector3i position = session.getPlayerEntity().getPosition().toInt().add(0, 5, 0);
|
||||
if (position.getY() < minY) {
|
||||
return false;
|
||||
}
|
||||
if (position.getY() >= maxY) {
|
||||
position = session.getPlayerEntity().getPosition().toInt().sub(0, 5, 0);
|
||||
if (position.getY() >= maxY) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, time to conjure up a fake block!
|
||||
Vector3i position = session.getPlayerEntity().getPosition().toInt();
|
||||
position = position.add(Vector3i.UP);
|
||||
UpdateBlockPacket blockPacket = new UpdateBlockPacket();
|
||||
blockPacket.setDataLayer(0);
|
||||
blockPacket.setBlockPosition(position);
|
||||
|
@ -99,6 +112,8 @@ public class BlockInventoryHolder extends InventoryHolder {
|
|||
inventory.setHolderPosition(position);
|
||||
|
||||
setCustomName(session, position, inventory, defaultJavaBlockState);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -30,7 +30,7 @@ import org.geysermc.geyser.session.GeyserSession;
|
|||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
|
||||
public abstract class InventoryHolder {
|
||||
public abstract void prepareInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory);
|
||||
public abstract boolean prepareInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory);
|
||||
public abstract void openInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory);
|
||||
public abstract void closeInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory);
|
||||
}
|
||||
|
|
|
@ -65,8 +65,8 @@ public abstract class AbstractBlockInventoryTranslator extends BaseInventoryTran
|
|||
}
|
||||
|
||||
@Override
|
||||
public void prepareInventory(GeyserSession session, Inventory inventory) {
|
||||
holder.prepareInventory(this, session, inventory);
|
||||
public boolean prepareInventory(GeyserSession session, Inventory inventory) {
|
||||
return holder.prepareInventory(this, session, inventory);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -101,7 +101,7 @@ public abstract class InventoryTranslator {
|
|||
|
||||
public final int size;
|
||||
|
||||
public abstract void prepareInventory(GeyserSession session, Inventory inventory);
|
||||
public abstract boolean prepareInventory(GeyserSession session, Inventory inventory);
|
||||
public abstract void openInventory(GeyserSession session, Inventory inventory);
|
||||
public abstract void closeInventory(GeyserSession session, Inventory inventory);
|
||||
public abstract void updateProperty(GeyserSession session, Inventory inventory, int key, int value);
|
||||
|
|
|
@ -55,7 +55,8 @@ public class LecternInventoryTranslator extends BaseInventoryTranslator {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void prepareInventory(GeyserSession session, Inventory inventory) {
|
||||
public boolean prepareInventory(GeyserSession session, Inventory inventory) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -94,7 +94,7 @@ public class MerchantInventoryTranslator extends BaseInventoryTranslator {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void prepareInventory(GeyserSession session, Inventory inventory) {
|
||||
public boolean prepareInventory(GeyserSession session, Inventory inventory) {
|
||||
MerchantContainer merchantInventory = (MerchantContainer) inventory;
|
||||
if (merchantInventory.getVillager() == null) {
|
||||
long geyserId = session.getEntityCache().getNextEntityId().incrementAndGet();
|
||||
|
@ -117,6 +117,8 @@ public class MerchantInventoryTranslator extends BaseInventoryTranslator {
|
|||
|
||||
merchantInventory.setVillager(villager);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -514,7 +514,8 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void prepareInventory(GeyserSession session, Inventory inventory) {
|
||||
public boolean prepareInventory(GeyserSession session, Inventory inventory) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -35,11 +35,12 @@ import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
|
|||
import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket;
|
||||
import org.geysermc.geyser.inventory.Container;
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.level.BedrockDimension;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.DoubleChestValue;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.level.block.entity.DoubleChestBlockEntityTranslator;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
|
||||
public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
|
||||
private final int defaultJavaBlockState;
|
||||
|
@ -50,7 +51,7 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void prepareInventory(GeyserSession session, Inventory inventory) {
|
||||
public boolean 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.getGeyser().getWorldManager().getBlockAt(session, session.getLastInteractionBlockPosition());
|
||||
|
@ -76,11 +77,25 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
|
|||
dataPacket.setData(tag.build());
|
||||
dataPacket.setBlockPosition(session.getLastInteractionBlockPosition());
|
||||
session.sendUpstreamPacket(dataPacket);
|
||||
return;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a fake block can be placed, either above the player or beneath.
|
||||
BedrockDimension dimension = session.getChunkCache().getBedrockDimension();
|
||||
int minY = dimension.minY(), maxY = minY + dimension.height();
|
||||
Vector3i position = session.getPlayerEntity().getPosition().toInt().add(0, 5, 0);
|
||||
if (position.getY() < minY) {
|
||||
return false;
|
||||
}
|
||||
if (position.getY() >= maxY) {
|
||||
position = session.getPlayerEntity().getPosition().toInt().sub(0, 5, 0);
|
||||
if (position.getY() >= maxY) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Vector3i position = session.getPlayerEntity().getPosition().toInt().add(Vector3i.UP);
|
||||
Vector3i pairPosition = position.add(Vector3i.UNIT_X);
|
||||
int bedrockBlockId = session.getBlockMappings().getBedrockBlockId(defaultJavaBlockState);
|
||||
|
||||
|
@ -125,6 +140,8 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
|
|||
session.sendUpstreamPacket(dataPacket);
|
||||
|
||||
inventory.setHolderPosition(position);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -25,44 +25,99 @@
|
|||
|
||||
package org.geysermc.geyser.translator.inventory.chest;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlags;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
|
||||
import com.nukkitx.protocol.bedrock.packet.AddEntityPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.ContainerClosePacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.RemoveEntityPacket;
|
||||
import org.geysermc.geyser.inventory.Container;
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.inventory.holder.BlockInventoryHolder;
|
||||
import org.geysermc.geyser.inventory.holder.InventoryHolder;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
public class SingleChestInventoryTranslator extends ChestInventoryTranslator {
|
||||
private final InventoryHolder holder;
|
||||
|
||||
public SingleChestInventoryTranslator(int size) {
|
||||
super(size, 27);
|
||||
this.holder = new BlockInventoryHolder("minecraft:chest[facing=north,type=single,waterlogged=false]", ContainerType.CONTAINER,
|
||||
"minecraft:ender_chest", "minecraft:trapped_chest") {
|
||||
@Override
|
||||
protected boolean isValidBlock(String[] javaBlockString) {
|
||||
if (javaBlockString[0].equals("minecraft:ender_chest")) {
|
||||
// Can't have double ender chests
|
||||
return true;
|
||||
}
|
||||
|
||||
// Add provision to ensure this isn't a double chest
|
||||
return super.isValidBlock(javaBlockString) && (javaBlockString.length > 1 && javaBlockString[1].contains("type=single"));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareInventory(GeyserSession session, Inventory inventory) {
|
||||
holder.prepareInventory(this, session, inventory);
|
||||
public boolean 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.getGeyser().getWorldManager().getBlockAt(session, session.getLastInteractionBlockPosition());
|
||||
String[] javaBlockString = BlockRegistries.JAVA_IDENTIFIERS.get().getOrDefault(javaBlockId, "minecraft:air").split("\\[");
|
||||
if (javaBlockString[0].equals("minecraft:ender_chest") || 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]);
|
||||
|
||||
NbtMap tag = NbtMap.builder()
|
||||
.putInt("x", session.getLastInteractionBlockPosition().getX())
|
||||
.putInt("y", session.getLastInteractionBlockPosition().getY())
|
||||
.putInt("z", session.getLastInteractionBlockPosition().getZ())
|
||||
.putString("CustomName", inventory.getTitle()).build();
|
||||
BlockEntityDataPacket dataPacket = new BlockEntityDataPacket();
|
||||
dataPacket.setData(tag);
|
||||
dataPacket.setBlockPosition(session.getLastInteractionBlockPosition());
|
||||
session.sendUpstreamPacket(dataPacket);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
long entityId = session.getEntityCache().getNextEntityId().incrementAndGet();
|
||||
AddEntityPacket addEntityPacket = new AddEntityPacket();
|
||||
addEntityPacket.setUniqueEntityId(entityId);
|
||||
addEntityPacket.setRuntimeEntityId(entityId);
|
||||
addEntityPacket.setIdentifier("minecraft:creeper");
|
||||
addEntityPacket.setPosition(session.getPlayerEntity().getPosition());
|
||||
addEntityPacket.setMotion(Vector3f.ZERO);
|
||||
addEntityPacket.setRotation(Vector3f.ZERO);
|
||||
EntityFlags entityFlags = new EntityFlags();
|
||||
entityFlags.setFlag(EntityFlag.INVISIBLE, true);
|
||||
addEntityPacket.getMetadata()
|
||||
.putFlags(entityFlags)
|
||||
.putFloat(EntityData.SCALE, 0F)
|
||||
.putFloat(EntityData.BOUNDING_BOX_WIDTH, 0F)
|
||||
.putFloat(EntityData.BOUNDING_BOX_HEIGHT, 0F)
|
||||
.putString(EntityData.NAMETAG, inventory.getTitle())
|
||||
.putInt(EntityData.CONTAINER_BASE_SIZE, inventory.getSize());
|
||||
session.sendUpstreamPacket(addEntityPacket);
|
||||
inventory.setHolderId(entityId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openInventory(GeyserSession session, Inventory inventory) {
|
||||
holder.openInventory(this, session, inventory);
|
||||
ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket();
|
||||
containerOpenPacket.setId((byte) inventory.getBedrockId());
|
||||
containerOpenPacket.setType(ContainerType.CONTAINER);
|
||||
containerOpenPacket.setBlockPosition(inventory.getHolderPosition());
|
||||
containerOpenPacket.setUniqueEntityId(inventory.getHolderId());
|
||||
session.sendUpstreamPacket(containerOpenPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeInventory(GeyserSession session, Inventory inventory) {
|
||||
holder.closeInventory(this, session, inventory);
|
||||
if (((Container) inventory).isUsingRealBlock()) {
|
||||
// No need to reset a block since we didn't change any blocks
|
||||
// But send a container close packet because we aren't destroying the original.
|
||||
ContainerClosePacket packet = new ContainerClosePacket();
|
||||
packet.setId((byte) inventory.getBedrockId());
|
||||
packet.setUnknownBool0(true); //TODO needs to be changed in Protocol to "server-side" or something
|
||||
session.sendUpstreamPacket(packet);
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveEntityPacket removeEntityPacket = new RemoveEntityPacket();
|
||||
removeEntityPacket.setUniqueEntityId(inventory.getHolderId());
|
||||
session.sendUpstreamPacket(removeEntityPacket);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,8 @@ public abstract class AbstractHorseInventoryTranslator extends BaseInventoryTran
|
|||
}
|
||||
|
||||
@Override
|
||||
public void prepareInventory(GeyserSession session, Inventory inventory) {
|
||||
public boolean prepareInventory(GeyserSession session, Inventory inventory) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -85,8 +85,7 @@ public class InventoryUtils {
|
|||
|
||||
public static void displayInventory(GeyserSession session, Inventory inventory) {
|
||||
InventoryTranslator translator = session.getInventoryTranslator();
|
||||
if (translator != null) {
|
||||
translator.prepareInventory(session, inventory);
|
||||
if (translator != null && translator.prepareInventory(session, inventory)) {
|
||||
if (translator instanceof DoubleChestInventoryTranslator && !((Container) inventory).isUsingRealBlock()) {
|
||||
session.scheduleInEventLoop(() -> {
|
||||
Inventory openInv = session.getOpenInventory();
|
||||
|
@ -103,7 +102,6 @@ public class InventoryUtils {
|
|||
translator.updateInventory(session, inventory);
|
||||
}
|
||||
} else {
|
||||
// Precaution - as of 1.16 every inventory should be translated so this shouldn't happen
|
||||
session.setOpenInventory(null);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue