rework chunk caching

This commit is contained in:
Leijurv 2018-08-22 11:41:31 -07:00
parent 56975c0e0f
commit 38aad9d92c
No known key found for this signature in database
GPG Key ID: 44A3EA646EADAC6A
4 changed files with 78 additions and 53 deletions

View File

@ -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;
}
/**

View File

@ -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();
}

View File

@ -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();

View File

@ -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;
}