rework chunk caching
This commit is contained in:
parent
56975c0e0f
commit
38aad9d92c
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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]);
|
||||
}
|
||||
@ -71,20 +70,24 @@ public final class ChunkPacker implements Helper {
|
||||
IBlockState blockState = chunk.getBlockState(x, height, z);
|
||||
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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user