From 5f5159d30e095041921ffbfa20ba57c7db953352 Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Sat, 11 Mar 2023 01:48:51 -0800 Subject: [PATCH] Extended collision boxes almost work Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .../mappings/versions/MappingsReader_v1.java | 4 +- .../JavaLevelChunkWithLightTranslator.java | 54 +++++++++++++++---- .../org/geysermc/geyser/util/ChunkUtils.java | 25 +++++++-- 3 files changed, 69 insertions(+), 14 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java b/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java index f65df3a04..2c399e50b 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java +++ b/core/src/main/java/org/geysermc/geyser/registry/mappings/versions/MappingsReader_v1.java @@ -294,11 +294,11 @@ public class MappingsReader_v1 extends MappingsReader { // This is needed to find the correct selection box for the given block int id = BlockRegistries.JAVA_IDENTIFIERS.getOrDefault(stateKey, -1); BoxComponent boxComponent = createBoxComponent(id, 0, 16, 0); - BoxComponent extendedboxComponent = createBoxComponent(id, 16, 32, -16); + BoxComponent extendedBoxComponent = createBoxComponent(id, 16, 32, -16); CustomBlockComponents.Builder builder = new CustomBlockComponentsBuilder() .collisionBox(boxComponent) .selectionBox(boxComponent) - .extendedCollisionBox(extendedboxComponent); + .extendedCollisionBox(extendedBoxComponent); if (node == null) { // No other components were defined diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelChunkWithLightTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelChunkWithLightTranslator.java index 38e2ff644..ecc5e9a5c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelChunkWithLightTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelChunkWithLightTranslator.java @@ -69,6 +69,7 @@ import org.geysermc.geyser.util.BlockEntityUtils; import org.geysermc.geyser.util.ChunkUtils; import java.io.IOException; +import java.util.Arrays; import java.util.BitSet; import java.util.List; import java.util.Map; @@ -109,6 +110,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator Arrays.fill(runningSectionExtendedCollisions, 256, 4095, 0); + case 256 -> Arrays.fill(runningSectionExtendedCollisions, 0, 256, 0); + } + if (javaId == BlockStateValues.JAVA_AIR_ID && runningSectionExtendedCollisions[yzx] != 0) { + section.getBlockStorageArray()[0].setFullBlock(xzy, runningSectionExtendedCollisions[yzx]); + continue; + } + int aboveBedrockExtendedCollisionId = BlockRegistries.EXTENDED_COLLISION_BOXES.getOrDefault(javaId, -1); + if (aboveBedrockExtendedCollisionId != -1) { + runningSectionExtendedCollisions[((yzx & 0x0ff) | (((yzx >> 8) + ((xzy & 0xF) < 15 ? 1 : -15)) << 8))] = aboveBedrockExtendedCollisionId; } // Check if block is piston or flower to see if we'll need to create additional block entities, as they're only block entities in Bedrock @@ -222,7 +228,23 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator Arrays.fill(runningSectionExtendedCollisions, 256, 4095, 0); + case 256 -> Arrays.fill(runningSectionExtendedCollisions, 0, 256, 0); + } + int javaId = javaPalette.idToState(paletteId); + if (javaId == BlockStateValues.JAVA_AIR_ID && runningSectionExtendedCollisions[yzx] != 0) { + bedrockData.set(xzy, layer0.idFor(runningSectionExtendedCollisions[yzx])); + continue; + } + int aboveBedrockExtendedCollisionId = BlockRegistries.EXTENDED_COLLISION_BOXES.getOrDefault(javaId, -1); + if (aboveBedrockExtendedCollisionId != -1) { + runningSectionExtendedCollisions[((yzx & 0x0ff) | (((yzx >> 8) + ((xzy & 0xF) < 15 ? 1 : -15)) << 8))] = aboveBedrockExtendedCollisionId; + } } layers = new BlockStorage[]{ layer0 }; @@ -238,6 +260,20 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator> 5] |= 1 << (xzy & 0x1F); } + + switch (yzx) { + case 0 -> Arrays.fill(runningSectionExtendedCollisions, 256, 4095, 0); + case 256 -> Arrays.fill(runningSectionExtendedCollisions, 0, 256, 0); + } + int javaId = javaPalette.idToState(paletteId); + if (javaId == BlockStateValues.JAVA_AIR_ID && runningSectionExtendedCollisions[yzx] != 0) { + bedrockData.set(xzy, layer0.idFor(runningSectionExtendedCollisions[yzx])); + continue; + } + int aboveBedrockExtendedCollisionId = BlockRegistries.EXTENDED_COLLISION_BOXES.getOrDefault(javaId, -1); + if (aboveBedrockExtendedCollisionId != -1) { + runningSectionExtendedCollisions[((yzx & 0x0ff) | (((yzx >> 8) + ((xzy & 0xF) < 15 ? 1 : -15)) << 8))] = aboveBedrockExtendedCollisionId; + } } // V1 palette diff --git a/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java b/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java index 717e40451..90ee2adfe 100644 --- a/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java @@ -129,7 +129,7 @@ public class ChunkUtils { // Otherwise, let's still store our reference to the item frame, but let the new block take precedence for now } - int blockId = session.getBlockMappings().getBedrockBlockId(blockState); + int bedrockId = session.getBlockMappings().getBedrockBlockId(blockState); int skullVariant = BlockStateValues.getSkullVariant(blockState); if (skullVariant == -1) { // Skull is gone @@ -138,17 +138,36 @@ public class ChunkUtils { // The changed block was a player skull so check if a custom block was defined for this skull SkullCache.Skull skull = session.getSkullCache().updateSkull(position, blockState); if (skull != null && skull.getCustomRuntimeId() != -1) { - blockId = skull.getCustomRuntimeId(); + bedrockId = skull.getCustomRuntimeId(); } } + // Extended collision boxes for custom blocks + int aboveBedrockExtendedCollisionId = BlockRegistries.EXTENDED_COLLISION_BOXES.getOrDefault(blockState, -1); + int aboveBlock = session.getChunkCache().getBlockAt(position.getX(), position.getY() + 1, position.getZ()); + if (aboveBedrockExtendedCollisionId != -1) { + UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); + updateBlockPacket.setDataLayer(0); + updateBlockPacket.setBlockPosition(position.add(0, 1, 0)); + updateBlockPacket.setRuntimeId(aboveBedrockExtendedCollisionId); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); + session.sendUpstreamPacket(updateBlockPacket); + } else if (aboveBlock == BlockStateValues.JAVA_AIR_ID) { + UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); + updateBlockPacket.setDataLayer(0); + updateBlockPacket.setBlockPosition(position.add(0, 1, 0)); + updateBlockPacket.setRuntimeId(session.getBlockMappings().getBedrockAirId()); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); + session.sendUpstreamPacket(updateBlockPacket); + } + // Prevent moving_piston from being placed // It's used for extending piston heads, but it isn't needed on Bedrock and causes pistons to flicker if (!BlockStateValues.isMovingPiston(blockState)) { UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); updateBlockPacket.setDataLayer(0); updateBlockPacket.setBlockPosition(position); - updateBlockPacket.setRuntimeId(blockId); + updateBlockPacket.setRuntimeId(bedrockId); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); session.sendUpstreamPacket(updateBlockPacket);