diff --git a/station-flattening-v0/src/main/java/net/modificationstation/stationapi/impl/client/network/FlattenedClientPlayNetworkHandler.java b/station-flattening-v0/src/main/java/net/modificationstation/stationapi/impl/client/network/FlattenedClientPlayNetworkHandler.java index ede2b238f..86858b1b7 100644 --- a/station-flattening-v0/src/main/java/net/modificationstation/stationapi/impl/client/network/FlattenedClientPlayNetworkHandler.java +++ b/station-flattening-v0/src/main/java/net/modificationstation/stationapi/impl/client/network/FlattenedClientPlayNetworkHandler.java @@ -14,6 +14,7 @@ import net.modificationstation.stationapi.impl.world.chunk.FlattenedChunk; import java.nio.ByteBuffer; +import java.util.Arrays; public class FlattenedClientPlayNetworkHandler extends StationFlatteningPacketHandler { @@ -31,6 +32,9 @@ public void onMapChunk(FlattenedChunkDataS2CPacket packet) { world.clearBlockResets(fromX, world.getBottomY(), fromZ, fromX + 15, world.getTopY() - 1, fromZ + 15); Chunk chunk = world.getChunk(packet.chunkX, packet.chunkZ); if (chunk instanceof FlattenedChunk flatteningChunk) { + if (flatteningChunk.blockIdCache != null) { + Arrays.fill(flatteningChunk.blockIdCache, (short) -1); + } ByteBuffer buf = ByteBuffer.wrap(packet.sectionsData); for (int i = 0; i < world.countVerticalSections(); i++) flatteningChunk.getOrCreateSection(world.sectionIndexToCoord(i) << 4, true).readDataPacket(buf); @@ -89,6 +93,9 @@ public void onChunkSection(FlattenedChunkSectionDataS2CPacket packet) { world.clearBlockResets(fromX, fromY, fromZ, fromX + 15, fromY + 15, fromZ + 15); Chunk chunk = world.getChunk(packet.chunkX, packet.chunkZ); if (chunk instanceof FlattenedChunk flatteningChunk) { + if (flatteningChunk.blockIdCache != null) { + Arrays.fill(flatteningChunk.blockIdCache, (short) -1); + } ByteBuffer buf = ByteBuffer.wrap(packet.sectionData); flatteningChunk.getOrCreateSection(fromY, true).readDataPacket(buf); } diff --git a/station-flattening-v0/src/main/java/net/modificationstation/stationapi/impl/world/chunk/ChunkSection.java b/station-flattening-v0/src/main/java/net/modificationstation/stationapi/impl/world/chunk/ChunkSection.java index efa244a69..a27baa3df 100644 --- a/station-flattening-v0/src/main/java/net/modificationstation/stationapi/impl/world/chunk/ChunkSection.java +++ b/station-flattening-v0/src/main/java/net/modificationstation/stationapi/impl/world/chunk/ChunkSection.java @@ -26,6 +26,10 @@ public class ChunkSection { private final NibbleArray skyLightArray = new NibbleArray(4096); private final NibbleArray blockLightArray = new NibbleArray(4096); + // Used for Block ID Cache + public int worldBottomY = 0; + public short[] blockIdCache = null; + public ChunkSection(int chunkPos, PalettedContainer blockStateContainer) { this.yOffset = (short) ChunkSection.blockCoordFromChunkCoord(chunkPos); this.blockStateContainer = blockStateContainer; @@ -50,6 +54,10 @@ public BlockState getBlockState(int x, int y, int z) { // } public BlockState setBlockState(int x, int y, int z, BlockState state) { + if (blockIdCache != null) { + blockIdCache[x | (z << 4) | ((y - worldBottomY) + this.yOffset << 8)] = -1; + } + BlockState blockState = this.blockStateContainer.swap(x, y, z, state); // FluidState fluidState = blockState2.getFluidState(); diff --git a/station-flattening-v0/src/main/java/net/modificationstation/stationapi/impl/world/chunk/FlattenedChunk.java b/station-flattening-v0/src/main/java/net/modificationstation/stationapi/impl/world/chunk/FlattenedChunk.java index 1f54408a4..05e83f28f 100644 --- a/station-flattening-v0/src/main/java/net/modificationstation/stationapi/impl/world/chunk/FlattenedChunk.java +++ b/station-flattening-v0/src/main/java/net/modificationstation/stationapi/impl/world/chunk/FlattenedChunk.java @@ -17,10 +17,12 @@ import net.modificationstation.stationapi.api.event.block.BlockEvent; import net.modificationstation.stationapi.api.event.world.BlockSetEvent; import net.modificationstation.stationapi.api.event.world.MetaSetEvent; +import net.modificationstation.stationapi.api.registry.BlockRegistry; import net.modificationstation.stationapi.api.util.math.MutableBlockPos; import net.modificationstation.stationapi.mixin.flattening.ChunkAccessor; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; public class FlattenedChunk extends Chunk { @@ -31,6 +33,14 @@ public class FlattenedChunk extends Chunk { public final short lastBlock; private final short[] stationHeightmap = new short[256]; + /** + * short cache will only be able to address 32767 IDs + * If the block registry next id is larger than that, it will be disabled + */ + private static final boolean canUseShortBlockIdCache = BlockRegistry.INSTANCE.getNextId() < 32767; + public final short[] blockIdCache; + public final int bottomY; + public FlattenedChunk(World world, int xPos, int zPos) { super(world, xPos, zPos); int countSections = world.countVerticalSections(); @@ -41,6 +51,14 @@ public FlattenedChunk(World world, int xPos, int zPos) { for(short i = 0; i < entities.length; i++) { this.entities[i] = new ArrayList<>(); } + + bottomY = world.getBottomY(); + if (canUseShortBlockIdCache) { + blockIdCache = new short[16 * 16 * world.getHeight()]; + Arrays.fill(blockIdCache, (short) -1); + } else { + blockIdCache = null; + } } public void fromLegacy(byte[] tiles) { @@ -99,10 +117,11 @@ public boolean isAboveMaxHeight(int relX, int y, int relZ) { return y >= getShortHeight(relX, relZ); } - private ChunkSection getSection(int y) { + protected ChunkSection getSection(int y) { if (y < firstBlock || y > lastBlock) { return null; } + return sections[world.sectionCoordToIndex(y >> 4)]; } @@ -129,6 +148,10 @@ public ChunkSection getOrCreateSection(int y, boolean fillSkyLight) { } sections[index] = section; } + + section.blockIdCache = blockIdCache; + section.worldBottomY = bottomY; + return section; } @@ -313,7 +336,24 @@ private void updateHeightMap(int x, int y, int z) { @Override public int getBlockId(int x, int y, int z) { - return getBlockState(x, y, z).getBlock().id; + if (blockIdCache == null) { + // TODO: Change to .block field access once various things gets merged + return getBlockState(x, y, z).getBlock().id; + } + + int key = x | (z << 4) | ((y - bottomY) << 8); + + if (key < 0 || key >= blockIdCache.length) { + System.err.println("x = " + x + ", y = " + y + ", z = " + z); + return 0; + } + + if (blockIdCache[key] == -1) { + // TODO: Change to .block field access once various things gets merged + blockIdCache[key] = (short) getBlockState(x, y, z).getBlock().id; + } + + return blockIdCache[key]; } @Override diff --git a/station-registry-api-v0/src/main/java/net/modificationstation/stationapi/api/registry/SimpleRegistry.java b/station-registry-api-v0/src/main/java/net/modificationstation/stationapi/api/registry/SimpleRegistry.java index 9b10d0855..902483296 100644 --- a/station-registry-api-v0/src/main/java/net/modificationstation/stationapi/api/registry/SimpleRegistry.java +++ b/station-registry-api-v0/src/main/java/net/modificationstation/stationapi/api/registry/SimpleRegistry.java @@ -327,6 +327,10 @@ public int size() { return this.keyToEntry.size(); } + public int getNextId() { + return this.nextId; + } + @Override public Lifecycle getEntryLifecycle(T entry) { return this.entryToLifecycle.get(entry);