Skip to content

Commit

Permalink
Merge pull request #173 from mircokroon/bugfixes
Browse files Browse the repository at this point in the history
Bugfixes
  • Loading branch information
mircokroon authored Jun 29, 2021
2 parents 052b738 + 49eaa1e commit 90d3423
Show file tree
Hide file tree
Showing 21 changed files with 135 additions and 52 deletions.
50 changes: 35 additions & 15 deletions src/main/java/game/data/LevelData.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
package game.data;

import config.Config;
import game.data.WorldManager;
import game.data.coordinates.Coordinate3D;
import game.data.coordinates.CoordinateDim2D;
import game.data.coordinates.CoordinateDim3D;
import game.data.coordinates.CoordinateDouble3D;
import game.data.dimension.Dimension;
import game.data.dimension.DimensionCodec;
import org.apache.commons.io.IOUtils;
import proxy.CompressionManager;
import se.llbit.nbt.*;
import util.NbtUtil;
import util.PathUtils;
Expand All @@ -20,14 +14,14 @@
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class LevelData {
private final WorldManager worldManager;
private final Path outputDir;
private final File file;
private Tag root;
private SpecificTag worldGenSettings;
private CompoundTag data;
private boolean savingBroken;

Expand Down Expand Up @@ -63,13 +57,14 @@ public Dimension getPlayerDimension() {

public void load() throws IOException {
load(false);
loadGeneratorSettings();
}
private void load(boolean forceInternal) throws IOException {
Files.createDirectories(outputDir);

InputStream fileInput;
if (!file.exists() || !file.isFile() || forceInternal) {
fileInput = WorldManager.class.getClassLoader().getResourceAsStream("level.dat");
fileInput = LevelData.class.getClassLoader().getResourceAsStream("level.dat");
} else {
fileInput = new FileInputStream(file);
}
Expand All @@ -87,6 +82,18 @@ private void load(boolean forceInternal) throws IOException {
this.data = (CompoundTag) root.unpack().get("Data");
}

/**
* Loads the default generator settings used in 1.16+. They are more complicated than before so loading them from a
* file is easier.
*/
private void loadGeneratorSettings() throws IOException {
this.worldGenSettings = NbtUtil
.read(LevelData.class.getClassLoader().getResourceAsStream("world-gen-settings.dat"))
.unpack()
.get("WorldGenSettings")
.asCompound();
}

/**
* Save the level.dat file so the world can be easily opened. If one doesn't exist, use the default one from
* the resource folder.
Expand Down Expand Up @@ -150,7 +157,19 @@ public void save() throws IOException {
}

private void enableWorldGeneration(CompoundTag data) {
if (Config.getDataVersion() < 2504) {
if (Config.versionReporter().isAtLeast1_16()) {
LongTag seed = new LongTag(Config.getLevelSeed());

CompoundTag dimensions = this.worldGenSettings.get("dimensions").asCompound();
for (Dimension dim : Dimension.DEFAULTS) {
Tag generator = dimensions.get(dim.getName()).get("generator");
generator.asCompound().add("seed", seed);
generator.get("biome_source").asCompound().add("seed", seed);
}
this.worldGenSettings.asCompound().add("seed", seed);

data.add("WorldGenSettings", this.worldGenSettings);
} else {
data.add("generatorVersion", new IntTag(1));
data.add("generatorName", new StringTag("default"));
// this is the 1.12.2 superflat format, but it still works in later versions.
Expand All @@ -159,16 +178,12 @@ private void enableWorldGeneration(CompoundTag data) {
}



/**
* Set world type to a superflat void world.
*/
private void disableWorldGeneration(CompoundTag data) {
if (Config.getDataVersion() < 2504) {
data.add("generatorVersion", new IntTag(1));
data.add("generatorName", new StringTag("flat"));
// this is the 1.12.2 superflat format, but it still works in later versions.
data.add("generatorOptions", new StringTag("3;minecraft:air;127"));
} else {
if (Config.versionReporter().isAtLeast1_16()) {
CompoundTag generator = new CompoundTag();
generator.add("type", new StringTag("minecraft:flat"));
generator.add("settings", new CompoundTag(Arrays.asList(
Expand Down Expand Up @@ -197,6 +212,11 @@ private void disableWorldGeneration(CompoundTag data) {
new NamedTag("seed", new LongTag(Config.getLevelSeed())),
new NamedTag("dimensions", dimensions)
)));
} else {
data.add("generatorVersion", new IntTag(1));
data.add("generatorName", new StringTag("flat"));
// this is the 1.12.2 superflat format, but it still works in later versions.
data.add("generatorOptions", new StringTag("3;minecraft:air;127"));
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/game/data/chunk/Chunk.java
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ protected void parseHeightMaps(DataTypeProvider dataProvider) {
protected void readBlockCount(DataTypeProvider provider) {
}

protected abstract ChunkSection createNewChunkSection(byte y, Palette palette);
public abstract ChunkSection createNewChunkSection(byte y, Palette palette);

protected abstract SpecificTag getNbtBiomes();

Expand Down
12 changes: 11 additions & 1 deletion src/main/java/game/data/chunk/ChunkSection.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package game.data.chunk;

import game.data.chunk.palette.BlockState;
import game.data.chunk.palette.DirectPalette;
import game.data.chunk.palette.GlobalPaletteProvider;
import game.data.chunk.palette.Palette;
import game.data.chunk.version.ChunkSection_1_13;
import game.data.chunk.version.encoder.BlockLocationEncoder;
import game.data.coordinates.Coordinate3D;
import org.apache.commons.lang3.mutable.MutableBoolean;
Expand All @@ -18,6 +20,8 @@
* Class to hold a 16 block tall chunk section.
*/
public abstract class ChunkSection {
protected Chunk chunk;

protected long[] blocks;
protected byte[] blockLight;
protected byte[] skyLight;
Expand All @@ -28,7 +32,8 @@ public abstract class ChunkSection {

public abstract int getDataVersion();

public ChunkSection(byte y, Palette palette) {
public ChunkSection(byte y, Palette palette, Chunk chunk) {
this.chunk = chunk;
this.y = y;
this.blockLight = new byte[2048];
this.skyLight = new byte[2048];
Expand Down Expand Up @@ -196,5 +201,10 @@ public void resetBlocks() {
this.blocks = new long[256];
this.palette = Palette.empty();
}

public void copyTo(ChunkSection other) {
other.blocks = this.blocks;
other.palette = this.palette;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,17 @@

import java.util.List;

public class DummyPalette extends Palette {
public class DirectPalette extends Palette {
int bitsPerBlock;

public DummyPalette() {
public DirectPalette() {
this(GlobalPaletteProvider.getGlobalPalette().getRequiredBits());
}

public DirectPalette(int bitsPerBlock) {
super();

this.bitsPerBlock = bitsPerBlock;
}

@Override
Expand All @@ -18,7 +25,7 @@ public int stateFromId(int index) {

@Override
public int getBitsPerBlock() {
return 12;
return bitsPerBlock;
}

@Override
Expand All @@ -33,6 +40,13 @@ public List<SpecificTag> toNbt() {

@Override
public void write(PacketBuilder packet) {
packet.writeByte((byte) 12);
packet.writeByte((byte) bitsPerBlock);
}

@Override
public String toString() {
return "DirectPalette{" +
"bitsPerBlock=" + bitsPerBlock +
'}';
}
}
4 changes: 4 additions & 0 deletions src/main/java/game/data/chunk/palette/GlobalPalette.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ public GlobalPalette(InputStream input) {
}));
}

public int getRequiredBits() {
return (int) Math.ceil(Math.log(states.size()) / Math.log(2));
}

/**
* Get a block state from a given index. Used to convert packet palettes to the global palette.
*/
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/game/data/chunk/palette/Palette.java
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ private int computeBitsPerBlock(int maxIndex) {
*/
public static Palette readPalette(int bitsPerBlock, DataTypeProvider dataTypeProvider) {
if (bitsPerBlock > 8) {
return new DummyPalette();
return new DirectPalette(bitsPerBlock);
}
int size = dataTypeProvider.readVarInt();

Expand Down Expand Up @@ -161,7 +161,7 @@ public int hashCode() {
public String toString() {
return "Palette{" +
"bitsPerBlock=" + bitsPerBlock +
", palette=" + Arrays.toString(palette) +
", palette(" + palette.length + ")=" + Arrays.toString(palette) +
'}';
}

Expand Down
8 changes: 4 additions & 4 deletions src/main/java/game/data/chunk/version/ChunkSection_1_12.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import game.data.WorldManager;
import game.data.chunk.Chunk;
import game.data.chunk.ChunkSection;
import game.data.chunk.palette.DummyPalette;
import game.data.chunk.palette.DirectPalette;
import game.data.chunk.palette.Palette;
import game.data.chunk.palette.PaletteBuilder;
import game.data.coordinates.Coordinate3D;
Expand All @@ -31,15 +31,15 @@ public int getDataVersion() {
protected int[][][] blockStates;


public ChunkSection_1_12(byte y, Palette palette) {
super(y, palette);
public ChunkSection_1_12(byte y, Palette palette, Chunk chunk) {
super(y, palette, chunk);
this.blockStates = new int[16][16][16];
}

public ChunkSection_1_12(int sectionY, Tag nbt) {
super(sectionY, nbt);
this.blockStates = new int[16][16][16];
this.palette = new DummyPalette();
this.palette = new DirectPalette();

long[] blocks = encodeBlocks(nbt.get("Blocks").byteArray(), nbt.get("Data").byteArray(), this.palette);

Expand Down
33 changes: 31 additions & 2 deletions src/main/java/game/data/chunk/version/ChunkSection_1_13.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

import config.Version;
import game.data.WorldManager;
import game.data.chunk.Chunk;
import game.data.chunk.ChunkSection;
import game.data.chunk.palette.DirectPalette;
import game.data.chunk.palette.Palette;
import game.data.coordinates.Coordinate3D;
import game.data.dimension.Dimension;
import packets.builder.PacketBuilder;
import se.llbit.nbt.CompoundTag;
Expand All @@ -25,8 +28,8 @@ public int getDataVersion() {
return VERSION.dataVersion;
}

public ChunkSection_1_13(byte y, Palette palette) {
super(y, palette);
public ChunkSection_1_13(byte y, Palette palette, Chunk chunk) {
super(y, palette, chunk);
}
public ChunkSection_1_13(int sectionY, Tag nbt) {
super(sectionY, nbt);
Expand All @@ -52,14 +55,40 @@ public void write(PacketBuilder packet) {

@Override
protected void addNbtTags(CompoundTag map) {
if (palette instanceof DirectPalette) {
convertToIndirectPalette();
}

map.add("BlockStates", new LongArrayTag(blocks));
map.add("Palette", createPalette());
}

/**
* Before saving chunks, we need to ensure that it's correctly using a palette. Chunk sections with a large variety of
* blocks need to be converted.
*/
private void convertToIndirectPalette() {
ChunkSection newSection = this.chunk.createNewChunkSection(this.y, Palette.empty());
newSection.setBlocks(new long[256]);

for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
newSection.setBlockAt(new Coordinate3D(x, y, z), getNumericBlockStateAt(x, y, z));
}
}
}

newSection.copyTo(this);
}


private ListTag createPalette() {
return new ListTag(Tag.TAG_COMPOUND, palette.toNbt());
}



@Override
public boolean equals(Object o) {
if (this == o) return true;
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/game/data/chunk/version/ChunkSection_1_14.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package game.data.chunk.version;

import config.Version;
import game.data.chunk.Chunk;
import game.data.chunk.palette.Palette;
import packets.builder.PacketBuilder;
import se.llbit.nbt.Tag;
Expand All @@ -12,8 +13,8 @@ public int getDataVersion() {
return VERSION.dataVersion;
}

public ChunkSection_1_14(byte y, Palette palette) {
super(y, palette);
public ChunkSection_1_14(byte y, Palette palette, Chunk chunk) {
super(y, palette, chunk);
}

public ChunkSection_1_14(int sectionY, Tag nbt) {
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/game/data/chunk/version/ChunkSection_1_15.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package game.data.chunk.version;

import config.Version;
import game.data.chunk.Chunk;
import game.data.chunk.palette.Palette;
import packets.builder.PacketBuilder;
import se.llbit.nbt.Tag;
Expand All @@ -12,8 +13,8 @@ public int getDataVersion() {
return VERSION.dataVersion;
}

public ChunkSection_1_15(byte y, Palette palette) {
super(y, palette);
public ChunkSection_1_15(byte y, Palette palette, Chunk chunk) {
super(y, palette, chunk);
}

public ChunkSection_1_15(int sectionY, Tag nbt) {
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/game/data/chunk/version/ChunkSection_1_16.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ protected BlockLocationEncoder getLocationEncoder() {
return blockLocationEncoder;
}

public ChunkSection_1_16(byte y, Palette palette) {
super(y, palette);
public ChunkSection_1_16(byte y, Palette palette, Chunk chunk) {
super(y, palette, chunk);
}

public ChunkSection_1_16(int sectionY, Tag nbt) {
Expand Down
Loading

0 comments on commit 90d3423

Please sign in to comment.