diff --git a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java index 979d3bc7d..f1f62da40 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/GeyserCustomBlockComponents.java @@ -168,7 +168,7 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents { protected boolean placeAir = false; protected Set tags = new HashSet<>(); - private void validateBox(BoxComponent box) { + private void validateBox(BoxComponent box, boolean collision) { if (box == null) { return; } @@ -181,21 +181,28 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents { float maxX = minX + box.sizeX(); float maxY = minY + box.sizeY(); float maxZ = minZ + box.sizeZ(); - if (minX < 0 || minY < 0 || minZ < 0 || maxX > 16 || maxY > 16 || maxZ > 16) { - throw new IllegalArgumentException("Box bounds must be within (0, 0, 0) and (16, 16, 16). Recieved: (" + minX + ", " + minY + ", " + minZ + ") to (" + maxX + ", " + maxY + ", " + maxZ + ")"); + if (collision) { + // Since 1.21.130, max y of collisions is 24 + if (minX < 0 || minY < 0 || minZ < 0 || maxX > 16 || maxY > 24 || maxZ > 16) { + throw new IllegalArgumentException("Collision box bounds must be within (0, 0, 0) and (16, 24, 16). Received: (" + minX + ", " + minY + ", " + minZ + ") to (" + maxX + ", " + maxY + ", " + maxZ + ")"); + } + } else { + if (minX < 0 || minY < 0 || minZ < 0 || maxX > 16 || maxY > 16 || maxZ > 16) { + throw new IllegalArgumentException("Box bounds must be within (0, 0, 0) and (16, 16, 16). Received: (" + minX + ", " + minY + ", " + minZ + ") to (" + maxX + ", " + maxY + ", " + maxZ + ")"); + } } } @Override public Builder selectionBox(BoxComponent selectionBox) { - validateBox(selectionBox); + validateBox(selectionBox, false); this.selectionBox = selectionBox; return this; } @Override public Builder collisionBox(BoxComponent collisionBox) { - validateBox(collisionBox); + validateBox(collisionBox, true); this.collisionBox = collisionBox; return this; } diff --git a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java index ecd7311ca..35902368d 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java +++ b/core/src/main/java/org/geysermc/geyser/network/GameProtocol.java @@ -156,6 +156,10 @@ public final class GameProtocol { return protocolVersion >= Bedrock_v844.CODEC.getProtocolVersion(); } + public static boolean is1_21_130orHigher(int protocolVersion) { + return protocolVersion >= Bedrock_v897.CODEC.getProtocolVersion(); + } + /** * Gets the supported Minecraft: Java Edition version names. * diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java index 665ab9cd0..4a0ecd219 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CustomBlockRegistryPopulator.java @@ -419,12 +419,14 @@ public class CustomBlockRegistryPopulator { .build()); } - if (components.selectionBox() != null) { - builder.putCompound("minecraft:selection_box", convertBox(components.selectionBox())); + BoxComponent selectionBox = components.selectionBox(); + if (selectionBox != null) { + builder.putCompound("minecraft:selection_box", convertBox(selectionBox)); } - if (components.collisionBox() != null) { - builder.putCompound("minecraft:collision_box", convertBox(components.collisionBox())); + BoxComponent collisionBox = components.collisionBox(); + if (collisionBox != null) { + builder.putCompound("minecraft:collision_box", convertCollisionBox(collisionBox, protocolVersion)); } if (components.geometry() != null) { @@ -541,6 +543,32 @@ public class CustomBlockRegistryPopulator { return builder.build(); } + /** + * Converts the provided COLLISION box component to an {@link NbtMap} + * + * @param boxComponent the box component to convert + * @return the NBT representation of the provided box component + */ + private static NbtMap convertCollisionBox(BoxComponent boxComponent, int protocolVersion) { + if (GameProtocol.is1_21_130orHigher(protocolVersion)) { + float minX = 8f + boxComponent.originX(); + float minY = boxComponent.originY(); + float minZ = 8f + boxComponent.originZ(); + return NbtMap.builder() + .putBoolean("enabled", !boxComponent.isEmpty()) + .putList("boxes", NbtType.COMPOUND, NbtMap.builder() + .putFloat("minX", minX) + .putFloat("minY", minY) + .putFloat("minZ", minZ) + .putFloat("maxX", minX + boxComponent.sizeX()) + .putFloat("maxY", minY + boxComponent.sizeY()) + .putFloat("maxZ", minZ + boxComponent.sizeZ()) + .build()).build(); + } else { + return convertBox(boxComponent); + } + } + /** * Converts the provided box component to an {@link NbtMap} * @@ -551,7 +579,8 @@ public class CustomBlockRegistryPopulator { return NbtMap.builder() .putBoolean("enabled", !boxComponent.isEmpty()) .putList("origin", NbtType.FLOAT, boxComponent.originX(), boxComponent.originY(), boxComponent.originZ()) - .putList("size", NbtType.FLOAT, boxComponent.sizeX(), boxComponent.sizeY(), boxComponent.sizeZ()) + // TODO remove after 1.21.130 - collision boxes sent to below 1.21.130 must be capped + .putList("size", NbtType.FLOAT, boxComponent.sizeX(), Math.min(boxComponent.sizeY(), 16), boxComponent.sizeZ()) .build(); } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java index 8602d37dc..14332a704 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java @@ -43,6 +43,7 @@ import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.event.java.ServerDefineCommandsEvent; import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.command.CommandRegistry; +import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.session.GeyserSession; @@ -123,7 +124,7 @@ public class JavaCommandsTranslator extends PacketTranslator