diff --git a/src/main/java/baritone/bot/chunk/CachedChunk.java b/src/main/java/baritone/bot/chunk/CachedChunk.java index e9f98873..c5b13e03 100644 --- a/src/main/java/baritone/bot/chunk/CachedChunk.java +++ b/src/main/java/baritone/bot/chunk/CachedChunk.java @@ -43,12 +43,12 @@ public final class CachedChunk implements IBlockTypeAccess { /** * The chunk x coordinate */ - private final int x; + public final int x; /** * The chunk z coordinate */ - private final int z; + public final int z; /** * The actual raw data of this packed chunk. @@ -62,6 +62,8 @@ public final class CachedChunk implements IBlockTypeAccess { */ private final String[] overview; + private final int[] heightMap; + CachedChunk(int x, int z, BitSet data, String[] overview) { validateSize(data); @@ -69,6 +71,8 @@ public final class CachedChunk implements IBlockTypeAccess { this.z = z; this.data = data; this.overview = overview; + this.heightMap = new int[256]; + calculateHeightMap(); } @Override @@ -77,25 +81,22 @@ public final class CachedChunk implements IBlockTypeAccess { return PathingBlockType.fromBits(data.get(index), data.get(index + 1)); } - void updateContents(BitSet data) { - validateSize(data); - - for (int i = 0; i < data.length(); i++) - this.data.set(i, data.get(i)); + private void calculateHeightMap() { + for (int z = 0; z < 16; z++) { + for (int x = 0; x < 16; x++) { + int index = z << 4 | x; + heightMap[index] = 0; + for (int y = 256; y >= 0; y--) { + if (getBlockType(x, y, z) != PathingBlockType.AIR) { + heightMap[index] = y; + } + } + } + } } - /** - * @return Thee chunk x coordinat - */ - public final int getX() { - return this.x; - } - - /** - * @return The chunk z coordinate - */ - public final int getZ() { - return this.z; + public final String[] getOverview() { + return overview; } /** diff --git a/src/main/java/baritone/bot/chunk/CachedRegion.java b/src/main/java/baritone/bot/chunk/CachedRegion.java index 2c220e85..dbed63c6 100644 --- a/src/main/java/baritone/bot/chunk/CachedRegion.java +++ b/src/main/java/baritone/bot/chunk/CachedRegion.java @@ -24,6 +24,7 @@ import java.io.*; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Arrays; import java.util.BitSet; import java.util.function.Consumer; import java.util.zip.GZIPInputStream; @@ -77,13 +78,8 @@ public final class CachedRegion implements IBlockTypeAccess { return null; } - final void updateCachedChunk(int chunkX, int chunkZ, BitSet chunkData, String[] chunkOverview) { - CachedChunk chunk = this.getChunk(chunkX, chunkZ); - if (chunk == null) { - this.chunks[chunkX][chunkZ] = new CachedChunk(chunkX, chunkZ, chunkData, chunkOverview); - } else { - chunk.updateContents(chunkData); - } + final void updateCachedChunk(int chunkX, int chunkZ, CachedChunk chunk) { + this.chunks[chunkX][chunkZ] = chunk; hasUnsavedChanges = true; } @@ -135,6 +131,15 @@ public final class CachedRegion implements IBlockTypeAccess { } } } + for (int z = 0; z < 32; z++) { + for (int x = 0; x < 32; x++) { + if (chunks[x][z] != null) { + for (int i = 0; i < 256; i++) { + out.writeUTF(chunks[x][z].getOverview()[i]); + } + } + } + } out.writeInt(~CACHED_REGION_MAGIC); } hasUnsavedChanges = false; @@ -155,6 +160,7 @@ public final class CachedRegion implements IBlockTypeAccess { return; System.out.println("Loading region " + x + "," + z + " from disk " + path); + long start = System.currentTimeMillis(); try ( FileInputStream fileIn = new FileInputStream(regionFile.toFile()); @@ -175,12 +181,7 @@ public final class CachedRegion implements IBlockTypeAccess { case CHUNK_PRESENT: byte[] bytes = new byte[CachedChunk.SIZE_IN_BYTES]; in.readFully(bytes); - BitSet bits = BitSet.valueOf(bytes); - String[] overview = new String[256]; - for(int i = 0; i < 256; i++) { - overview[i] = in.readUTF(); - } - updateCachedChunk(x, z, bits, overview); + this.chunks[x][z] = new CachedChunk(x, z, BitSet.valueOf(bytes), new String[256]); break; case CHUNK_NOT_PRESENT: this.chunks[x][z] = null; @@ -190,13 +191,24 @@ public final class CachedRegion implements IBlockTypeAccess { } } } + for (int z = 0; z < 32; z++) { + for (int x = 0; x < 32; x++) { + if (chunks[x][z] != null) { + for (int i = 0; i < 256; i++) { + chunks[x][z].getOverview()[i] = in.readUTF(); + } + System.out.println(Arrays.asList(chunks[x][z].getOverview())); + } + } + } int fileEndMagic = in.readInt(); if (fileEndMagic != ~magic) { throw new IOException("Bad end of file magic"); } } hasUnsavedChanges = false; - System.out.println("Loaded region successfully"); + long end = System.currentTimeMillis(); + System.out.println("Loaded region successfully in " + (end - start) + "ms"); } catch (IOException ex) { ex.printStackTrace(); } diff --git a/src/main/java/baritone/bot/chunk/CachedWorld.java b/src/main/java/baritone/bot/chunk/CachedWorld.java index 670cd38c..51005288 100644 --- a/src/main/java/baritone/bot/chunk/CachedWorld.java +++ b/src/main/java/baritone/bot/chunk/CachedWorld.java @@ -67,13 +67,17 @@ public final class CachedWorld implements IBlockTypeAccess { @Override public final PathingBlockType getBlockType(int x, int y, int z) { - CachedRegion region = getOrCreateRegion(x >> 9, z >> 9); + // no point in doing getOrCreate region, if we don't have it we don't have it + CachedRegion region = getRegion(x >> 9, z >> 9); + if (region == null) { + return null; + } return region.getBlockType(x & 511, y, z & 511); } - private void updateCachedChunk(int chunkX, int chunkZ, BitSet data) { - CachedRegion region = getOrCreateRegion(chunkX >> 5, chunkZ >> 5); - region.updateCachedChunk(chunkX & 31, chunkZ & 31, data, ); + private void updateCachedChunk(CachedChunk chunk) { + CachedRegion region = getOrCreateRegion(chunk.x >> 5, chunk.z >> 5); + region.updateCachedChunk(chunk.x & 31, chunk.z & 31, chunk); } public final void save() { @@ -105,7 +109,7 @@ public final class CachedWorld implements IBlockTypeAccess { * @param regionZ The region Z coordinate * @return The region located at the specified coordinates */ - CachedRegion getOrCreateRegion(int regionX, int regionZ) { + private CachedRegion getOrCreateRegion(int regionX, int regionZ) { return cachedRegions.computeIfAbsent(getRegionID(regionX, regionZ), id -> { CachedRegion newRegion = new CachedRegion(regionX, regionZ); newRegion.load(this.directory); @@ -157,7 +161,8 @@ public final class CachedWorld implements IBlockTypeAccess { Chunk chunk = queue.take(); BitSet packedChunk = ChunkPacker.createPackedChunk(chunk); String[] packedOverview = ChunkPacker.createPackedOverview(chunk); - CachedWorld.this.updateCachedChunk(chunk.x, chunk.z, packedChunk); + CachedChunk cached = new CachedChunk(chunk.x, chunk.z, packedChunk, packedOverview); + CachedWorld.this.updateCachedChunk(cached); //System.out.println("Processed chunk at " + chunk.x + "," + chunk.z); } catch (InterruptedException e) { e.printStackTrace(); diff --git a/src/main/java/baritone/bot/chunk/ChunkPacker.java b/src/main/java/baritone/bot/chunk/ChunkPacker.java index d2fd5d6e..d454436c 100644 --- a/src/main/java/baritone/bot/chunk/ChunkPacker.java +++ b/src/main/java/baritone/bot/chunk/ChunkPacker.java @@ -20,14 +20,13 @@ package baritone.bot.chunk; import baritone.bot.pathing.movement.MovementHelper; import baritone.bot.utils.BlockStateInterface; import baritone.bot.utils.Helper; -import baritone.bot.utils.pathing.BetterBlockPos; import baritone.bot.utils.pathing.PathingBlockType; import net.minecraft.block.Block; import net.minecraft.block.BlockAir; +import net.minecraft.block.BlockDoublePlant; +import net.minecraft.block.BlockTallGrass; import net.minecraft.block.state.IBlockState; -import net.minecraft.init.Blocks; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.BlockPos.MutableBlockPos; +import net.minecraft.util.ResourceLocation; import net.minecraft.world.chunk.Chunk; import java.util.BitSet; @@ -48,7 +47,7 @@ public final class ChunkPacker implements Helper { for (int z = 0; z < 16; z++) { for (int x = 0; x < 16; x++) { int index = CachedChunk.getPositionIndex(x, y, z); - boolean[] bits = getPathingBlockType(new BlockPos(x, y, z), chunk.getBlockState(x, y, z)).getBits(); + boolean[] bits = getPathingBlockType(chunk.getBlockState(x, y, z).getBlock()).getBits(); bitSet.set(index, bits[0]); bitSet.set(index + 1, bits[1]); } @@ -65,26 +64,30 @@ public final class ChunkPacker implements Helper { public static String[] createPackedOverview(Chunk chunk) { long start = System.currentTimeMillis(); String[] blockNames = new String[256]; - for(int z = 0; z < 16; z++) { - for(int x = 0; x < 16; x++) { + for (int z = 0; z < 16; z++) { + for (int x = 0; x < 16; x++) { int height = chunk.getHeightValue(x, z); IBlockState blockState = chunk.getBlockState(x, height, z); - for(int y = height; y > 0; y--) { + for (int y = height; y > 0; y--) { blockState = chunk.getBlockState(x, y, z); - if(blockState.getBlock() != Blocks.AIR) { + if (getPathingBlockType(blockState.getBlock()) != PathingBlockType.AIR) { break; } } - blockNames[z << 4 | x] = blockState.getBlock().getLocalizedName(); + ResourceLocation loc = Block.REGISTRY.getNameForObject(blockState.getBlock()); + String name = loc.getPath(); // normally, only write the part after the minecraft: + if (!loc.getNamespace().equals("minecraft")) { + // Baritone is running on top of forge with mods installed, perhaps? + name = loc.toString(); // include the namespace with the colon + } + blockNames[z << 4 | x] = name; } } long end = System.currentTimeMillis(); return blockNames; } - private static PathingBlockType getPathingBlockType(BlockPos pos, IBlockState state) { - Block block = state.getBlock(); - + private static PathingBlockType getPathingBlockType(Block block) { if (BlockStateInterface.isWater(block)) { return PathingBlockType.WATER; } @@ -93,7 +96,11 @@ public final class ChunkPacker implements Helper { return PathingBlockType.AVOID; } - if (block instanceof BlockAir) { + // We used to do an AABB check here + // however, this failed in the nether when you were near a nether fortress + // because fences check their adjacent blocks in the world for their fence connection status to determine AABB shape + // this caused a nullpointerexception when we saved chunks on unload, because they were unable to check their neighbors + if (block instanceof BlockAir || block instanceof BlockTallGrass || block instanceof BlockDoublePlant) { return PathingBlockType.AIR; }