diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/tweaker/VersionTweaker.kt b/src/main/java/de/bixilon/minosoft/data/mappings/tweaker/VersionTweaker.kt index ce491ffb7..a033ebb0a 100644 --- a/src/main/java/de/bixilon/minosoft/data/mappings/tweaker/VersionTweaker.kt +++ b/src/main/java/de/bixilon/minosoft/data/mappings/tweaker/VersionTweaker.kt @@ -93,7 +93,11 @@ object VersionTweaker { return } for ((sectionHeight, section) in sections) { - for ((location, blockInfo) in section.blocks) { + for ((index, blockInfo) in section.blocks.withIndex()) { + if (blockInfo == null) { + continue + } + val location = ChunkSection.getPosition(index) val newBlock = transformBlock(blockInfo.block, sections, location, sectionHeight) if (newBlock === blockInfo.block) { continue diff --git a/src/main/java/de/bixilon/minosoft/data/world/Chunk.kt b/src/main/java/de/bixilon/minosoft/data/world/Chunk.kt index 2e73849e6..8ce2a51e5 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/Chunk.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/Chunk.kt @@ -56,7 +56,7 @@ class Chunk( } // replace all chunk sections for ((sectionHeight, chunkSection) in it) { - getSectionOrCreate(sectionHeight).setData(chunkSection, merge) + getSectionOrCreate(sectionHeight).setData(chunkSection) } } data.biomeAccessor?.let { @@ -82,7 +82,7 @@ class Chunk( getSectionOrCreate(position.getSectionHeight()).let { val inChunkSectionLocation = position.getInChunkSectionLocation() if (block == null) { - it.blocks.remove(inChunkSectionLocation) + it.blocks[ChunkSection.getIndex(inChunkSectionLocation)] = null return } it.setBlockInfo(inChunkSectionLocation, BlockInfo(block)) diff --git a/src/main/java/de/bixilon/minosoft/data/world/ChunkSection.kt b/src/main/java/de/bixilon/minosoft/data/world/ChunkSection.kt index ef7754fe7..767480723 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/ChunkSection.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/ChunkSection.kt @@ -13,24 +13,21 @@ package de.bixilon.minosoft.data.world import de.bixilon.minosoft.data.mappings.blocks.BlockState +import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition /** * Collection of 16x16x16 blocks */ -class ChunkSection constructor( - val blocks: MutableMap = mutableMapOf(), +class ChunkSection( + val blocks: Array = arrayOfNulls(ProtocolDefinition.BLOCKS_PER_SECTION), ) { fun getBlockInfo(position: InChunkSectionPosition): BlockInfo? { - return blocks[position] + return blocks[getIndex(position)] } fun setBlockInfo(position: InChunkSectionPosition, blockInfo: BlockInfo?) { - if (blockInfo == null) { - blocks.remove(position) - return - } - blocks[position] = blockInfo + blocks[getIndex(position)] = blockInfo } fun getBlockInfo(x: Int, y: Int, z: Int): BlockInfo? { @@ -45,10 +42,23 @@ class ChunkSection constructor( setBlockInfo(position, BlockInfo(block)) } - fun setData(chunkSection: ChunkSection, merge: Boolean = false) { - if (!merge) { - this.blocks.clear() + fun setData(chunkSection: ChunkSection) { + for ((index, blockInfo) in chunkSection.blocks.withIndex()) { + blocks[index] = blockInfo + } + } + + companion object { + fun getIndex(position: InChunkSectionPosition): Int { + return getIndex(position.x, position.y, position.z) + } + + fun getIndex(x: Int, y: Int, z: Int): Int { + return y shl 8 or (z shl 4) or x + } + + fun getPosition(index: Int): InChunkSectionPosition { + return InChunkSectionPosition(index and 0x0F, (index shr 8) and 0x0F, (index shr 4) and 0x0F) } - this.blocks.putAll(chunkSection.blocks) } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/WorldRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/WorldRenderer.kt index 0209c6987..7a9ae8ccb 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/WorldRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/WorldRenderer.kt @@ -58,8 +58,11 @@ class WorldRenderer( val mesh = ChunkMesh() - for ((position, blockInfo) in section.blocks) { - val blockPosition = BlockPosition(chunkPosition, sectionHeight, position) + for ((index, blockInfo) in section.blocks.withIndex()) { + if (blockInfo == null) { + continue + } + val blockPosition = BlockPosition(chunkPosition, sectionHeight, ChunkSection.getPosition(index)) val neighborBlocks: Array = arrayOfNulls(Directions.DIRECTIONS.size) for (direction in Directions.DIRECTIONS) { diff --git a/src/main/java/de/bixilon/minosoft/util/chunk/ChunkUtil.java b/src/main/java/de/bixilon/minosoft/util/chunk/ChunkUtil.java index 94c36a72d..4b325e8f7 100644 --- a/src/main/java/de/bixilon/minosoft/util/chunk/ChunkUtil.java +++ b/src/main/java/de/bixilon/minosoft/util/chunk/ChunkUtil.java @@ -19,7 +19,6 @@ import de.bixilon.minosoft.data.mappings.blocks.BlockState; import de.bixilon.minosoft.data.world.BlockInfo; import de.bixilon.minosoft.data.world.ChunkData; import de.bixilon.minosoft.data.world.ChunkSection; -import de.bixilon.minosoft.data.world.InChunkSectionPosition; import de.bixilon.minosoft.data.world.biome.DummyBiomeAccessor; import de.bixilon.minosoft.data.world.biome.XZBiomeAccessor; import de.bixilon.minosoft.data.world.light.DummyLightAccessor; @@ -62,7 +61,7 @@ public final class ChunkUtil { HashMap sectionMap = new HashMap<>(); for (int sectionHeight = dimension.getLowestSection(); sectionHeight < dimension.getHighestSection(); sectionHeight++) { // max sections per chunks in chunk column if (BitByte.isBitSet(sectionBitMasks[0], sectionHeight)) { - HashMap blockMap = new HashMap<>(); + BlockInfo[] blocks = new BlockInfo[ProtocolDefinition.BLOCKS_PER_SECTION]; for (int nibbleY = 0; nibbleY < ProtocolDefinition.SECTION_HEIGHT_Y; nibbleY++) { for (int nibbleZ = 0; nibbleZ < ProtocolDefinition.SECTION_WIDTH_Z; nibbleZ++) { @@ -90,12 +89,15 @@ public final class ChunkUtil { continue; } BlockState block = buffer.getConnection().getMapping().getBlockState(fullBlockId); - blockMap.put(new InChunkSectionPosition(nibbleX, nibbleY, nibbleZ), new BlockInfo(block)); + if (block == null) { + continue; + } + blocks[ChunkSection.Companion.getIndex(nibbleX, nibbleY, nibbleZ)] = new BlockInfo(block); arrayPos++; } } } - sectionMap.put(dimension.getLowestSection() + sectionHeight, new ChunkSection(blockMap)); // ToDo + sectionMap.put(dimension.getLowestSection() + sectionHeight, new ChunkSection(blocks)); // ToDo } } return new ChunkData(sectionMap, new DummyBiomeAccessor(buffer.getConnection().getMapping().getBiomeRegistry().get(0)), DummyLightAccessor.INSTANCE); @@ -126,7 +128,7 @@ public final class ChunkUtil { if (!BitByte.isBitSet(sectionBitMasks[0], sectionHeight)) { continue; } - HashMap blockMap = new HashMap<>(); + BlockInfo[] blocks = new BlockInfo[ProtocolDefinition.BLOCKS_PER_SECTION]; for (int nibbleY = 0; nibbleY < ProtocolDefinition.SECTION_HEIGHT_Y; nibbleY++) { for (int nibbleZ = 0; nibbleZ < ProtocolDefinition.SECTION_WIDTH_Z; nibbleZ++) { @@ -137,12 +139,12 @@ public final class ChunkUtil { arrayPos++; continue; } - blockMap.put(new InChunkSectionPosition(nibbleX, nibbleY, nibbleZ), new BlockInfo(block)); + blocks[ChunkSection.Companion.getIndex(nibbleX, nibbleY, nibbleZ)] = new BlockInfo(block); arrayPos++; } } } - sectionMap.put(dimension.getLowestSection() + sectionHeight, new ChunkSection(blockMap)); + sectionMap.put(dimension.getLowestSection() + sectionHeight, new ChunkSection(blocks)); } return new ChunkData(sectionMap, new DummyBiomeAccessor(buffer.getConnection().getMapping().getBiomeRegistry().get(0)), DummyLightAccessor.INSTANCE); // ToDo } @@ -162,7 +164,7 @@ public final class ChunkUtil { long[] data = buffer.readLongArray(); - HashMap blockMap = new HashMap<>(); + BlockInfo[] blocks = new BlockInfo[ProtocolDefinition.BLOCKS_PER_SECTION]; for (int nibbleY = 0; nibbleY < ProtocolDefinition.SECTION_HEIGHT_Y; nibbleY++) { for (int nibbleZ = 0; nibbleZ < ProtocolDefinition.SECTION_WIDTH_Z; nibbleZ++) { for (int nibbleX = 0; nibbleX < ProtocolDefinition.SECTION_WIDTH_X; nibbleX++) { @@ -193,7 +195,7 @@ public final class ChunkUtil { if (block == null) { continue; } - blockMap.put(new InChunkSectionPosition(nibbleX, nibbleY, nibbleZ), new BlockInfo(block)); + blocks[ChunkSection.Companion.getIndex(nibbleX, nibbleY, nibbleZ)] = new BlockInfo(block); } } } @@ -206,7 +208,7 @@ public final class ChunkUtil { // ToDo } - sectionMap.put(dimension.getLowestSection() + sectionHeight, new ChunkSection(blockMap)); + sectionMap.put(dimension.getLowestSection() + sectionHeight, new ChunkSection(blocks)); } ChunkData chunkData = new ChunkData(); chunkData.setBlocks(sectionMap);