From d68911ee3905c8912b6f6fbb039661abf56da7e4 Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Sun, 14 Nov 2021 01:44:39 +0100 Subject: [PATCH] Clean up code --- .../justmap/map/data/fast/MapChunk.java | 225 ++++++++---------- .../justmap/map/data/fast/MapRegionLayer.java | 4 +- 2 files changed, 105 insertions(+), 124 deletions(-) diff --git a/src/main/java/ru/bulldog/justmap/map/data/fast/MapChunk.java b/src/main/java/ru/bulldog/justmap/map/data/fast/MapChunk.java index d8603763..9cf16f21 100644 --- a/src/main/java/ru/bulldog/justmap/map/data/fast/MapChunk.java +++ b/src/main/java/ru/bulldog/justmap/map/data/fast/MapChunk.java @@ -13,10 +13,9 @@ import ru.bulldog.justmap.map.data.Layer; import ru.bulldog.justmap.util.BlockStateUtil; +import ru.bulldog.justmap.util.colors.ColorUtil; import ru.bulldog.justmap.util.colors.Colors; -import static ru.bulldog.justmap.util.colors.ColorUtil.ABGRtoARGB; - public class MapChunk { private final int relRegX; private final int relRegZ; @@ -24,15 +23,15 @@ public class MapChunk { private final int level; // Note that color data has a different layout than the scouted data - private final byte[][] colorData = new byte[MapRegionLayer.CHUNK_SIZE][MapRegionLayer.CHUNK_SIZE * MapRegionLayer.BYTES_PER_PIXEL]; + private final byte[][] pixelColors = new byte[MapRegionLayer.CHUNK_SIZE][MapRegionLayer.CHUNK_SIZE * MapRegionLayer.BYTES_PER_PIXEL]; - private final byte[][] solidY = new byte[MapRegionLayer.CHUNK_SIZE][MapRegionLayer.CHUNK_SIZE]; - private final byte[][] transparentY = new byte[MapRegionLayer.CHUNK_SIZE][MapRegionLayer.CHUNK_SIZE]; - private final byte[][] waterY = new byte[MapRegionLayer.CHUNK_SIZE][MapRegionLayer.CHUNK_SIZE]; - private final byte[][] delta = new byte[MapRegionLayer.CHUNK_SIZE][MapRegionLayer.CHUNK_SIZE]; + private final int[][] scoutedTransparentBlocks = new int[MapRegionLayer.CHUNK_SIZE][MapRegionLayer.CHUNK_SIZE]; + private final int[][] scoutedSolidBlocks = new int[MapRegionLayer.CHUNK_SIZE][MapRegionLayer.CHUNK_SIZE]; + private final byte[][] scoutedTransparentY = new byte[MapRegionLayer.CHUNK_SIZE][MapRegionLayer.CHUNK_SIZE]; + private final byte[][] scoutedWaterY = new byte[MapRegionLayer.CHUNK_SIZE][MapRegionLayer.CHUNK_SIZE]; + private final byte[][] scoutedSolidY = new byte[MapRegionLayer.CHUNK_SIZE][MapRegionLayer.CHUNK_SIZE]; - private final int[][] solidBlock = new int[MapRegionLayer.CHUNK_SIZE][MapRegionLayer.CHUNK_SIZE]; - private final int[][] transparentBlock = new int[MapRegionLayer.CHUNK_SIZE][MapRegionLayer.CHUNK_SIZE]; + private final byte[][] derivedDeltaY = new byte[MapRegionLayer.CHUNK_SIZE][MapRegionLayer.CHUNK_SIZE]; public MapChunk(int relRegX, int relRegZ, Layer layer, int level) { this.relRegX = relRegX; @@ -41,89 +40,117 @@ public MapChunk(int relRegX, int relRegZ, Layer layer, int level) { this.level = level; } - private void examinePos(World world, WorldChunk worldChunk, BlockPos.Mutable thisBlockPos) { - int posX = thisBlockPos.getX(); - int posZ = thisBlockPos.getZ(); + private int getTopBlockYInLeveledLayer(WorldChunk worldChunk, int posX, int posZ, boolean hideWater, boolean hidePlants) { + int floor = layer.getHeight() * level; + int ceiling = layer.getHeight() * (level + 1); + int y = ceiling; + BlockPos.Mutable pos = new BlockPos.Mutable(); + pos.set(posX, y, posZ); + boolean caveFound; + do { + if (y < floor) { + return -1; + } + caveFound = BlockStateUtil.isSkippedBlockState(worldChunk.getBlockState(pos), !hideWater, !hidePlants); + y--; + pos.set(posX, y, posZ); + } while (!caveFound); + + boolean bottomFound; + do { + if (y < 0) { + return -1; + } + bottomFound = !BlockStateUtil.isSkippedBlockState(worldChunk.getBlockState(pos), !hideWater, !hidePlants); + y--; + pos.set(posX, y, posZ); + } while (!bottomFound); + + // We overstepped by one + return y+1; + } + + private void updateScoutedData(World world, WorldChunk worldChunk, BlockPos.Mutable pos) { + int xOffset = pos.getX() & 15; + int zOffset = pos.getZ() & 15; // Get the highest non-air block - int y = worldChunk.sampleHeightmap(Heightmap.Type.WORLD_SURFACE, posX, posZ); - - int solid_y = -1; - int transparent_y = -1; - int water_y = -1; - BlockState solid_block = BlockStateUtil.AIR; - BlockState transparent_block = BlockStateUtil.AIR; - while (solid_y < 0) { - thisBlockPos.setY(y); - BlockState blockState = worldChunk.getBlockState(thisBlockPos); - if (water_y < 0 && + int y = worldChunk.sampleHeightmap(Heightmap.Type.WORLD_SURFACE, xOffset, zOffset); + + int solidY = -1; + int transparentY = -1; + int waterY = -1; + BlockState solidBlock = BlockStateUtil.AIR; + BlockState transparentBlock = BlockStateUtil.AIR; + while (solidY < 0) { + pos.setY(y); + BlockState blockState = worldChunk.getBlockState(pos); + if (waterY < 0 && (!blockState.getFluidState().isEmpty() && blockState.getFluidState().isIn(FluidTags.WATER))) { - water_y = y; + waterY = y; } - if (transparent_y < 0 && - blockState.getMapColor(world, thisBlockPos) == MapColor.CLEAR) { - transparent_y = y; - transparent_block = blockState; + if (transparentY < 0 && + blockState.getMapColor(world, pos) == MapColor.CLEAR) { + transparentY = y; + transparentBlock = blockState; } - if (blockState.getMapColor(world, thisBlockPos) != MapColor.CLEAR + if (blockState.getMapColor(world, pos) != MapColor.CLEAR && blockState.getFluidState().isEmpty() && !blockState.getFluidState().isIn(FluidTags.WATER)) { - solid_y = y; - solid_block = blockState; + solidY = y; + solidBlock = blockState; } y--; if (y < 0) { // got just void - solid_y = 0; - solid_block = BlockStateUtil.AIR; + solidY = 0; + solidBlock = BlockStateUtil.AIR; } } - int xOffset = posX & 15; - int zOffset = posZ & 15; - solidY[xOffset][zOffset] = (byte) solid_y; - transparentY[xOffset][zOffset] = (byte) transparent_y; - waterY[xOffset][zOffset] = (byte) water_y; + scoutedSolidY[xOffset][zOffset] = (byte) solidY; + scoutedTransparentY[xOffset][zOffset] = (byte) transparentY; + scoutedWaterY[xOffset][zOffset] = (byte) waterY; - solidBlock[xOffset][zOffset] = Block.getRawIdFromState(solid_block); - transparentBlock[xOffset][zOffset] = Block.getRawIdFromState(transparent_block); + scoutedSolidBlocks[xOffset][zOffset] = Block.getRawIdFromState(solidBlock); + scoutedTransparentBlocks[xOffset][zOffset] = Block.getRawIdFromState(transparentBlock); } - private void calculateDelta(World world, WorldChunk worldChunk, int xOffset, int zOffset) { - int solid_y = solidY[xOffset][zOffset]; + private void updateDerivedData(World world, WorldChunk worldChunk, int xOffset, int zOffset) { + int solidY = scoutedSolidY[xOffset][zOffset]; // For terrain, Vanilla calculate shading according to height difference // with north (z-1) neighbor // FIXME: this breaks at chunk border! - int north_solid_y; + int northSolidY; if (zOffset > 0) { - north_solid_y = solidY[xOffset][zOffset - 1]; + northSolidY = scoutedSolidY[xOffset][zOffset - 1]; } else { // FIXME: fake! use our own height - north_solid_y = solidY[xOffset][zOffset]; + northSolidY = scoutedSolidY[xOffset][zOffset]; } - int my_delta = solid_y - north_solid_y; - delta[xOffset][zOffset] = (byte) my_delta; + int my_delta = solidY - northSolidY; + derivedDeltaY[xOffset][zOffset] = (byte) my_delta; } - private int blockColorChunkFromCache(int xOffset, int zOffset) { - int solid_y = solidY[xOffset][zOffset]; - int transparent_y = transparentY[xOffset][zOffset]; - int water_y = waterY[xOffset][zOffset]; - int y_delta = delta[xOffset][zOffset]; + private int getVanillaPixelColor(int xOffset, int zOffset) { + int solidY = scoutedSolidY[xOffset][zOffset]; + int transparentY = scoutedTransparentY[xOffset][zOffset]; + int waterY = scoutedWaterY[xOffset][zOffset]; + int deltaY = derivedDeltaY[xOffset][zOffset]; - BlockState solid_block = Block.getStateFromRawId(solidBlock[xOffset][zOffset]); - BlockState transparent_block = Block.getStateFromRawId(transparentBlock[xOffset][zOffset]); + BlockState solidBlock = Block.getStateFromRawId(scoutedSolidBlocks[xOffset][zOffset]); + BlockState transparentBlock = Block.getStateFromRawId(scoutedTransparentBlocks[xOffset][zOffset]); int shade = 0; MapColor mapColor; - if (water_y > solid_y) { + if (waterY > solidY) { // For water, calculate shading according to depth - int waterDepth = water_y - solid_y; + int waterDepth = waterY - solidY; double shadeArg = waterDepth * 0.1d + (xOffset + zOffset & 1) * 0.2d; if (shadeArg < 0.5d) { shade = 2; @@ -136,7 +163,7 @@ private int blockColorChunkFromCache(int xOffset, int zOffset) { } else { // For terrain, calculate shading according to height difference // with neighbor - double shadeArg = y_delta * 4/5.0d + ((xOffset + zOffset & 1) - 0.5d) * 0.4d; + double shadeArg = deltaY * 4/5.0d + ((xOffset + zOffset & 1) - 0.5d) * 0.4d; if (shadeArg > 0.6d) { shade = 2; } else if (shadeArg < -0.6d) { @@ -148,7 +175,7 @@ private int blockColorChunkFromCache(int xOffset, int zOffset) { // We're taking a bit of a chance here. In practice, the // implementation of getMapColor() ignores its arguments, but // that might change in the future - mapColor = solid_block.getMapColor(null, null); + mapColor = solidBlock.getMapColor(null, null); } catch (NullPointerException e) { mapColor = MapColor.CLEAR; } @@ -157,53 +184,21 @@ private int blockColorChunkFromCache(int xOffset, int zOffset) { if (mapColor == MapColor.CLEAR) { return Colors.BLACK; } else { - return ABGRtoARGB(MapColor.COLORS[mapColor.id].getRenderColor(shade)); + return ColorUtil.ABGRtoARGB(MapColor.COLORS[mapColor.id].getRenderColor(shade)); } } - private int getTopBlockY(WorldChunk worldChunk, int x, int z) { - if (layer == Layer.SURFACE) { - return getTopBlockYOnSurface(worldChunk, x, z); - } else { - return getTopBlockYInLeveledLayer(worldChunk, x, z, false, true); - } - } - - private int getTopBlockYOnSurface(WorldChunk worldChunk, int x, int z) { - return worldChunk.sampleHeightmap(Heightmap.Type.WORLD_SURFACE, x, z); - } - - private int getTopBlockYInLeveledLayer(WorldChunk worldChunk, int posX, int posZ, boolean hideWater, boolean hidePlants) { - int floor = layer.getHeight() * level; - int ceiling = layer.getHeight() * (level + 1); - int y = ceiling; - BlockPos.Mutable pos = new BlockPos.Mutable(); - pos.set(posX, y, posZ); - boolean caveFound; - do { - if (y < floor) { - return -1; - } - caveFound = BlockStateUtil.isSkippedBlockState(worldChunk.getBlockState(pos), !hideWater, !hidePlants); - y--; - pos.set(posX, y, posZ); - } while (!caveFound); - - boolean bottomFound; - do { - if (y < 0) { - return -1; - } - bottomFound = !BlockStateUtil.isSkippedBlockState(worldChunk.getBlockState(pos), !hideWater, !hidePlants); - y--; - pos.set(posX, y, posZ); - } while (!bottomFound); + private void updatePixelColor(int x, int z) { + int color = getVanillaPixelColor(x, z); - // We overstepped by one - return y+1; + int xOffset = x * 4; + pixelColors[z][xOffset + 0] = (byte) 0; + pixelColors[z][xOffset + 1] = (byte) (color & 255); + pixelColors[z][xOffset + 2] = (byte) ((color >> 8) & 255); + pixelColors[z][xOffset + 3] = (byte) ((color >> 16) & 255); } - public void updateChunk(WorldChunk worldChunk) { + public void onChunkUpdate(WorldChunk worldChunk) { World world = FastMapManager.MANAGER.getFastWorldMapper().getWorld(); BlockPos.Mutable blockPos = new BlockPos.Mutable(); @@ -211,39 +206,32 @@ public void updateChunk(WorldChunk worldChunk) { blockPos.setX(worldChunk.getPos().getStartX() + x); for (int z = 0; z < MapRegionLayer.CHUNK_SIZE; z++) { blockPos.setZ(worldChunk.getPos().getStartZ() + z); - examinePos(world, worldChunk, blockPos); + updateScoutedData(world, worldChunk, blockPos); } } for (int x = 0; x < MapRegionLayer.CHUNK_SIZE; x++) { for (int z = 0; z < MapRegionLayer.CHUNK_SIZE; z++) { - calculateDelta(world, worldChunk, x, z); - } - } - - for (int x = 0; x < MapRegionLayer.CHUNK_SIZE; x++) { - for (int z = 0; z < MapRegionLayer.CHUNK_SIZE; z++) { - int color = blockColorChunkFromCache(x, z); - setColor(x, z, color); + updateDerivedData(world, worldChunk, x, z); + updatePixelColor(x, z); } } } - public void updateBlock(BlockPos blockPos) { + public void onBlockUpdate(BlockPos blockPos) { int x = blockPos.getX() & 15; int z = blockPos.getZ() & 15; - int relevantY = solidY[x][z]; + int relevantY = scoutedSolidY[x][z]; if (blockPos.getY() >= relevantY) { // Only look at changes to blocks that could possibly affect the map BlockPos.Mutable pos = new BlockPos.Mutable(); pos.set(blockPos); World world = FastMapManager.MANAGER.getFastWorldMapper().getWorld(); WorldChunk worldChunk = world.getWorldChunk(pos); - examinePos(world, worldChunk, pos); - calculateDelta(world, worldChunk, x, z); + updateScoutedData(world, worldChunk, pos); + updateDerivedData(world, worldChunk, x, z); // FIXME: We also need to calculate delta on it's neighbor! - int color = blockColorChunkFromCache(x, z); - setColor(x, z, color); + updatePixelColor(x, z); } } @@ -252,16 +240,9 @@ public void writeToTextureBuffer(ByteBuffer buffer) { buffer.put((relRegZ * MapRegionLayer.CHUNK_SIZE + row) * MapRegionLayer.REGION_SIZE * MapRegionLayer.BYTES_PER_PIXEL + (relRegX * MapRegionLayer.CHUNK_SIZE * MapRegionLayer.BYTES_PER_PIXEL), - colorData[row], 0, + pixelColors[row], 0, MapRegionLayer.CHUNK_SIZE * MapRegionLayer.BYTES_PER_PIXEL); } } - private void setColor(int x, int z, int color) { - int xOffset = x * 4; - colorData[z][xOffset + 0] = (byte) 0; - colorData[z][xOffset + 1] = (byte) (color & 255); - colorData[z][xOffset + 2] = (byte) ((color >> 8) & 255); - colorData[z][xOffset + 3] = (byte) ((color >> 16) & 255); - } } diff --git a/src/main/java/ru/bulldog/justmap/map/data/fast/MapRegionLayer.java b/src/main/java/ru/bulldog/justmap/map/data/fast/MapRegionLayer.java index 90fb6c73..e7837d03 100644 --- a/src/main/java/ru/bulldog/justmap/map/data/fast/MapRegionLayer.java +++ b/src/main/java/ru/bulldog/justmap/map/data/fast/MapRegionLayer.java @@ -41,7 +41,7 @@ public void updateChunk(WorldChunk worldChunk) { // FIXME: verify/assert that chunkpos is inside region? MapChunk mapChunk = getMapChunk(worldChunk.getPos()); - mapChunk.updateChunk(worldChunk); + mapChunk.onChunkUpdate(worldChunk); mapChunk.writeToTextureBuffer(buffer); isModified = true; } @@ -50,7 +50,7 @@ public void updateBlock(BlockPos pos) { ChunkPos chunkPos = new ChunkPos(pos); MapChunk mapChunk = getMapChunk(chunkPos); - mapChunk.updateBlock(pos); + mapChunk.onBlockUpdate(pos); mapChunk.writeToTextureBuffer(buffer); isModified = true; }