diff --git a/src/main/java/com/seibel/lod/core/a7/Initializer.java b/src/main/java/com/seibel/lod/core/a7/Initializer.java index 5fe3ed35d..100440a95 100644 --- a/src/main/java/com/seibel/lod/core/a7/Initializer.java +++ b/src/main/java/com/seibel/lod/core/a7/Initializer.java @@ -1,9 +1,11 @@ package com.seibel.lod.core.a7; import com.seibel.lod.core.a7.datatype.column.ColumnRenderLoader; +import com.seibel.lod.core.a7.datatype.full.FullDataLoader; public class Initializer { public static void init() { ColumnRenderLoader unused = new ColumnRenderLoader(); // Auto register into the loader system + FullDataLoader unused2 = new FullDataLoader(); // Auto register into the loader system } } diff --git a/src/main/java/com/seibel/lod/core/a7/datatype/full/FullDataLoader.java b/src/main/java/com/seibel/lod/core/a7/datatype/full/FullDataLoader.java new file mode 100644 index 000000000..3da73017d --- /dev/null +++ b/src/main/java/com/seibel/lod/core/a7/datatype/full/FullDataLoader.java @@ -0,0 +1,26 @@ +package com.seibel.lod.core.a7.datatype.full; + +import com.seibel.lod.core.a7.datatype.DataSourceLoader; +import com.seibel.lod.core.a7.datatype.LodDataSource; +import com.seibel.lod.core.a7.level.ILevel; +import com.seibel.lod.core.a7.save.io.file.DataMetaFile; + +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; + +public class FullDataLoader extends DataSourceLoader { + public FullDataLoader() { + super(FullDataSource.class, FullDataSource.TYPE_ID, new byte[]{FullDataSource.LATEST_VERSION}); + } + + @Override + public LodDataSource loadData(DataMetaFile dataFile, InputStream data, ILevel level) throws IOException { + try ( + //TODO: Add decompressor here + DataInputStream dis = new DataInputStream(data); + ) { + return FullDataSource.loadData(dataFile, dis, level); + } + } +} diff --git a/src/main/java/com/seibel/lod/core/a7/datatype/full/FullDataSource.java b/src/main/java/com/seibel/lod/core/a7/datatype/full/FullDataSource.java index fefabfdf1..d8722a996 100644 --- a/src/main/java/com/seibel/lod/core/a7/datatype/full/FullDataSource.java +++ b/src/main/java/com/seibel/lod/core/a7/datatype/full/FullDataSource.java @@ -9,20 +9,22 @@ import com.seibel.lod.core.a7.save.io.file.DataMetaFile; import com.seibel.lod.core.a7.datatype.LodDataSource; import com.seibel.lod.core.a7.util.IdMappingUtil; import com.seibel.lod.core.a7.pos.DhSectionPos; +import com.seibel.lod.core.logging.DhLoggerBuilder; import com.seibel.lod.core.objects.DHChunkPos; import com.seibel.lod.core.util.LodUtil; import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper; +import org.apache.logging.log4j.Logger; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.OutputStream; +import java.io.*; import java.util.ArrayList; import java.util.HashMap; public class FullDataSource extends FullArrayView implements LodDataSource { // 1 chunk + private static final Logger LOGGER = DhLoggerBuilder.getLogger(); public static final byte SECTION_SIZE_OFFSET = ColumnRenderSource.SECTION_SIZE_OFFSET; public static final int SECTION_SIZE = 1 << SECTION_SIZE_OFFSET; public static final byte LATEST_VERSION = 0; + public static final long TYPE_ID = "FullDataSource".hashCode(); private final DhSectionPos sectionPos; private int localVersion = 0; protected FullDataSource(DhSectionPos sectionPos) { @@ -77,12 +79,83 @@ public class FullDataSource extends FullArrayView implements LodDataSource { // @Override public void saveData(ILevel level, DataMetaFile file, OutputStream dataStream) throws IOException { - //TODO try (DataOutputStream dos = new DataOutputStream(dataStream)) { + dos.writeInt(getDataDetail()); dos.writeInt(size); + dos.writeInt(level.getMinY()); + dos.writeInt(0xFFFFFFFF); + // Data array length + for (int x = 0; x < size; x++) { + for (int z = 0; z < size; z++) { + dos.writeByte(get(x, z).getSingleLength()); + } + } + // Data array content (only on non-empty columns) + dos.writeInt(0xFFFFFFFF); + for (int x = 0; x < size; x++) { + for (int z = 0; z < size; z++) { + SingleFullArrayView column = get(x, z); + if (!column.doesItExist()) continue; + long[] raw = column.getRaw(); + for (long l : raw) { + dos.writeLong(l); + } + } + } + // Id mapping + dos.writeInt(0xFFFFFFFF); + mapping.serialize(dos); + dos.writeInt(0xFFFFFFFF); } } + + public static FullDataSource loadData(DataMetaFile dataFile, InputStream dataStream, ILevel level) throws IOException { + try (DataInputStream dos = new DataInputStream(dataStream)) { + int dataDetail = dos.readInt(); + if(dataDetail != dataFile.dataLevel) + throw new IOException(LodUtil.formatLog("Data level mismatch: {} != {}", dataDetail, dataFile.dataLevel)); + int size = dos.readInt(); + if (size != SECTION_SIZE) + throw new IOException(LodUtil.formatLog( + "Section size mismatch: {} != {} (Currently only 1 section size is supported)", size, SECTION_SIZE)); + int minY = dos.readInt(); + if (minY != level.getMinY()) + LOGGER.warn("Data minY mismatch: {} != {}. Will ignore data's y level", minY, level.getMinY()); + int end = dos.readInt(); + // Data array length + if (end != 0xFFFFFFFF) throw new IOException("invalid header end guard"); + long[][] data = new long[size*size][]; + for (int x = 0; x < size; x++) { + for (int z = 0; z < size; z++) { + data[x*size+z] = new long[dos.readByte()]; + } + } + // Data array content (only on non-empty columns) + end = dos.readInt(); + if (end != 0xFFFFFFFF) throw new IOException("invalid data length end guard"); + for (int i = 0; i < data.length; i++) { + if (data[i].length == 0) continue; + for (int j = 0; j < data[i].length; j++) { + data[i][j] = dos.readLong(); + } + } + // Id mapping + end = dos.readInt(); + if (end != 0xFFFFFFFF) throw new IOException("invalid data content end guard"); + IdBiomeBlockStateMap mapping = IdBiomeBlockStateMap.deserialize(dos); + end = dos.readInt(); + if (end != 0xFFFFFFFF) throw new IOException("invalid id mapping end guard"); + return new FullDataSource(dataFile.pos, mapping, data); + } + } + + private FullDataSource(DhSectionPos pos, IdBiomeBlockStateMap mapping, long[][] data) { + super(mapping, data, SECTION_SIZE); + LodUtil.assertTrue(data.length == SECTION_SIZE*SECTION_SIZE); + this.sectionPos = pos; + } + public static FullDataSource createEmpty(DhSectionPos pos) { return new FullDataSource(pos); } diff --git a/src/main/java/com/seibel/lod/core/a7/datatype/full/accessor/SingleFullArrayView.java b/src/main/java/com/seibel/lod/core/a7/datatype/full/accessor/SingleFullArrayView.java index 702f20dbf..d1bf9fe2a 100644 --- a/src/main/java/com/seibel/lod/core/a7/datatype/full/accessor/SingleFullArrayView.java +++ b/src/main/java/com/seibel/lod/core/a7/datatype/full/accessor/SingleFullArrayView.java @@ -33,6 +33,9 @@ public class SingleFullArrayView implements IFullDataView { if (x != 0 || z != 0) throw new IllegalArgumentException("Only contains 1 column of full data!"); return this; } + public long[] getRaw() { + return dataArrays[offset]; + } public long getSingle(int yIndex) { return dataArrays[offset][yIndex]; diff --git a/src/main/java/com/seibel/lod/core/wrapperInterfaces/IWrapperFactory.java b/src/main/java/com/seibel/lod/core/wrapperInterfaces/IWrapperFactory.java index c08e8f357..d272a1a51 100644 --- a/src/main/java/com/seibel/lod/core/wrapperInterfaces/IWrapperFactory.java +++ b/src/main/java/com/seibel/lod/core/wrapperInterfaces/IWrapperFactory.java @@ -25,6 +25,8 @@ import com.seibel.lod.core.wrapperInterfaces.block.IBlockStateWrapper; import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper; import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractBatchGenerationEnvionmentWrapper; +import java.io.IOException; + /** * This handles creating abstract wrapper objects. * @@ -34,7 +36,7 @@ import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractBatchGenera public interface IWrapperFactory extends IBindable { AbstractBatchGenerationEnvionmentWrapper createBatchGenerator(ILevel targetLevel); - IBiomeWrapper deserializeBiomeWrapper(String str); - IBlockStateWrapper deserializeBlockStateWrapper(String str); + IBiomeWrapper deserializeBiomeWrapper(String str) throws IOException; + IBlockStateWrapper deserializeBlockStateWrapper(String str) throws IOException; IBlockStateWrapper getAirBlockStateWrapper(); }