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
|
* The chunk x coordinate
|
||||||
*/
|
*/
|
||||||
private final int x;
|
public final int x;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The chunk z coordinate
|
* The chunk z coordinate
|
||||||
*/
|
*/
|
||||||
private final int z;
|
public final int z;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The actual raw data of this packed chunk.
|
* The actual raw data of this packed chunk.
|
||||||
@ -62,6 +62,8 @@ public final class CachedChunk implements IBlockTypeAccess {
|
|||||||
*/
|
*/
|
||||||
private final String[] overview;
|
private final String[] overview;
|
||||||
|
|
||||||
|
private final int[] heightMap;
|
||||||
|
|
||||||
CachedChunk(int x, int z, BitSet data, String[] overview) {
|
CachedChunk(int x, int z, BitSet data, String[] overview) {
|
||||||
validateSize(data);
|
validateSize(data);
|
||||||
|
|
||||||
@ -69,6 +71,8 @@ public final class CachedChunk implements IBlockTypeAccess {
|
|||||||
this.z = z;
|
this.z = z;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.overview = overview;
|
this.overview = overview;
|
||||||
|
this.heightMap = new int[256];
|
||||||
|
calculateHeightMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -77,25 +81,22 @@ public final class CachedChunk implements IBlockTypeAccess {
|
|||||||
return PathingBlockType.fromBits(data.get(index), data.get(index + 1));
|
return PathingBlockType.fromBits(data.get(index), data.get(index + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateContents(BitSet data) {
|
private void calculateHeightMap() {
|
||||||
validateSize(data);
|
for (int z = 0; z < 16; z++) {
|
||||||
|
for (int x = 0; x < 16; x++) {
|
||||||
for (int i = 0; i < data.length(); i++)
|
int index = z << 4 | x;
|
||||||
this.data.set(i, data.get(i));
|
heightMap[index] = 0;
|
||||||
|
for (int y = 256; y >= 0; y--) {
|
||||||
|
if (getBlockType(x, y, z) != PathingBlockType.AIR) {
|
||||||
|
heightMap[index] = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public final String[] getOverview() {
|
||||||
* @return Thee chunk x coordinat
|
return overview;
|
||||||
*/
|
|
||||||
public final int getX() {
|
|
||||||
return this.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The chunk z coordinate
|
|
||||||
*/
|
|
||||||
public final int getZ() {
|
|
||||||
return this.z;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,6 +24,7 @@ import java.io.*;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.zip.GZIPInputStream;
|
import java.util.zip.GZIPInputStream;
|
||||||
@ -77,13 +78,8 @@ public final class CachedRegion implements IBlockTypeAccess {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final void updateCachedChunk(int chunkX, int chunkZ, BitSet chunkData, String[] chunkOverview) {
|
final void updateCachedChunk(int chunkX, int chunkZ, CachedChunk chunk) {
|
||||||
CachedChunk chunk = this.getChunk(chunkX, chunkZ);
|
this.chunks[chunkX][chunkZ] = chunk;
|
||||||
if (chunk == null) {
|
|
||||||
this.chunks[chunkX][chunkZ] = new CachedChunk(chunkX, chunkZ, chunkData, chunkOverview);
|
|
||||||
} else {
|
|
||||||
chunk.updateContents(chunkData);
|
|
||||||
}
|
|
||||||
hasUnsavedChanges = true;
|
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);
|
out.writeInt(~CACHED_REGION_MAGIC);
|
||||||
}
|
}
|
||||||
hasUnsavedChanges = false;
|
hasUnsavedChanges = false;
|
||||||
@ -155,6 +160,7 @@ public final class CachedRegion implements IBlockTypeAccess {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
System.out.println("Loading region " + x + "," + z + " from disk " + path);
|
System.out.println("Loading region " + x + "," + z + " from disk " + path);
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
|
||||||
try (
|
try (
|
||||||
FileInputStream fileIn = new FileInputStream(regionFile.toFile());
|
FileInputStream fileIn = new FileInputStream(regionFile.toFile());
|
||||||
@ -175,12 +181,7 @@ public final class CachedRegion implements IBlockTypeAccess {
|
|||||||
case CHUNK_PRESENT:
|
case CHUNK_PRESENT:
|
||||||
byte[] bytes = new byte[CachedChunk.SIZE_IN_BYTES];
|
byte[] bytes = new byte[CachedChunk.SIZE_IN_BYTES];
|
||||||
in.readFully(bytes);
|
in.readFully(bytes);
|
||||||
BitSet bits = BitSet.valueOf(bytes);
|
this.chunks[x][z] = new CachedChunk(x, z, BitSet.valueOf(bytes), new String[256]);
|
||||||
String[] overview = new String[256];
|
|
||||||
for(int i = 0; i < 256; i++) {
|
|
||||||
overview[i] = in.readUTF();
|
|
||||||
}
|
|
||||||
updateCachedChunk(x, z, bits, overview);
|
|
||||||
break;
|
break;
|
||||||
case CHUNK_NOT_PRESENT:
|
case CHUNK_NOT_PRESENT:
|
||||||
this.chunks[x][z] = null;
|
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();
|
int fileEndMagic = in.readInt();
|
||||||
if (fileEndMagic != ~magic) {
|
if (fileEndMagic != ~magic) {
|
||||||
throw new IOException("Bad end of file magic");
|
throw new IOException("Bad end of file magic");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hasUnsavedChanges = false;
|
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) {
|
} catch (IOException ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -67,13 +67,17 @@ public final class CachedWorld implements IBlockTypeAccess {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final PathingBlockType getBlockType(int x, int y, int z) {
|
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);
|
return region.getBlockType(x & 511, y, z & 511);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateCachedChunk(int chunkX, int chunkZ, BitSet data) {
|
private void updateCachedChunk(CachedChunk chunk) {
|
||||||
CachedRegion region = getOrCreateRegion(chunkX >> 5, chunkZ >> 5);
|
CachedRegion region = getOrCreateRegion(chunk.x >> 5, chunk.z >> 5);
|
||||||
region.updateCachedChunk(chunkX & 31, chunkZ & 31, data, );
|
region.updateCachedChunk(chunk.x & 31, chunk.z & 31, chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void save() {
|
public final void save() {
|
||||||
@ -105,7 +109,7 @@ public final class CachedWorld implements IBlockTypeAccess {
|
|||||||
* @param regionZ The region Z coordinate
|
* @param regionZ The region Z coordinate
|
||||||
* @return The region located at the specified coordinates
|
* @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 -> {
|
return cachedRegions.computeIfAbsent(getRegionID(regionX, regionZ), id -> {
|
||||||
CachedRegion newRegion = new CachedRegion(regionX, regionZ);
|
CachedRegion newRegion = new CachedRegion(regionX, regionZ);
|
||||||
newRegion.load(this.directory);
|
newRegion.load(this.directory);
|
||||||
@ -157,7 +161,8 @@ public final class CachedWorld implements IBlockTypeAccess {
|
|||||||
Chunk chunk = queue.take();
|
Chunk chunk = queue.take();
|
||||||
BitSet packedChunk = ChunkPacker.createPackedChunk(chunk);
|
BitSet packedChunk = ChunkPacker.createPackedChunk(chunk);
|
||||||
String[] packedOverview = ChunkPacker.createPackedOverview(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);
|
//System.out.println("Processed chunk at " + chunk.x + "," + chunk.z);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -20,14 +20,13 @@ package baritone.bot.chunk;
|
|||||||
import baritone.bot.pathing.movement.MovementHelper;
|
import baritone.bot.pathing.movement.MovementHelper;
|
||||||
import baritone.bot.utils.BlockStateInterface;
|
import baritone.bot.utils.BlockStateInterface;
|
||||||
import baritone.bot.utils.Helper;
|
import baritone.bot.utils.Helper;
|
||||||
import baritone.bot.utils.pathing.BetterBlockPos;
|
|
||||||
import baritone.bot.utils.pathing.PathingBlockType;
|
import baritone.bot.utils.pathing.PathingBlockType;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockAir;
|
import net.minecraft.block.BlockAir;
|
||||||
|
import net.minecraft.block.BlockDoublePlant;
|
||||||
|
import net.minecraft.block.BlockTallGrass;
|
||||||
import net.minecraft.block.state.IBlockState;
|
import net.minecraft.block.state.IBlockState;
|
||||||
import net.minecraft.init.Blocks;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.util.math.BlockPos;
|
|
||||||
import net.minecraft.util.math.BlockPos.MutableBlockPos;
|
|
||||||
import net.minecraft.world.chunk.Chunk;
|
import net.minecraft.world.chunk.Chunk;
|
||||||
|
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
@ -48,7 +47,7 @@ public final class ChunkPacker implements Helper {
|
|||||||
for (int z = 0; z < 16; z++) {
|
for (int z = 0; z < 16; z++) {
|
||||||
for (int x = 0; x < 16; x++) {
|
for (int x = 0; x < 16; x++) {
|
||||||
int index = CachedChunk.getPositionIndex(x, y, z);
|
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, bits[0]);
|
||||||
bitSet.set(index + 1, bits[1]);
|
bitSet.set(index + 1, bits[1]);
|
||||||
}
|
}
|
||||||
@ -65,26 +64,30 @@ public final class ChunkPacker implements Helper {
|
|||||||
public static String[] createPackedOverview(Chunk chunk) {
|
public static String[] createPackedOverview(Chunk chunk) {
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
String[] blockNames = new String[256];
|
String[] blockNames = new String[256];
|
||||||
for(int z = 0; z < 16; z++) {
|
for (int z = 0; z < 16; z++) {
|
||||||
for(int x = 0; x < 16; x++) {
|
for (int x = 0; x < 16; x++) {
|
||||||
int height = chunk.getHeightValue(x, z);
|
int height = chunk.getHeightValue(x, z);
|
||||||
IBlockState blockState = chunk.getBlockState(x, height, 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);
|
blockState = chunk.getBlockState(x, y, z);
|
||||||
if(blockState.getBlock() != Blocks.AIR) {
|
if (getPathingBlockType(blockState.getBlock()) != PathingBlockType.AIR) {
|
||||||
break;
|
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();
|
long end = System.currentTimeMillis();
|
||||||
return blockNames;
|
return blockNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PathingBlockType getPathingBlockType(BlockPos pos, IBlockState state) {
|
private static PathingBlockType getPathingBlockType(Block block) {
|
||||||
Block block = state.getBlock();
|
|
||||||
|
|
||||||
if (BlockStateInterface.isWater(block)) {
|
if (BlockStateInterface.isWater(block)) {
|
||||||
return PathingBlockType.WATER;
|
return PathingBlockType.WATER;
|
||||||
}
|
}
|
||||||
@ -93,7 +96,11 @@ public final class ChunkPacker implements Helper {
|
|||||||
return PathingBlockType.AVOID;
|
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;
|
return PathingBlockType.AIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user