Skip to content

Commit

Permalink
Reimplement Linear region file format support
Browse files Browse the repository at this point in the history
  • Loading branch information
TBlueF committed Feb 22, 2024
1 parent ff1e38a commit dbde93c
Show file tree
Hide file tree
Showing 10 changed files with 247 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public class MCAWorld implements World {
private final Path dimensionFolder;
private final Path regionFolder;

private final ChunkLoader chunkLoader = new ChunkLoader();
private final ChunkLoader chunkLoader = new ChunkLoader(this);
private final LoadingCache<Vector2i, Region> regionCache = Caffeine.newBuilder()
.executor(BlueMap.THREAD_POOL)
.maximumSize(64)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import de.bluecolored.bluemap.core.storage.Compression;
import de.bluecolored.bluemap.core.world.mca.MCAUtil;
import de.bluecolored.bluemap.core.world.mca.region.MCARegion;
import de.bluecolored.bluemap.core.world.mca.MCAWorld;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.Nullable;
Expand All @@ -16,6 +16,12 @@

public class ChunkLoader {

private final MCAWorld world;

public ChunkLoader(MCAWorld world) {
this.world = world;
}

// sorted list of chunk-versions, loaders at the start of the list are preferred over loaders at the end
private static final List<ChunkVersionLoader<?>> CHUNK_VERSION_LOADERS = List.of(
new ChunkVersionLoader<>(Chunk_1_18.Data.class, Chunk_1_18::new, 2844),
Expand All @@ -26,23 +32,23 @@ public class ChunkLoader {

private ChunkVersionLoader<?> lastUsedLoader = CHUNK_VERSION_LOADERS.get(0);

public MCAChunk load(MCARegion region, byte[] data, int offset, int length, Compression compression) throws IOException {
public MCAChunk load(byte[] data, int offset, int length, Compression compression) throws IOException {
InputStream in = new ByteArrayInputStream(data, offset, length);
in.mark(-1);

// try last used version
ChunkVersionLoader<?> usedLoader = lastUsedLoader;
MCAChunk chunk;
try (InputStream decompressedIn = new BufferedInputStream(compression.decompress(in))) {
chunk = usedLoader.load(region, decompressedIn);
chunk = usedLoader.load(world, decompressedIn);
}

// check version and reload chunk if the wrong loader has been used and a better one has been found
ChunkVersionLoader<?> actualLoader = findBestLoaderForVersion(chunk.getDataVersion());
if (actualLoader != null && usedLoader != actualLoader) {
in.reset(); // reset read position
try (InputStream decompressedIn = new BufferedInputStream(compression.decompress(in))) {
chunk = actualLoader.load(region, decompressedIn);
chunk = actualLoader.load(world, decompressedIn);
}
lastUsedLoader = actualLoader;
}
Expand All @@ -62,12 +68,12 @@ public MCAChunk load(MCARegion region, byte[] data, int offset, int length, Comp
private static class ChunkVersionLoader<D extends MCAChunk.Data> {

private final Class<D> dataType;
private final BiFunction<MCARegion, D, MCAChunk> constructor;
private final BiFunction<MCAWorld, D, MCAChunk> constructor;
private final int dataVersion;

public MCAChunk load(MCARegion region, InputStream in) throws IOException {
public MCAChunk load(MCAWorld world, InputStream in) throws IOException {
D data = MCAUtil.BLUENBT.read(in, dataType);
return mightSupport(data.getDataVersion()) ? constructor.apply(region, data) : new MCAChunk(region, data) {};
return mightSupport(data.getDataVersion()) ? constructor.apply(world, data) : new MCAChunk(world, data) {};
}

public boolean mightSupport(int dataVersion) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import de.bluecolored.bluemap.core.world.DimensionType;
import de.bluecolored.bluemap.core.world.LightData;
import de.bluecolored.bluemap.core.world.mca.MCAUtil;
import de.bluecolored.bluemap.core.world.mca.region.MCARegion;
import de.bluecolored.bluemap.core.world.mca.MCAWorld;
import de.bluecolored.bluenbt.NBTName;
import lombok.Getter;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -38,8 +38,8 @@ public class Chunk_1_13 extends MCAChunk {

final int[] biomes;

public Chunk_1_13(MCARegion region, Data data) {
super(region, data);
public Chunk_1_13(MCAWorld world, Data data) {
super(world, data);

Level level = data.level;

Expand All @@ -50,7 +50,7 @@ public Chunk_1_13(MCARegion region, Data data) {
STATUS_POSTPROCESSED.equals(level.status);
this.inhabitedTime = level.inhabitedTime;

DimensionType dimensionType = getRegion().getWorld().getDimensionType();
DimensionType dimensionType = getWorld().getDimensionType();
this.skyLight = dimensionType.hasSkylight() ? 16 : 0;

this.worldSurfaceHeights = level.heightmaps.worldSurface;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package de.bluecolored.bluemap.core.world.mca.chunk;

import de.bluecolored.bluemap.core.world.Biome;
import de.bluecolored.bluemap.core.world.mca.region.MCARegion;
import de.bluecolored.bluemap.core.world.mca.MCAWorld;

public class Chunk_1_15 extends Chunk_1_13 {

public Chunk_1_15(MCARegion region, Data data) {
super(region, data);
public Chunk_1_15(MCAWorld world, Data data) {
super(world, data);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
import de.bluecolored.bluemap.core.world.DimensionType;
import de.bluecolored.bluemap.core.world.LightData;
import de.bluecolored.bluemap.core.world.mca.MCAUtil;
import de.bluecolored.bluemap.core.world.mca.MCAWorld;
import de.bluecolored.bluemap.core.world.mca.PackedIntArrayAccess;
import de.bluecolored.bluemap.core.world.mca.region.MCARegion;
import de.bluecolored.bluenbt.NBTName;
import lombok.Getter;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -37,16 +37,16 @@ public class Chunk_1_16 extends MCAChunk {

private final int[] biomes;

public Chunk_1_16(MCARegion region, Data data) {
super(region, data);
public Chunk_1_16(MCAWorld world, Data data) {
super(world, data);

Level level = data.level;

this.generated = !STATUS_EMPTY.equals(level.status);
this.hasLightData = STATUS_FULL.equals(level.status);
this.inhabitedTime = level.inhabitedTime;

DimensionType dimensionType = getRegion().getWorld().getDimensionType();
DimensionType dimensionType = getWorld().getDimensionType();
this.skyLight = dimensionType.hasSkylight() ? 16 : 0;

int worldHeight = dimensionType.getHeight();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
import de.bluecolored.bluemap.core.world.DimensionType;
import de.bluecolored.bluemap.core.world.LightData;
import de.bluecolored.bluemap.core.world.mca.MCAUtil;
import de.bluecolored.bluemap.core.world.mca.MCAWorld;
import de.bluecolored.bluemap.core.world.mca.PackedIntArrayAccess;
import de.bluecolored.bluemap.core.world.mca.region.MCARegion;
import de.bluecolored.bluenbt.NBTName;
import lombok.Getter;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -37,14 +37,14 @@ public class Chunk_1_18 extends MCAChunk {
private final Section[] sections;
private final int sectionMin, sectionMax;

public Chunk_1_18(MCARegion region, Data data) {
super(region, data);
public Chunk_1_18(MCAWorld world, Data data) {
super(world, data);

this.generated = !STATUS_EMPTY.equals(data.status);
this.hasLightData = STATUS_FULL.equals(data.status);
this.inhabitedTime = data.inhabitedTime;

DimensionType dimensionType = getRegion().getWorld().getDimensionType();
DimensionType dimensionType = getWorld().getDimensionType();
this.worldMinY = dimensionType.getMinY();
this.skyLight = dimensionType.hasSkylight() ? 16 : 0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import de.bluecolored.bluemap.core.world.BlockState;
import de.bluecolored.bluemap.core.world.Chunk;
import de.bluecolored.bluemap.core.world.mca.region.MCARegion;
import de.bluecolored.bluemap.core.world.mca.MCAWorld;
import lombok.Getter;
import lombok.ToString;

Expand All @@ -20,11 +20,11 @@ public abstract class MCAChunk implements Chunk {
protected static final String[] EMPTY_STRING_ARRAY = new String[0];
protected static final BlockState[] EMPTY_BLOCKSTATE_ARRAY = new BlockState[0];

private final MCARegion region;
private final MCAWorld world;
private final int dataVersion;

public MCAChunk(MCARegion region, Data chunkData) {
this.region = region;
public MCAChunk(MCAWorld world, Data chunkData) {
this.world = world;
this.dataVersion = chunkData.getDataVersion();
}

Expand Down
Loading

0 comments on commit dbde93c

Please sign in to comment.