From eb5e281735acedea5b22a2a7e97f3c25d739f01d Mon Sep 17 00:00:00 2001 From: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> Date: Sun, 19 Mar 2023 02:20:34 -0700 Subject: [PATCH] Extended collision boxes are much improved Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com> --- .../geyser/registry/BlockRegistries.java | 7 +- .../populator/BlockRegistryPopulator.java | 10 +- .../CustomBlockRegistryPopulator.java | 3 +- .../geyser/registry/type/BlockMappings.java | 2 + .../JavaLevelChunkWithLightTranslator.java | 113 ++++++++++++------ .../org/geysermc/geyser/util/ChunkUtils.java | 34 +++--- 6 files changed, 105 insertions(+), 64 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java b/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java index ad07740a7..21a792fc5 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java +++ b/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java @@ -116,12 +116,7 @@ public class BlockRegistries { /** * A registry which stores Custom Block Data for extended collision boxes and the Java IDs of blocks that will have said extended collision boxes placed above them. */ - public static final SimpleMappedRegistry> EXTENDED_COLLISION_BOXES_DATA = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new)); - - /** - * A registry which stores Java IDs of blocks that will have a custom collision block placed above them and the Bedrock ID of said collision block. - */ - public static final SimpleMappedRegistry EXTENDED_COLLISION_BOXES = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new)); + public static final SimpleMappedRegistry> EXTENDED_COLLISION_BOXES = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new)); /** * A registry which stores skin texture hashes to custom skull blocks. diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java index da2572d72..52baa9a9e 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java @@ -33,6 +33,8 @@ import com.nukkitx.protocol.bedrock.data.BlockPropertyData; import com.nukkitx.protocol.bedrock.v544.Bedrock_v544; import com.nukkitx.protocol.bedrock.v560.Bedrock_v560; import com.nukkitx.protocol.bedrock.v567.Bedrock_v567; +import it.unimi.dsi.fastutil.ints.Int2IntMap; +import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.objects.Object2IntMap; @@ -140,16 +142,17 @@ public final class BlockRegistryPopulator { } Object2IntMap customBlockStateIds = Object2IntMaps.emptyMap(); + Int2IntMap extendedCollisionBoxes = new Int2IntOpenHashMap(); if (BlockRegistries.CUSTOM_BLOCKS.get().length != 0) { customBlockStateIds = new Object2IntOpenHashMap<>(customExtBlockStates.size()); - Map extendedCollisionBoxes = new HashMap<>(); + //Map extendedCollisionBoxes = new HashMap<>(); for (int i = 0; i < customExtBlockStates.size(); i++) { NbtMap tag = customBlockStates.get(i); CustomBlockState blockState = customExtBlockStates.get(i); int bedrockRuntimeId = blockStateOrderedMap.getOrDefault(tag, -1); customBlockStateIds.put(blockState, bedrockRuntimeId); - Set extendedCollisionjavaIds = BlockRegistries.EXTENDED_COLLISION_BOXES_DATA.getOrDefault(blockState.block(), null); + Set extendedCollisionjavaIds = BlockRegistries.EXTENDED_COLLISION_BOXES.getOrDefault(blockState.block(), null); if (extendedCollisionjavaIds != null) { for (int javaId : extendedCollisionjavaIds) { extendedCollisionBoxes.put(javaId, bedrockRuntimeId); @@ -157,8 +160,6 @@ public final class BlockRegistryPopulator { } } - BlockRegistries.EXTENDED_COLLISION_BOXES.set(extendedCollisionBoxes); - remappedVanillaIds = new int[vanillaBlockStates.size()]; for (int i = 0; i < vanillaBlockStates.size(); i++) { remappedVanillaIds[i] = blockStateOrderedMap.getOrDefault(vanillaBlockStates.get(i), -1); @@ -273,6 +274,7 @@ public final class BlockRegistryPopulator { .remappedVanillaIds(remappedVanillaIds) .blockProperties(customBlockProperties) .customBlockStateIds(customBlockStateIds) + .extendedCollisionBoxes(extendedCollisionBoxes) .build()); } 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 805513368..3bc5e2a83 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 @@ -8,7 +8,6 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.checkerframework.checker.nullness.qual.NonNull; -import org.geysermc.geyser.Constants; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.block.custom.CustomBlockData; import org.geysermc.geyser.api.block.custom.CustomBlockPermutation; @@ -131,7 +130,7 @@ public class CustomBlockRegistryPopulator { BlockRegistries.CUSTOM_BLOCK_ITEM_OVERRIDES.set(customBlockItemOverrides); GeyserImpl.getInstance().getLogger().info("Registered " + customBlockItemOverrides.size() + " custom block item overrides."); - BlockRegistries.EXTENDED_COLLISION_BOXES_DATA.set(extendedCollisionBoxes); + BlockRegistries.EXTENDED_COLLISION_BOXES.set(extendedCollisionBoxes); GeyserImpl.getInstance().getLogger().info("Registered " + extendedCollisionBoxes.size() + " custom block extended collision boxes."); } diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/BlockMappings.java b/core/src/main/java/org/geysermc/geyser/registry/type/BlockMappings.java index 7c3cc0c79..668ec2002 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/type/BlockMappings.java +++ b/core/src/main/java/org/geysermc/geyser/registry/type/BlockMappings.java @@ -28,6 +28,7 @@ package org.geysermc.geyser.registry.type; import com.nukkitx.nbt.NbtList; import com.nukkitx.nbt.NbtMap; import com.nukkitx.protocol.bedrock.data.BlockPropertyData; +import it.unimi.dsi.fastutil.ints.Int2IntMap; import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.objects.Object2IntMap; import lombok.Builder; @@ -61,6 +62,7 @@ public class BlockMappings { List blockProperties; Object2IntMap customBlockStateIds; + Int2IntMap extendedCollisionBoxes; public int getBedrockBlockId(int state) { if (state >= this.javaToBedrockBlocks.length) { 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 ecc5e9a5c..5bf48549b 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,7 +69,6 @@ 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; @@ -111,10 +110,13 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator> 4)); if (bedrockSectionY < 0 || maxBedrockSectionY < bedrockSectionY) { @@ -144,17 +146,19 @@ 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; + if (!session.getBlockMappings().getExtendedCollisionBoxes().isEmpty()) { + if (javaId == BlockStateValues.JAVA_AIR_ID && runningSectionExtendedCollisions[yzx] != 0) { + section.getBlockStorageArray()[0].setFullBlock(xzy, runningSectionExtendedCollisions[yzx]); + runningSectionExtendedCollisions[yzx] = 0; + continue; + } + int aboveBedrockExtendedCollisionId = session.getBlockMappings().getExtendedCollisionBoxes().getOrDefault(javaId, -1); + if (aboveBedrockExtendedCollisionId != -1) { + runningSectionExtendedCollisions[((yzx & 0x0ff) | (((yzx >> 8) + ((xzy & 0xF) < 15 ? 1 : -15)) << 8))] = aboveBedrockExtendedCollisionId; + if ((xzy & 0xF) == 15) { + thisExtendedCollisionNextSection = true; + } + } } // 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 @@ -185,7 +189,8 @@ 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 }; - } else { + } else if (!waterloggedPaletteIds.isEmpty() && !extendedCollision) { // The section contains waterlogged blocks, we need to convert coordinate order AND generate a V1 block storage for // layer 1 with palette ID 1 indicating water int[] layer1Data = new int[BlockStorage.SIZE >> 5]; @@ -260,19 +262,57 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator> 5] |= 1 << (xzy & 0x1F); } + } + + // V1 palette + IntList layer1Palette = IntList.of( + session.getBlockMappings().getBedrockAirId(), // Air - see BlockStorage's constructor for more information + session.getBlockMappings().getBedrockWaterId()); - 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) { + layers = new BlockStorage[]{ layer0, new BlockStorage(BitArrayVersion.V1.createArray(BlockStorage.SIZE, layer1Data), layer1Palette) }; + } else if (waterloggedPaletteIds.isEmpty() && extendedCollision) { + for (int yzx = 0; yzx < BlockStorage.SIZE; yzx++) { + int paletteId = javaData.get(yzx); + int xzy = indexYZXtoXZY(yzx); + bedrockData.set(xzy, paletteId); + + if (paletteId == airPaletteId && runningSectionExtendedCollisions[yzx] != 0) { bedrockData.set(xzy, layer0.idFor(runningSectionExtendedCollisions[yzx])); + runningSectionExtendedCollisions[yzx] = 0; continue; } - int aboveBedrockExtendedCollisionId = BlockRegistries.EXTENDED_COLLISION_BOXES.getOrDefault(javaId, -1); + int aboveBedrockExtendedCollisionId = session.getBlockMappings().getExtendedCollisionBoxes().getOrDefault(javaPalette.idToState(paletteId), -1); if (aboveBedrockExtendedCollisionId != -1) { runningSectionExtendedCollisions[((yzx & 0x0ff) | (((yzx >> 8) + ((xzy & 0xF) < 15 ? 1 : -15)) << 8))] = aboveBedrockExtendedCollisionId; + if ((xzy & 0xF) == 15) { + thisExtendedCollisionNextSection = true; + } + } + } + + layers = new BlockStorage[]{ layer0 }; + } else { + int[] layer1Data = new int[BlockStorage.SIZE >> 5]; + for (int yzx = 0; yzx < BlockStorage.SIZE; yzx++) { + int paletteId = javaData.get(yzx); + int xzy = indexYZXtoXZY(yzx); + bedrockData.set(xzy, paletteId); + + if (waterloggedPaletteIds.get(paletteId)) { + layer1Data[xzy >> 5] |= 1 << (xzy & 0x1F); + } + + if (paletteId == airPaletteId && runningSectionExtendedCollisions[yzx] != 0) { + bedrockData.set(xzy, layer0.idFor(runningSectionExtendedCollisions[yzx])); + runningSectionExtendedCollisions[yzx] = 0; + continue; + } + int aboveBedrockExtendedCollisionId = session.getBlockMappings().getExtendedCollisionBoxes().getOrDefault(javaPalette.idToState(paletteId), -1); + if (aboveBedrockExtendedCollisionId != -1) { + runningSectionExtendedCollisions[((yzx & 0x0ff) | (((yzx >> 8) + ((xzy & 0xF) < 15 ? 1 : -15)) << 8))] = aboveBedrockExtendedCollisionId; + if ((xzy & 0xF) == 15) { + thisExtendedCollisionNextSection = true; + } } } @@ -285,6 +325,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator