diff --git a/src/main/java/baritone/cache/CachedChunk.java b/src/main/java/baritone/cache/CachedChunk.java
index 56485fd72..bbc713af7 100644
--- a/src/main/java/baritone/cache/CachedChunk.java
+++ b/src/main/java/baritone/cache/CachedChunk.java
@@ -26,11 +26,10 @@ import java.util.BitSet;
import java.util.List;
import java.util.Map;
import net.minecraft.core.BlockPos;
-import net.minecraft.resources.ResourceKey;
-import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
+import net.minecraft.world.level.dimension.DimensionType;
/**
* @author Brady
@@ -110,17 +109,19 @@ public final class CachedChunk {
Blocks.VINE
);
+ public final int height;
+
/**
* The size of the chunk data in bits. Equal to 16 KiB.
*
- * Chunks are 16x16x256, each block requires 2 bits.
+ * Chunks are 16x16xH, each block requires 2 bits.
*/
- public static final int SIZE = 2 * 16 * 16 * 256;
+ public final int size;
/**
- * The size of the chunk data in bytes. Equal to 16 KiB.
+ * The size of the chunk data in bytes. Equal to 16 KiB for 256 height.
*/
- public static final int SIZE_IN_BYTES = SIZE / 8;
+ public final int sizeInBytes;
/**
* The chunk x coordinate
@@ -152,11 +153,14 @@ public final class CachedChunk {
public final long cacheTimestamp;
- CachedChunk(int x, int z, BitSet data, BlockState[] overview, Map> specialBlockLocations, long cacheTimestamp) {
+ CachedChunk(int x, int z, int height, BitSet data, BlockState[] overview, Map> specialBlockLocations, long cacheTimestamp) {
+ this.size = size(height);
+ this.sizeInBytes = sizeInBytes(size);
validateSize(data);
this.x = x;
this.z = z;
+ this.height = height;
this.data = data;
this.overview = overview;
this.heightMap = new int[256];
@@ -171,6 +175,14 @@ public final class CachedChunk {
calculateHeightMap();
}
+ public static int size(int dimension_height) {
+ return 2 * 16 * 16 * dimension_height;
+ }
+
+ public static int sizeInBytes(int size) {
+ return size / 8;
+ }
+
private final void setSpecial() {
for (Map.Entry> entry : specialBlockLocations.entrySet()) {
for (BlockPos pos : entry.getValue()) {
@@ -179,7 +191,7 @@ public final class CachedChunk {
}
}
- public final BlockState getBlock(int x, int y, int z, ResourceKey dimension) {
+ public final BlockState getBlock(int x, int y, int z, DimensionType dimension) {
int index = getPositionIndex(x, y, z);
PathingBlockType type = getType(index);
int internalPos = z << 4 | x;
@@ -201,11 +213,11 @@ public final class CachedChunk {
}
if (type == PathingBlockType.SOLID) {
- if (y == 127 && dimension == Level.NETHER) {
+ if (y == dimension.logicalHeight() - 1 && dimension.hasCeiling()) {
// nether roof is always unbreakable
return Blocks.BEDROCK.defaultBlockState();
}
- if (y < 5 && dimension == Level.OVERWORLD) {
+ if (y < 5 && dimension.natural()) {
// solid blocks below 5 are commonly bedrock
// however, returning bedrock always would be a little yikes
// discourage paths that include breaking blocks below 5 a little more heavily just so that it takes paths breaking what's known to be stone (at 5 or above) instead of what could maybe be bedrock (below 5)
@@ -224,7 +236,7 @@ public final class CachedChunk {
for (int x = 0; x < 16; x++) {
int index = z << 4 | x;
heightMap[index] = 0;
- for (int y = 256; y >= 0; y--) {
+ for (int y = height; y >= 0; y--) {
int i = getPositionIndex(x, y, z);
if (data.get(i) || data.get(i + 1)) {
heightMap[index] = y;
@@ -275,14 +287,14 @@ public final class CachedChunk {
/**
* Validates the size of an input {@link BitSet} containing the raw
- * packed chunk data. Sizes that exceed {@link CachedChunk#SIZE} are
+ * packed chunk data. Sizes that exceed {@link CachedChunk#size} are
* considered invalid, and thus, an exception will be thrown.
*
* @param data The raw data
* @throws IllegalArgumentException if the bitset size exceeds the maximum size
*/
- private static void validateSize(BitSet data) {
- if (data.size() > SIZE) {
+ private void validateSize(BitSet data) {
+ if (data.size() > size) {
throw new IllegalArgumentException("BitSet of invalid length provided");
}
}
diff --git a/src/main/java/baritone/cache/CachedRegion.java b/src/main/java/baritone/cache/CachedRegion.java
index 7581e2bdc..e501a6bb4 100644
--- a/src/main/java/baritone/cache/CachedRegion.java
+++ b/src/main/java/baritone/cache/CachedRegion.java
@@ -28,9 +28,8 @@ import java.util.*;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import net.minecraft.core.BlockPos;
-import net.minecraft.resources.ResourceKey;
-import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
+import net.minecraft.world.level.dimension.DimensionType;
/**
* @author Brady
@@ -61,14 +60,14 @@ public final class CachedRegion implements ICachedRegion {
*/
private final int z;
- private final ResourceKey dimension;
+ private final DimensionType dimension;
/**
* Has this region been modified since its most recent load or save
*/
private boolean hasUnsavedChanges;
- CachedRegion(int x, int z, ResourceKey dimension) {
+ CachedRegion(int x, int z, DimensionType dimension) {
this.x = x;
this.z = z;
this.hasUnsavedChanges = false;
@@ -77,9 +76,10 @@ public final class CachedRegion implements ICachedRegion {
@Override
public final BlockState getBlock(int x, int y, int z) {
+ int adjY = y - dimension.minY();
CachedChunk chunk = chunks[x >> 4][z >> 4];
if (chunk != null) {
- return chunk.getBlock(x & 15, y, z & 15, dimension);
+ return chunk.getBlock(x & 15, adjY, z & 15, dimension);
}
return null;
}
@@ -143,7 +143,7 @@ public final class CachedRegion implements ICachedRegion {
byte[] chunkBytes = chunk.toByteArray();
out.write(chunkBytes);
// Messy, but fills the empty 0s that should be trailing to fill up the space.
- out.write(new byte[CachedChunk.SIZE_IN_BYTES - chunkBytes.length]);
+ out.write(new byte[chunk.sizeInBytes - chunkBytes.length]);
}
}
}
@@ -224,10 +224,11 @@ public final class CachedRegion implements ICachedRegion {
int isChunkPresent = in.read();
switch (isChunkPresent) {
case CHUNK_PRESENT:
- byte[] bytes = new byte[CachedChunk.SIZE_IN_BYTES];
+ byte[] bytes = new byte[CachedChunk.sizeInBytes(CachedChunk.size(dimension.height()))];
in.readFully(bytes);
bitSets[x][z] = BitSet.valueOf(bytes);
location[x][z] = new HashMap<>();
+ //this is top block in columns
overview[x][z] = new BlockState[256];
present[x][z] = true;
break;
@@ -291,7 +292,7 @@ public final class CachedRegion implements ICachedRegion {
int regionZ = this.z;
int chunkX = x + 32 * regionX;
int chunkZ = z + 32 * regionZ;
- this.chunks[x][z] = new CachedChunk(chunkX, chunkZ, bitSets[x][z], overview[x][z], location[x][z], cacheTimestamp[x][z]);
+ this.chunks[x][z] = new CachedChunk(chunkX, chunkZ, dimension.height(), bitSets[x][z], overview[x][z], location[x][z], cacheTimestamp[x][z]);
}
}
}
diff --git a/src/main/java/baritone/cache/CachedWorld.java b/src/main/java/baritone/cache/CachedWorld.java
index 4d9ff16df..83fffd1a7 100644
--- a/src/main/java/baritone/cache/CachedWorld.java
+++ b/src/main/java/baritone/cache/CachedWorld.java
@@ -38,6 +38,7 @@ import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.chunk.LevelChunk;
+import net.minecraft.world.level.dimension.DimensionType;
/**
* @author Brady
@@ -72,9 +73,9 @@ public final class CachedWorld implements ICachedWorld, Helper {
*/
private final Map toPackMap = new ConcurrentHashMap<>();
- private final ResourceKey dimension;
+ private final DimensionType dimension;
- CachedWorld(Path directory, ResourceKey dimension) {
+ CachedWorld(Path directory, DimensionType dimension) {
if (!Files.exists(directory)) {
try {
Files.createDirectories(directory);
diff --git a/src/main/java/baritone/cache/ChunkPacker.java b/src/main/java/baritone/cache/ChunkPacker.java
index f85fc3cce..cd15e4ed7 100644
--- a/src/main/java/baritone/cache/ChunkPacker.java
+++ b/src/main/java/baritone/cache/ChunkPacker.java
@@ -21,8 +21,6 @@ import baritone.api.utils.BlockUtils;
import baritone.pathing.movement.MovementHelper;
import baritone.utils.pathing.PathingBlockType;
import net.minecraft.core.BlockPos;
-import net.minecraft.resources.ResourceKey;
-import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.AirBlock;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
@@ -33,6 +31,7 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.chunk.PalettedContainer;
+import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.phys.Vec3;
import java.util.*;
@@ -50,10 +49,11 @@ public final class ChunkPacker {
//long start = System.nanoTime() / 1000000L;
Map> specialBlocks = new HashMap<>();
- BitSet bitSet = new BitSet(CachedChunk.SIZE);
+ final int height = chunk.getLevel().dimensionType().height();
+ BitSet bitSet = new BitSet(CachedChunk.size(height));
try {
LevelChunkSection[] chunkInternalStorageArray = chunk.getSections();
- for (int y0 = 0; y0 < 16; y0++) {
+ for (int y0 = 0; y0 < height / 16; y0++) {
LevelChunkSection extendedblockstorage = chunkInternalStorageArray[y0];
if (extendedblockstorage == null) {
// any 16x16x16 area that's all air will have null storage
@@ -95,11 +95,12 @@ public final class ChunkPacker {
//System.out.println("Chunk packing took " + (end - start) + "ms for " + chunk.x + "," + chunk.z);
BlockState[] blocks = new BlockState[256];
+ // get top block in columns
// @formatter:off
for (int z = 0; z < 16; z++) {
https://www.ibm.com/developerworks/library/j-perry-writing-good-java-code/index.html
for (int x = 0; x < 16; x++) {
- for (int y = 255; y >= 0; y--) {
+ for (int y = height - 1; y >= 0; y--) {
int index = CachedChunk.getPositionIndex(x, y, z);
if (bitSet.get(index) || bitSet.get(index + 1)) {
blocks[z << 4 | x] = getFromChunk(chunk, x, y, z);
@@ -110,7 +111,7 @@ public final class ChunkPacker {
}
}
// @formatter:on
- return new CachedChunk(chunk.getPos().x, chunk.getPos().z, bitSet, blocks, specialBlocks, System.currentTimeMillis());
+ return new CachedChunk(chunk.getPos().x, chunk.getPos().z, height, bitSet, blocks, specialBlocks, System.currentTimeMillis());
}
private static PathingBlockType getPathingBlockType(BlockState state, LevelChunk chunk, int x, int y, int z) {
@@ -153,7 +154,7 @@ public final class ChunkPacker {
return PathingBlockType.SOLID;
}
- public static BlockState pathingTypeToBlock(PathingBlockType type, ResourceKey dimension) {
+ public static BlockState pathingTypeToBlock(PathingBlockType type, DimensionType dimension) {
switch (type) {
case AIR:
return Blocks.AIR.defaultBlockState();
@@ -163,13 +164,13 @@ public final class ChunkPacker {
return Blocks.LAVA.defaultBlockState();
case SOLID:
// Dimension solid types
- if (dimension == Level.OVERWORLD) {
+ if (dimension.natural()) {
return Blocks.STONE.defaultBlockState();
}
- if (dimension == Level.NETHER) {
+ if (dimension.ultraWarm()) {
return Blocks.NETHERRACK.defaultBlockState();
}
- if (dimension == Level.END) {
+ if (dimension.createDragonFight()) {
return Blocks.END_STONE.defaultBlockState();
}
default:
diff --git a/src/main/java/baritone/cache/WorldData.java b/src/main/java/baritone/cache/WorldData.java
index 31b1964b0..159d2db27 100644
--- a/src/main/java/baritone/cache/WorldData.java
+++ b/src/main/java/baritone/cache/WorldData.java
@@ -26,6 +26,7 @@ import java.io.IOException;
import java.nio.file.Path;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.Level;
+import net.minecraft.world.level.dimension.DimensionType;
/**
* Data about a world, from baritone's point of view. Includes cached chunks, waypoints, and map data.
@@ -39,9 +40,9 @@ public class WorldData implements IWorldData {
private final ContainerMemory containerMemory;
//public final MapData map;
public final Path directory;
- public final ResourceKey dimension;
+ public final DimensionType dimension;
- WorldData(Path directory, ResourceKey dimension) {
+ WorldData(Path directory, DimensionType dimension) {
this.directory = directory;
this.cache = new CachedWorld(directory.resolve("cache"), dimension);
this.waypoints = new WaypointCollection(directory.resolve("waypoints"));
diff --git a/src/main/java/baritone/cache/WorldProvider.java b/src/main/java/baritone/cache/WorldProvider.java
index 7f992e6dc..3d30603b4 100644
--- a/src/main/java/baritone/cache/WorldProvider.java
+++ b/src/main/java/baritone/cache/WorldProvider.java
@@ -56,7 +56,7 @@ public class WorldProvider implements IWorldProvider, Helper {
*
* @param world The world's Registry Data
*/
- public final void initWorld(ResourceKey world) {
+ public final void initWorld(ResourceKey worldKey, DimensionType world) {
File directory;
File readme;
@@ -64,7 +64,7 @@ public class WorldProvider implements IWorldProvider, Helper {
// If there is an integrated server running (Aka Singleplayer) then do magic to find the world save file
if (mc.hasSingleplayerServer()) {
- directory = DimensionType.getStorageFolder(world, integratedServer.getWorldPath(LevelResource.ROOT).toFile());
+ directory = DimensionType.getStorageFolder(worldKey, integratedServer.getWorldPath(LevelResource.ROOT).toFile());
// Gets the "depth" of this directory relative the the game's run directory, 2 is the location of the world
if (directory.toPath().relativize(mc.gameDirectory.toPath()).getNameCount() != 2) {
@@ -90,7 +90,7 @@ public class WorldProvider implements IWorldProvider, Helper {
} catch (IOException ignored) {}
// We will actually store the world data in a subfolder: "DIM"
- Path dir = DimensionType.getStorageFolder(world, directory).toPath();
+ Path dir = getDimDir(worldKey, world.logicalHeight(), directory);
if (!Files.exists(dir)) {
try {
Files.createDirectories(dir);
@@ -103,6 +103,10 @@ public class WorldProvider implements IWorldProvider, Helper {
}
}
+ public final Path getDimDir(ResourceKey level, int height, File directory) {
+ return directory.toPath().resolve(level.location().getNamespace()).resolve(level.location().getPath() + "_" + height);
+ }
+
public final void closeWorld() {
WorldData world = this.currentWorld;
this.currentWorld = null;
diff --git a/src/main/java/baritone/cache/WorldScanner.java b/src/main/java/baritone/cache/WorldScanner.java
index b4ec4afc8..8a932555a 100644
--- a/src/main/java/baritone/cache/WorldScanner.java
+++ b/src/main/java/baritone/cache/WorldScanner.java
@@ -37,8 +37,6 @@ public enum WorldScanner implements IWorldScanner {
INSTANCE;
- private static final int[] DEFAULT_COORDINATE_ITERATION_ORDER = IntStream.range(0, 16).toArray();
-
@Override
public List scanChunkRadius(IPlayerContext ctx, BlockOptionalMetaLookup filter, int max, int yLevelThreshold, int maxSearchRadius) {
ArrayList res = new ArrayList<>();
@@ -51,10 +49,10 @@ public enum WorldScanner implements IWorldScanner {
int maxSearchRadiusSq = maxSearchRadius * maxSearchRadius;
int playerChunkX = ctx.playerFeet().getX() >> 4;
int playerChunkZ = ctx.playerFeet().getZ() >> 4;
- int playerY = ctx.playerFeet().getY();
+ int playerY = ctx.playerFeet().getY() - ctx.world().dimensionType().minY();
int playerYBlockStateContainerIndex = playerY >> 4;
- int[] coordinateIterationOrder = IntStream.range(0, 16).boxed().sorted(Comparator.comparingInt(y -> Math.abs(y - playerYBlockStateContainerIndex))).mapToInt(x -> x).toArray();
+ int[] coordinateIterationOrder = IntStream.range(0, ctx.world().dimensionType().height() / 16).boxed().sorted(Comparator.comparingInt(y -> Math.abs(y - playerYBlockStateContainerIndex))).mapToInt(x -> x).toArray();
int searchRadiusSq = 0;
boolean foundWithinY = false;
@@ -75,7 +73,7 @@ public enum WorldScanner implements IWorldScanner {
continue;
}
allUnloaded = false;
- if (scanChunkInto(chunkX << 4, chunkZ << 4, chunk, filter, res, max, yLevelThreshold, playerY, coordinateIterationOrder)) {
+ if (scanChunkInto(chunkX << 4, chunkZ << 4, ctx.world().dimensionType().minY(), chunk, filter, res, max, yLevelThreshold, playerY, coordinateIterationOrder)) {
foundWithinY = true;
}
}
@@ -105,7 +103,7 @@ public enum WorldScanner implements IWorldScanner {
}
ArrayList res = new ArrayList<>();
- scanChunkInto(pos.x << 4, pos.z << 4, chunk, filter, res, max, yLevelThreshold, playerY, DEFAULT_COORDINATE_ITERATION_ORDER);
+ scanChunkInto(pos.x << 4, pos.z << 4, ctx.world().dimensionType().minY(), chunk, filter, res, max, yLevelThreshold, playerY, IntStream.range(0, ctx.world().dimensionType().height() / 16).toArray());
return res;
}
@@ -144,11 +142,10 @@ public enum WorldScanner implements IWorldScanner {
return queued;
}
- private boolean scanChunkInto(int chunkX, int chunkZ, LevelChunk chunk, BlockOptionalMetaLookup filter, Collection result, int max, int yLevelThreshold, int playerY, int[] coordinateIterationOrder) {
+ private boolean scanChunkInto(int chunkX, int chunkZ, int minY, LevelChunk chunk, BlockOptionalMetaLookup filter, Collection result, int max, int yLevelThreshold, int playerY, int[] coordinateIterationOrder) {
LevelChunkSection[] chunkInternalStorageArray = chunk.getSections();
boolean foundWithinY = false;
- for (int yIndex = 0; yIndex < 16; yIndex++) {
- int y0 = coordinateIterationOrder[yIndex];
+ for (int y0 : coordinateIterationOrder) {
LevelChunkSection section = chunkInternalStorageArray[y0];
if (section == null || LevelChunkSection.isEmpty(section)) {
continue;
@@ -172,7 +169,7 @@ public enum WorldScanner implements IWorldScanner {
}
}
}
- result.add(new BlockPos(chunkX | x, y, chunkZ | z));
+ result.add(new BlockPos(chunkX | x, y + minY, chunkZ | z));
}
}
}
diff --git a/src/main/java/baritone/event/GameEventHandler.java b/src/main/java/baritone/event/GameEventHandler.java
index 5056b6a0b..b7853e360 100644
--- a/src/main/java/baritone/event/GameEventHandler.java
+++ b/src/main/java/baritone/event/GameEventHandler.java
@@ -114,7 +114,7 @@ public final class GameEventHandler implements IEventBus, Helper {
if (event.getState() == EventState.POST) {
cache.closeWorld();
if (event.getWorld() != null) {
- cache.initWorld(event.getWorld().dimension());
+ cache.initWorld(event.getWorld().dimension(), event.getWorld().dimensionType());
}
}