Full Data Source half done!
This commit is contained in:
@@ -16,6 +16,7 @@ public interface LodDataSource {
|
||||
byte getDataVersion();
|
||||
|
||||
|
||||
|
||||
// Saving related
|
||||
void saveData(ILevel level, DataMetaFile file, OutputStream dataStream) throws IOException;
|
||||
default File generateFilePathAndName(File levelFolderPath, ILevel level, DhSectionPos sectionPos) {
|
||||
|
||||
@@ -3,9 +3,11 @@ package com.seibel.lod.core.a7.datatype.full;
|
||||
import com.seibel.lod.core.a7.datatype.full.accessor.FullArrayView;
|
||||
|
||||
public class ChunkSizedData extends FullArrayView {
|
||||
private final long[][] chunkDataArray = new long[16*16][];
|
||||
public ChunkSizedData() {
|
||||
super(new IdBiomeBlockStateMap(), new long[16*16][0], 16);
|
||||
}
|
||||
|
||||
public ChunkSizedData(long[][] dataArrays) {
|
||||
super(dataArrays, 16);
|
||||
public void setSingleColumn(long[] data, int x, int z) {
|
||||
dataArrays[x*16+z] = data;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.seibel.lod.core.a7.datatype.full;
|
||||
|
||||
import com.seibel.lod.core.a7.datatype.column.ColumnRenderSource;
|
||||
import com.seibel.lod.core.a7.datatype.full.accessor.FullArrayView;
|
||||
import com.seibel.lod.core.a7.level.ILevel;
|
||||
import com.seibel.lod.core.a7.save.io.file.DataMetaFile;
|
||||
import com.seibel.lod.core.a7.datatype.LodDataSource;
|
||||
@@ -12,11 +14,15 @@ import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class FullDataSource implements LodDataSource { // 1 chunk
|
||||
private DhSectionPos sectionPos;
|
||||
ArrayList<String> idMap;
|
||||
protected FullDataSource() {
|
||||
idMap = new ArrayList<String>();
|
||||
public class FullDataSource extends FullArrayView implements LodDataSource { // 1 chunk
|
||||
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;
|
||||
private final DhSectionPos sectionPos;
|
||||
private int localVersion = 0;
|
||||
protected FullDataSource(DhSectionPos sectionPos) {
|
||||
super(new IdBiomeBlockStateMap(), new long[SECTION_SIZE*SECTION_SIZE][0], SECTION_SIZE);
|
||||
this.sectionPos = sectionPos;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -26,36 +32,21 @@ public class FullDataSource implements LodDataSource { // 1 chunk
|
||||
|
||||
@Override
|
||||
public byte getDataDetail() {
|
||||
return 0;
|
||||
return (byte) (sectionPos.sectionDetail-SECTION_SIZE_OFFSET);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLocalVersion(int localVer) {
|
||||
|
||||
localVersion = localVer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getDataVersion() {
|
||||
return 0;
|
||||
return LATEST_VERSION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveData(ILevel level, DataMetaFile file, OutputStream dataStream) throws IOException {
|
||||
|
||||
}
|
||||
|
||||
public static FullDataSource createNewFromChunk(IChunkWrapper chunk) {
|
||||
FullDataSource dataContainer = new FullDataSource();
|
||||
HashMap<String, Integer> idMap = new HashMap<String, Integer>();
|
||||
|
||||
idMap.put(IdMappingUtil.BLOCKSTATE_ID_AIR, 0);
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
int y = chunk.getMaxY(x, z);
|
||||
String currentBlockState = IdMappingUtil.BLOCKSTATE_ID_AIR;
|
||||
// FIXME: Move LodBuilder code to here
|
||||
}
|
||||
}
|
||||
return dataContainer;
|
||||
//TODO
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,35 +2,42 @@ package com.seibel.lod.core.a7.datatype.full;
|
||||
|
||||
// Static class for the data format:
|
||||
// ID: blockState id Y: Height(signed) DP: Depth(signed?)
|
||||
// BL: Block light SL: Sky light
|
||||
// =======Bit layout=======
|
||||
// __ __ __ __ __ __ __ __ <-- Top bits
|
||||
// BL BL BL BL SL SL SL SL <-- Top bits
|
||||
// YY YY YY YY YY YY YY YY
|
||||
// YY YY YY YY DP DP
|
||||
// DP DP DP DP DP DP DP DP DP DP
|
||||
// YY YY YY YY DP DP DP DP
|
||||
// DP DP DP DP DP DP DP DP
|
||||
// ID ID ID ID ID ID IO ID
|
||||
// ID ID ID ID ID ID IO ID
|
||||
// ID ID ID ID ID ID IO ID
|
||||
// ID ID ID ID ID ID IO ID <-- Bottom bits
|
||||
//
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
|
||||
public class FullFormat {
|
||||
|
||||
public static final int ID_WIDTH = 32;
|
||||
public static final int DP_WIDTH = 12;
|
||||
public static final int Y_WIDTH = 12;
|
||||
public static final int LIGHT_WIDTH = 8;
|
||||
public static final int ID_OFFSET = 0;
|
||||
public static final int DP_OFFSET = ID_OFFSET + ID_WIDTH;
|
||||
public static final int Y_OFFSET = DP_OFFSET + DP_WIDTH;
|
||||
public static final int LIGHT_OFFSET = Y_OFFSET + Y_WIDTH;
|
||||
|
||||
public static final int ID_MASK = (int)Math.pow(2, ID_WIDTH) - 1;
|
||||
|
||||
public static final long ID_MASK = Integer.MAX_VALUE;
|
||||
public static final long INVERSE_ID_MASK = ~ID_MASK;
|
||||
public static final int DP_MASK = (int)Math.pow(2, DP_WIDTH) - 1;
|
||||
public static final int Y_MASK = (int)Math.pow(2, Y_WIDTH) - 1;
|
||||
|
||||
public static long encode(int id, int depth, int y) {
|
||||
public static long encode(int id, int depth, int y, byte lightPair) {
|
||||
long data = 0;
|
||||
data |= id & ID_MASK;
|
||||
data |= (long) (depth & DP_MASK) << DP_OFFSET;
|
||||
data |= (long) (y & Y_MASK) << Y_OFFSET;
|
||||
data |= (long) lightPair << LIGHT_OFFSET;
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -46,4 +53,12 @@ public class FullFormat {
|
||||
return (int) (data << (64 - Y_OFFSET - Y_WIDTH) >> Y_OFFSET);
|
||||
}
|
||||
|
||||
public static byte getLight(long data) {
|
||||
return (byte) (data << (64 - LIGHT_OFFSET - LIGHT_WIDTH) >> LIGHT_OFFSET);
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
public static long remap(int[] mapping, long data) {
|
||||
return (data & INVERSE_ID_MASK) | mapping[(int)data];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.seibel.lod.core.a7.datatype.full;
|
||||
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
// WARNING: This is not THREAD-SAFE!
|
||||
public class IdBiomeBlockStateMap {
|
||||
public static final class Entry {
|
||||
public final IBiomeWrapper biome;
|
||||
public final IBlockStateWrapper blockState;
|
||||
public Entry(IBiomeWrapper biome, IBlockStateWrapper blockState) {
|
||||
this.biome = biome;
|
||||
this.blockState = blockState;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(biome, blockState);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final ArrayList<Entry> entries = new ArrayList<>();
|
||||
final HashMap<Entry, Integer> idMap = new HashMap<>();
|
||||
|
||||
public Entry get(int id) {
|
||||
return entries.get(id);
|
||||
}
|
||||
|
||||
public int setAndGetId(IBiomeWrapper biome, IBlockStateWrapper blockState) {
|
||||
return idMap.computeIfAbsent(new Entry(biome, blockState), (e) -> {
|
||||
int id = entries.size();
|
||||
entries.add(e);
|
||||
return id;
|
||||
});
|
||||
}
|
||||
public int setAndGetId(Entry biomeBlockStateEntry) {
|
||||
return idMap.computeIfAbsent(biomeBlockStateEntry, (e) -> {
|
||||
int id = entries.size();
|
||||
entries.add(e);
|
||||
return id;
|
||||
});
|
||||
}
|
||||
|
||||
public int[] computeAndMergeMapFrom(IdBiomeBlockStateMap target) {
|
||||
ArrayList<Entry> mergeEntry = target.entries;
|
||||
int[] mapper = new int[mergeEntry.size()];
|
||||
for (int i=0; i<mergeEntry.size(); i++) {
|
||||
mapper[i] = setAndGetId(mergeEntry.get(i));
|
||||
}
|
||||
return mapper;
|
||||
}
|
||||
|
||||
//TODO: Serialization & Deserialization
|
||||
}
|
||||
@@ -1,16 +1,21 @@
|
||||
package com.seibel.lod.core.a7.datatype.full.accessor;
|
||||
|
||||
public class FullArrayView implements IFullDataView {
|
||||
private final long[][] dataArrays;
|
||||
private final int offset;
|
||||
private final int size;
|
||||
import com.seibel.lod.core.a7.datatype.full.FullFormat;
|
||||
import com.seibel.lod.core.a7.datatype.full.IdBiomeBlockStateMap;
|
||||
|
||||
public FullArrayView(long[][] dataArrays, int size) {
|
||||
public class FullArrayView implements IFullDataView {
|
||||
protected final long[][] dataArrays;
|
||||
protected final int offset;
|
||||
protected final int size;
|
||||
protected final IdBiomeBlockStateMap mapping;
|
||||
|
||||
public FullArrayView(IdBiomeBlockStateMap mapping, long[][] dataArrays, int size) {
|
||||
if (dataArrays.length != size*size)
|
||||
throw new IllegalArgumentException(
|
||||
"tried constructing dataArrayView with invalid input!");
|
||||
this.dataArrays = dataArrays;
|
||||
this.size = size;
|
||||
this.mapping = mapping;
|
||||
offset = 0;
|
||||
}
|
||||
public FullArrayView(FullArrayView source, int size, int offsetX, int offsetZ) {
|
||||
@@ -19,17 +24,23 @@ public class FullArrayView implements IFullDataView {
|
||||
"tried constructing dataArrayView subview with invalid input!");
|
||||
dataArrays = source.dataArrays;
|
||||
this.size = size;
|
||||
mapping = source.mapping;
|
||||
offset = source.offset + offsetX * size + offsetZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdBiomeBlockStateMap getMapping() {
|
||||
return mapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingleFullArrayView get(int index) {
|
||||
return new SingleFullArrayView(dataArrays, index + offset);
|
||||
return new SingleFullArrayView(mapping, dataArrays, index + offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingleFullArrayView get(int x, int z) {
|
||||
return new SingleFullArrayView(dataArrays, x*size + z + offset);
|
||||
return new SingleFullArrayView(mapping, dataArrays, x*size + z + offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -42,12 +53,28 @@ public class FullArrayView implements IFullDataView {
|
||||
return new FullArrayView(this, size, ox, oz);
|
||||
}
|
||||
|
||||
public void copyTo(FullArrayView target) {
|
||||
//WARNING: It will potentially share the underlying array object!
|
||||
public void shadowCopyTo(FullArrayView target) {
|
||||
if (target.size != size)
|
||||
throw new IllegalArgumentException("Target view must have same size as this view");
|
||||
for (int x=0; x<size; x++) {
|
||||
System.arraycopy(dataArrays, offset+x*size,
|
||||
target.dataArrays, offset+x*size, size);
|
||||
if (target.mapping.equals(mapping)) {
|
||||
for (int x = 0; x < size; x++) {
|
||||
System.arraycopy(dataArrays, offset + x * size,
|
||||
target.dataArrays, offset + x * size, size);
|
||||
}
|
||||
}
|
||||
else {
|
||||
int[] map = target.mapping.computeAndMergeMapFrom(mapping);
|
||||
for (int x = 0; x < size; x++) {
|
||||
for (int o=x*size; o<x*size+size; o++) {
|
||||
long[] sourceData = dataArrays[offset+o];
|
||||
long[] newData = new long[sourceData.length];
|
||||
for (int i = 0; i < newData.length; i++) {
|
||||
newData[i] = FullFormat.remap(map, sourceData[i]);
|
||||
}
|
||||
target.dataArrays[target.offset+o] = newData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
package com.seibel.lod.core.a7.datatype.full.accessor;
|
||||
|
||||
import com.seibel.lod.core.a7.datatype.full.IdBiomeBlockStateMap;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
public interface IFullDataView {
|
||||
IdBiomeBlockStateMap getMapping();
|
||||
|
||||
SingleFullArrayView get(int index);
|
||||
SingleFullArrayView get(int x, int z);
|
||||
int width();
|
||||
|
||||
+26
-1
@@ -1,17 +1,27 @@
|
||||
package com.seibel.lod.core.a7.datatype.full.accessor;
|
||||
|
||||
import com.seibel.lod.core.a7.datatype.full.FullFormat;
|
||||
import com.seibel.lod.core.a7.datatype.full.IdBiomeBlockStateMap;
|
||||
|
||||
public class SingleFullArrayView implements IFullDataView {
|
||||
private final long[][] dataArrays;
|
||||
private final int offset;
|
||||
public SingleFullArrayView(long[][] dataArrays, int offset) {
|
||||
private final IdBiomeBlockStateMap mapping;
|
||||
public SingleFullArrayView(IdBiomeBlockStateMap mapping, long[][] dataArrays, int offset) {
|
||||
this.dataArrays = dataArrays;
|
||||
this.offset = offset;
|
||||
this.mapping = mapping;
|
||||
}
|
||||
|
||||
public boolean doesItExist() {
|
||||
return dataArrays[offset].length!=0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdBiomeBlockStateMap getMapping() {
|
||||
return mapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingleFullArrayView get(int index) {
|
||||
if (index != 0) throw new IllegalArgumentException("Only contains 1 column of full data!");
|
||||
@@ -46,4 +56,19 @@ public class SingleFullArrayView implements IFullDataView {
|
||||
return this;
|
||||
}
|
||||
|
||||
//WARNING: It will potentially share the underlying array object!
|
||||
public void shadowCopyTo(SingleFullArrayView target) {
|
||||
if (target.mapping.equals(mapping)) {
|
||||
target.dataArrays[target.offset] = dataArrays[offset];
|
||||
}
|
||||
else {
|
||||
int[] map = target.mapping.computeAndMergeMapFrom(mapping);
|
||||
long[] sourceData = dataArrays[offset];
|
||||
long[] newData = new long[sourceData.length];
|
||||
for (int i = 0; i < newData.length; i++) {
|
||||
newData[i] = FullFormat.remap(map, sourceData[i]);
|
||||
}
|
||||
target.dataArrays[target.offset] = newData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,57 @@
|
||||
package com.seibel.lod.core.a7.datatype.transform;
|
||||
|
||||
import com.seibel.lod.core.a7.datatype.full.ChunkSizedData;
|
||||
import com.seibel.lod.core.a7.datatype.full.FullFormat;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||
|
||||
public class LodDataBuilder {
|
||||
public static ChunkSizedData createChunkData(IChunkWrapper chunk) {
|
||||
if (!canGenerateLodFromChunk(chunk)) return null;
|
||||
|
||||
ChunkSizedData chunkData = new ChunkSizedData();
|
||||
|
||||
for (int x=0; x<16; x++) {
|
||||
for (int z=0; z<16; z++) {
|
||||
LongArrayList longs = new LongArrayList(chunk.getHeight()/4);
|
||||
int lastY = chunk.getMaxBuildHeight();
|
||||
IBiomeWrapper biome = chunk.getBiome(x, lastY, z);
|
||||
IBlockStateWrapper blockState = IBlockStateWrapper.AIR;
|
||||
int mappedId = chunkData.getMapping().setAndGetId(biome, blockState);
|
||||
byte light = (byte) (chunk.getBlockLight(x,lastY,z) << 4 + chunk.getSkyLight(x,lastY,z));
|
||||
int y=chunk.getMaxY(x, z);
|
||||
|
||||
for (; y>=chunk.getMinBuildHeight(); y--) {
|
||||
IBiomeWrapper newBiome = chunk.getBiome(x, y, z);
|
||||
IBlockStateWrapper newBlockState = chunk.getBlockState(x, y, z);
|
||||
byte newLight = (byte) (chunk.getBlockLight(x,y,z) << 4 + chunk.getSkyLight(x,y,z));
|
||||
|
||||
if (!newBiome.equals(biome) || !newBlockState.equals(blockState)) {
|
||||
longs.add(FullFormat.encode(mappedId, lastY-y+1, y+1, light));
|
||||
biome = newBiome;
|
||||
blockState = newBlockState;
|
||||
mappedId = chunkData.getMapping().setAndGetId(biome, blockState);
|
||||
light = newLight;
|
||||
lastY = y;
|
||||
} else if (newLight != light) {
|
||||
longs.add(FullFormat.encode(mappedId, lastY-y+1, y+1, light));
|
||||
light = newLight;
|
||||
lastY = y;
|
||||
}
|
||||
}
|
||||
longs.add(FullFormat.encode(mappedId, lastY-y+1, y+1, light));
|
||||
chunkData.setSingleColumn(longs.toArray((long[]) null), x, z);
|
||||
}
|
||||
}
|
||||
|
||||
return chunkData;
|
||||
}
|
||||
|
||||
public static boolean canGenerateLodFromChunk(IChunkWrapper chunk)
|
||||
{
|
||||
return chunk != null &&
|
||||
chunk.isLightCorrect();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,7 +215,6 @@ public class LodBuilder
|
||||
return chunk != null && chunk.isLightCorrect() && chunk.doesNearbyChunksExist();
|
||||
}
|
||||
|
||||
|
||||
private boolean writeAllLodNodeData(LodDimension lodDim, LodRegion region, int chunkX, int chunkZ,
|
||||
long[] data, LodBuilderConfig config, boolean override)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.seibel.lod.core.wrapperInterfaces.block;
|
||||
|
||||
public interface IBlockStateWrapper {
|
||||
IBlockStateWrapper AIR = null;
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import com.seibel.lod.core.enums.ELodDirection;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.IBindable;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockDetailWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||
|
||||
/**
|
||||
@@ -99,4 +100,6 @@ public interface IChunkWrapper extends IBindable
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
IBlockStateWrapper getBlockState(int x, int y, int z);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user