Rename and refactor several FullData source/view files

This commit is contained in:
James Seibel
2023-04-22 11:04:10 -05:00
parent ecbadfb8c6
commit d8e5d588d9
33 changed files with 501 additions and 475 deletions
@@ -1,7 +1,7 @@
package com.seibel.lod.core.dataObjects.fullData;
import com.seibel.lod.core.dataObjects.fullData.accessor.SingleFullArrayView;
import com.seibel.lod.core.dataObjects.fullData.sources.FullDataSource;
import com.seibel.lod.core.dataObjects.fullData.sources.CompleteFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.sources.IFullDataSource;
import com.seibel.lod.core.file.fullDatafile.IFullDataSourceProvider;
import com.seibel.lod.core.pos.DhLodPos;
@@ -17,23 +17,23 @@ public class FullDataDownSampler {
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
public static CompletableFuture<IFullDataSource> createDownSamplingFuture(DhSectionPos newTarget, IFullDataSourceProvider provider) {
// TODO: Make this future somehow run with lowest priority (to ensure ram usage stays low)
return createDownSamplingFuture(FullDataSource.createEmpty(newTarget), provider);
return createDownSamplingFuture(CompleteFullDataSource.createEmpty(newTarget), provider);
}
public static CompletableFuture<IFullDataSource> createDownSamplingFuture(FullDataSource target, IFullDataSourceProvider provider) {
int sectionSizeNeeded = 1 << target.getDataDetail();
public static CompletableFuture<IFullDataSource> createDownSamplingFuture(CompleteFullDataSource target, IFullDataSourceProvider provider) {
int sectionSizeNeeded = 1 << target.getDataDetailLevel();
ArrayList<CompletableFuture<IFullDataSource>> futures;
DhLodPos basePos = target.getSectionPos().getSectionBBoxPos().getCornerLodPos(FullDataSource.SECTION_SIZE_OFFSET);
if (sectionSizeNeeded <= FullDataSource.SECTION_SIZE_OFFSET) {
DhLodPos basePos = target.getSectionPos().getSectionBBoxPos().getCornerLodPos(CompleteFullDataSource.SECTION_SIZE_OFFSET);
if (sectionSizeNeeded <= CompleteFullDataSource.SECTION_SIZE_OFFSET) {
futures = new ArrayList<>(sectionSizeNeeded * sectionSizeNeeded);
for (int ox = 0; ox < sectionSizeNeeded; ox++) {
for (int oz = 0; oz < sectionSizeNeeded; oz++) {
CompletableFuture<IFullDataSource> future = provider.read(new DhSectionPos(
FullDataSource.SECTION_SIZE_OFFSET, basePos.x + ox, basePos.z + oz));
CompleteFullDataSource.SECTION_SIZE_OFFSET, basePos.x + ox, basePos.z + oz));
future = future.whenComplete((source, ex) -> {
if (ex == null && source != null && source instanceof FullDataSource) {
downSample(target, (FullDataSource) source);
if (ex == null && source != null && source instanceof CompleteFullDataSource) {
downSample(target, (CompleteFullDataSource) source);
} else if (ex != null) {
LOGGER.error("Error while down sampling", ex);
}
@@ -42,15 +42,15 @@ public class FullDataDownSampler {
}
}
} else {
futures = new ArrayList<>(FullDataSource.SECTION_SIZE * FullDataSource.SECTION_SIZE);
int multiplier = sectionSizeNeeded / FullDataSource.SECTION_SIZE;
for (int ox = 0; ox < FullDataSource.SECTION_SIZE; ox++) {
for (int oz = 0; oz < FullDataSource.SECTION_SIZE; oz++) {
futures = new ArrayList<>(CompleteFullDataSource.SECTION_SIZE * CompleteFullDataSource.SECTION_SIZE);
int multiplier = sectionSizeNeeded / CompleteFullDataSource.SECTION_SIZE;
for (int ox = 0; ox < CompleteFullDataSource.SECTION_SIZE; ox++) {
for (int oz = 0; oz < CompleteFullDataSource.SECTION_SIZE; oz++) {
CompletableFuture<IFullDataSource> future = provider.read(new DhSectionPos(
FullDataSource.SECTION_SIZE_OFFSET, basePos.x + ox * multiplier, basePos.z + oz * multiplier));
CompleteFullDataSource.SECTION_SIZE_OFFSET, basePos.x + ox * multiplier, basePos.z + oz * multiplier));
future = future.whenComplete((source, ex) -> {
if (ex == null && source != null && source instanceof FullDataSource) {
downSample(target, (FullDataSource) source);
if (ex == null && source != null && source instanceof CompleteFullDataSource) {
downSample(target, (CompleteFullDataSource) source);
} else if (ex != null) {
LOGGER.error("Error while down sampling", ex);
}
@@ -62,41 +62,41 @@ public class FullDataDownSampler {
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).thenApply(v -> target);
}
public static void downSample(FullDataSource target, FullDataSource source) {
public static void downSample(CompleteFullDataSource target, CompleteFullDataSource source) {
LodUtil.assertTrue(target.getSectionPos().overlaps(source.getSectionPos()));
LodUtil.assertTrue(target.getDataDetail() > source.getDataDetail());
LodUtil.assertTrue(target.getDataDetailLevel() > source.getDataDetailLevel());
byte detailDiff = (byte) (target.getDataDetail() - source.getDataDetail());
byte detailDiff = (byte) (target.getDataDetailLevel() - source.getDataDetailLevel());
DhSectionPos trgPos = target.getSectionPos();
DhSectionPos srcPos = source.getSectionPos();
if (detailDiff >= FullDataSource.SECTION_SIZE_OFFSET) {
if (detailDiff >= CompleteFullDataSource.SECTION_SIZE_OFFSET) {
// The source occupies only 1 datapoint in the target
// FIXME: TEMP method for down-sampling: take only the corner column
int sourceSectionPerTargetData = 1 << (detailDiff - FullDataSource.SECTION_SIZE_OFFSET);
int sourceSectionPerTargetData = 1 << (detailDiff - CompleteFullDataSource.SECTION_SIZE_OFFSET);
if (srcPos.sectionX % sourceSectionPerTargetData != 0 || srcPos.sectionZ % sourceSectionPerTargetData != 0) {
return;
}
DhLodPos trgOffset = trgPos.getCorner(target.getDataDetail());
DhLodPos srcOffset = srcPos.getSectionBBoxPos().convertToDetailLevel(target.getDataDetail());
DhLodPos trgOffset = trgPos.getCorner(target.getDataDetailLevel());
DhLodPos srcOffset = srcPos.getSectionBBoxPos().convertToDetailLevel(target.getDataDetailLevel());
int offsetX = trgOffset.x - srcOffset.x;
int offsetZ = trgOffset.z - srcOffset.z;
LodUtil.assertTrue(offsetX >= 0 && offsetX < FullDataSource.SECTION_SIZE
&& offsetZ >= 0 && offsetZ < FullDataSource.SECTION_SIZE);
LodUtil.assertTrue(offsetX >= 0 && offsetX < CompleteFullDataSource.SECTION_SIZE
&& offsetZ >= 0 && offsetZ < CompleteFullDataSource.SECTION_SIZE);
target.markNotEmpty();
source.get(0,0).deepCopyTo(target.get(offsetX, offsetZ));
} else if (detailDiff > 0) {
// The source occupies multiple data-points in the target
int srcDataPerTrgData = 1 << detailDiff;
int overlappedTrgDataSize = FullDataSource.SECTION_SIZE / srcDataPerTrgData;
int overlappedTrgDataSize = CompleteFullDataSource.SECTION_SIZE / srcDataPerTrgData;
DhLodPos trgOffset = trgPos.getCorner(target.getDataDetail());
DhLodPos srcOffset = srcPos.getSectionBBoxPos().getCornerLodPos(target.getDataDetail());
DhLodPos trgOffset = trgPos.getCorner(target.getDataDetailLevel());
DhLodPos srcOffset = srcPos.getSectionBBoxPos().getCornerLodPos(target.getDataDetailLevel());
int offsetX = trgOffset.x - srcOffset.x;
int offsetZ = trgOffset.z - srcOffset.z;
LodUtil.assertTrue(offsetX >= 0 && offsetX < FullDataSource.SECTION_SIZE
&& offsetZ >= 0 && offsetZ < FullDataSource.SECTION_SIZE);
LodUtil.assertTrue(offsetX >= 0 && offsetX < CompleteFullDataSource.SECTION_SIZE
&& offsetZ >= 0 && offsetZ < CompleteFullDataSource.SECTION_SIZE);
target.markNotEmpty();
for (int ox = 0; ox < overlappedTrgDataSize; ox++) {
@@ -0,0 +1,52 @@
package com.seibel.lod.core.dataObjects.fullData.accessor;
import com.seibel.lod.core.dataObjects.fullData.FullDataPointIdMap;
import com.seibel.lod.core.pos.DhChunkPos;
import com.seibel.lod.core.pos.DhLodPos;
import com.seibel.lod.core.util.LodUtil;
/**
* Contains the Full Data for a single chunk.
*/
public class ChunkSizedFullDataView extends FullDataArrayView
{
public final DhChunkPos pos;
// TODO replace this var with LodUtil.BLOCK_DETAIL_LEVEL
public final byte detailLevel = LodUtil.BLOCK_DETAIL_LEVEL;
public ChunkSizedFullDataView(DhChunkPos pos)
{
super(new FullDataPointIdMap(),
new long[LodUtil.CHUNK_WIDTH * LodUtil.CHUNK_WIDTH][0],
LodUtil.CHUNK_WIDTH);
this.pos = pos;
}
public void setSingleColumn(long[] data, int x, int z)
{
dataArrays[x * LodUtil.CHUNK_WIDTH + z] = data;
}
public long nonEmptyCount()
{
long count = 0;
for (long[] data : dataArrays)
{
if (data.length != 0)
{
count += 1;
}
}
return count;
}
public long emptyCount() { return LodUtil.CHUNK_WIDTH * LodUtil.CHUNK_WIDTH - nonEmptyCount(); }
public DhLodPos getLodPos() { return new DhLodPos(LodUtil.CHUNK_DETAIL_LEVEL, pos.x, pos.z); }
}
@@ -1,112 +0,0 @@
package com.seibel.lod.core.dataObjects.fullData.accessor;
import com.seibel.lod.core.dataObjects.fullData.FullDataPointIdMap;
import com.seibel.lod.core.util.FullDataPointUtil;
import com.seibel.lod.core.util.LodUtil;
public class FullArrayView implements IFullDataView
{
protected final long[][] dataArrays;
protected final int offset;
protected final int size;
protected final int dataSize;
protected final FullDataPointIdMap mapping;
public FullArrayView(FullDataPointIdMap 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.dataSize = size;
this.mapping = mapping;
this.offset = 0;
}
public FullArrayView(FullArrayView source, int size, int offsetX, int offsetZ)
{
if (source.size < size || source.size < size + offsetX || source.size < size + offsetZ)
{
throw new IllegalArgumentException("tried constructing dataArrayView subview with invalid input!");
}
this.dataArrays = source.dataArrays;
this.size = size;
this.dataSize = source.dataSize;
this.mapping = source.mapping;
this.offset = source.offset + offsetX * this.dataSize + offsetZ;
}
@Override
public FullDataPointIdMap getMapping() { return this.mapping; }
@Override
public SingleFullArrayView get(int index) { return this.get(index / this.size, index % this.size); }
@Override
public SingleFullArrayView get(int x, int z) { return new SingleFullArrayView(this.mapping, this.dataArrays, x * this.size + z + this.offset); }
@Override
public int width() { return this.size; }
@Override
public FullArrayView subView(int size, int xOffset, int zOffset) { return new FullArrayView(this, size, xOffset, zOffset); }
/** WARNING: This will potentially share the underlying array object! */
public void shadowCopyTo(FullArrayView target)
{
if (target.size != this.size)
{
throw new IllegalArgumentException("Target view must have same size as this view");
}
if (target.mapping.equals(this.mapping))
{
for (int x = 0; x < this.size; x++)
{
System.arraycopy(this.dataArrays, this.offset + x * this.dataSize,
target.dataArrays, target.offset + x * target.dataSize, this.size);
}
}
else
{
int[] remappedIds = target.mapping.mergeAndReturnRemappedEntityIds(this.mapping);
for (int x = 0; x < this.size; x++)
{
for (int o = 0; o < this.size; o++)
{
long[] sourceData = this.dataArrays[this.offset + x * this.dataSize + o];
long[] newData = new long[sourceData.length];
for (int i = 0; i < newData.length; i++)
{
newData[i] = FullDataPointUtil.remap(remappedIds, sourceData[i]);
}
target.dataArrays[target.offset + x * target.dataSize + o] = newData;
}
}
}
}
public void downsampleFrom(FullArrayView source)
{
LodUtil.assertTrue(source.size > this.size && source.size % this.size == 0);
int dataPerUnit = source.size / this.size;
for (int xOffset = 0; xOffset < this.size; xOffset++)
{
for (int zOffset = 0; zOffset < this.size; zOffset++)
{
SingleFullArrayView column = this.get(xOffset, zOffset);
column.downsampleFrom(source.subView(dataPerUnit, xOffset * dataPerUnit, zOffset * dataPerUnit));
}
}
}
}
@@ -0,0 +1,134 @@
package com.seibel.lod.core.dataObjects.fullData.accessor;
import com.seibel.lod.core.dataObjects.fullData.FullDataPointIdMap;
import com.seibel.lod.core.util.FullDataPointUtil;
import com.seibel.lod.core.util.LodUtil;
/**
*
*/
public class FullDataArrayView implements IFullDataView
{
protected final FullDataPointIdMap mapping;
protected final long[][] dataArrays;
/** measured in data points */
protected final int width;
/** measured in data points */
protected final int dataWidth;
protected final int offset;
//==============//
// constructors //
//==============//
public FullDataArrayView(FullDataPointIdMap mapping, long[][] dataArrays, int width)
{
if (dataArrays.length != width * width)
{
throw new IllegalArgumentException("tried constructing dataArrayView with invalid input!");
}
this.dataArrays = dataArrays;
this.width = width;
this.dataWidth = width;
this.mapping = mapping;
this.offset = 0;
}
public FullDataArrayView(FullDataArrayView source, int width, int offsetX, int offsetZ)
{
if (source.width < width || source.width < width + offsetX || source.width < width + offsetZ)
{
throw new IllegalArgumentException("tried constructing dataArrayView subview with invalid input!");
}
this.dataArrays = source.dataArrays;
this.width = width;
this.dataWidth = source.dataWidth;
this.mapping = source.mapping;
this.offset = source.offset + offsetX * this.dataWidth + offsetZ;
}
//=========//
// methods //
//=========//
@Override
public FullDataArrayView subView(int size, int xOffset, int zOffset) { return new FullDataArrayView(this, size, xOffset, zOffset); }
/** WARNING: This will potentially share the underlying array object! */
public void shadowCopyTo(FullDataArrayView target)
{
if (target.width != this.width)
{
throw new IllegalArgumentException("Target view must have same size as this view");
}
if (target.mapping.equals(this.mapping))
{
for (int x = 0; x < this.width; x++)
{
System.arraycopy(this.dataArrays, this.offset + x * this.dataWidth,
target.dataArrays, target.offset + x * target.dataWidth, this.width);
}
}
else
{
int[] remappedIds = target.mapping.mergeAndReturnRemappedEntityIds(this.mapping);
for (int x = 0; x < this.width; x++)
{
for (int z = 0; z < this.width; z++)
{
long[] sourceData = this.dataArrays[this.offset + x * this.dataWidth + z];
long[] newData = new long[sourceData.length];
for (int dataPointIndex = 0; dataPointIndex < newData.length; dataPointIndex++)
{
newData[dataPointIndex] = FullDataPointUtil.remap(remappedIds, sourceData[dataPointIndex]);
}
target.dataArrays[target.offset + x * target.dataWidth + z] = newData;
}
}
}
}
public void downsampleFrom(FullDataArrayView arrayView)
{
LodUtil.assertTrue(arrayView.width > this.width && arrayView.width % this.width == 0);
int dataPerUnit = arrayView.width / this.width;
for (int xOffset = 0; xOffset < this.width; xOffset++)
{
for (int zOffset = 0; zOffset < this.width; zOffset++)
{
SingleFullArrayView column = this.get(xOffset, zOffset);
column.downsampleFrom(arrayView.subView(dataPerUnit, xOffset * dataPerUnit, zOffset * dataPerUnit));
}
}
}
//=========//
// getters //
//=========//
@Override
public FullDataPointIdMap getMapping() { return this.mapping; }
@Override
public SingleFullArrayView get(int index) { return this.get(index / this.width, index % this.width); }
@Override
public SingleFullArrayView get(int relativeX, int relativeZ) { return new SingleFullArrayView(this.mapping, this.dataArrays, relativeX * this.width + relativeZ + this.offset); }
@Override
public int width() { return this.width; }
}
@@ -9,11 +9,18 @@ public interface IFullDataView
{
FullDataPointIdMap getMapping();
/** generally used for iterating through the whole data set */
SingleFullArrayView get(int index);
SingleFullArrayView get(int x, int z);
SingleFullArrayView get(int relativeX, int relativeZ);
/** measured in full data points */
int width();
IFullDataView subView(int size, int xOffset, int zOffset);
/** Returns an iterator that goes over each data column */
default Iterator<SingleFullArrayView> iterator()
{
@@ -34,6 +41,4 @@ public interface IFullDataView
};
}
IFullDataView subView(int size, int xOffset, int zOffset);
}
@@ -37,9 +37,9 @@ public class SingleFullArrayView implements IFullDataView
}
@Override
public SingleFullArrayView get(int x, int z)
public SingleFullArrayView get(int relativeX, int relativeZ)
{
if (x != 0 || z != 0)
if (relativeX != 0 || relativeZ != 0)
{
throw new IllegalArgumentException("Only contains 1 column of full data!");
}
@@ -1,7 +1,7 @@
package com.seibel.lod.core.dataObjects.fullData.loader;
import com.seibel.lod.core.dataObjects.fullData.sources.IFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.sources.FullDataSource;
import com.seibel.lod.core.dataObjects.fullData.sources.CompleteFullDataSource;
import com.seibel.lod.core.file.fullDatafile.FullDataMetaFile;
import com.seibel.lod.core.level.IDhLevel;
@@ -12,14 +12,14 @@ public class FullDataLoader extends AbstractFullDataSourceLoader
{
public FullDataLoader()
{
super(FullDataSource.class, FullDataSource.TYPE_ID, new byte[]{FullDataSource.LATEST_VERSION});
super(CompleteFullDataSource.class, CompleteFullDataSource.TYPE_ID, new byte[]{ CompleteFullDataSource.LATEST_VERSION});
}
@Override
public IFullDataSource loadData(FullDataMetaFile dataFile, BufferedInputStream bufferedInputStream, IDhLevel level) throws IOException, InterruptedException
{
//TODO: Add decompressor here
return FullDataSource.loadData(dataFile, bufferedInputStream, level);
return CompleteFullDataSource.loadData(dataFile, bufferedInputStream, level);
}
}
@@ -1,7 +1,7 @@
package com.seibel.lod.core.dataObjects.fullData.loader;
import com.seibel.lod.core.dataObjects.fullData.sources.IFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.sources.SingleChunkFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.sources.SpottyFullDataSource;
import com.seibel.lod.core.file.fullDatafile.FullDataMetaFile;
import com.seibel.lod.core.level.IDhLevel;
@@ -11,12 +11,12 @@ import java.io.IOException;
public class SingleChunkFullDataLoader extends AbstractFullDataSourceLoader
{
public SingleChunkFullDataLoader() {
super(SingleChunkFullDataSource.class, SingleChunkFullDataSource.TYPE_ID, new byte[]{ SingleChunkFullDataSource.LATEST_VERSION});
super(SpottyFullDataSource.class, SpottyFullDataSource.TYPE_ID, new byte[]{ SpottyFullDataSource.LATEST_VERSION});
}
@Override
public IFullDataSource loadData(FullDataMetaFile dataFile, BufferedInputStream bufferedInputStream, IDhLevel level) throws IOException, InterruptedException
{
return SingleChunkFullDataSource.loadData(dataFile, bufferedInputStream, level);
return SpottyFullDataSource.loadData(dataFile, bufferedInputStream, level);
}
}
@@ -1,45 +0,0 @@
package com.seibel.lod.core.dataObjects.fullData.sources;
import com.seibel.lod.core.dataObjects.fullData.FullDataPointIdMap;
import com.seibel.lod.core.dataObjects.fullData.accessor.FullArrayView;
import com.seibel.lod.core.pos.DhLodPos;
public class ChunkSizedFullDataSource extends FullArrayView
{
public final byte dataDetail;
public final int x;
public final int z;
public ChunkSizedFullDataSource(byte dataDetail, int x, int z)
{
super(new FullDataPointIdMap(), new long[16 * 16][0], 16);
this.dataDetail = dataDetail;
this.x = x;
this.z = z;
}
public void setSingleColumn(long[] data, int x, int z)
{
dataArrays[x * 16 + z] = data;
}
public long nonEmptyCount()
{
long count = 0;
for (long[] data : dataArrays)
{
if (data.length != 0)
count += 1;
}
return count;
}
public long emptyCount() { return 16 * 16 - nonEmptyCount(); }
public DhLodPos getBBoxLodPos() { return new DhLodPos((byte) (dataDetail + 4), x, z); }
}
@@ -2,7 +2,8 @@ package com.seibel.lod.core.dataObjects.fullData.sources;
import com.seibel.lod.api.enums.worldGeneration.EDhApiWorldGenerationStep;
import com.seibel.lod.core.dataObjects.fullData.FullDataPointIdMap;
import com.seibel.lod.core.dataObjects.fullData.accessor.FullArrayView;
import com.seibel.lod.core.dataObjects.fullData.accessor.ChunkSizedFullDataView;
import com.seibel.lod.core.dataObjects.fullData.accessor.FullDataArrayView;
import com.seibel.lod.core.dataObjects.fullData.accessor.SingleFullArrayView;
import com.seibel.lod.core.level.IDhLevel;
import com.seibel.lod.core.pos.DhBlockPos2D;
@@ -19,13 +20,13 @@ import java.io.*;
/**
*
*/
public class FullDataSource extends FullArrayView implements IFullDataSource
public class CompleteFullDataSource extends FullDataArrayView implements IFullDataSource
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
public static final byte SECTION_SIZE_OFFSET = 6;
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();
public static final long TYPE_ID = "CompleteFullDataSource".hashCode();
private final DhSectionPos sectionPos;
private boolean isEmpty = true;
@@ -33,13 +34,13 @@ public class FullDataSource extends FullArrayView implements IFullDataSource
// TODO why is this protected?
protected FullDataSource(DhSectionPos sectionPos)
protected CompleteFullDataSource(DhSectionPos sectionPos)
{
super(new FullDataPointIdMap(), new long[SECTION_SIZE*SECTION_SIZE][0], SECTION_SIZE);
this.sectionPos = sectionPos;
}
public FullDataSource(DhSectionPos pos, FullDataPointIdMap mapping, long[][] data)
public CompleteFullDataSource(DhSectionPos pos, FullDataPointIdMap mapping, long[][] data)
{
super(mapping, data, SECTION_SIZE);
LodUtil.assertTrue(data.length == SECTION_SIZE * SECTION_SIZE);
@@ -52,7 +53,7 @@ public class FullDataSource extends FullArrayView implements IFullDataSource
@Override
public DhSectionPos getSectionPos() { return this.sectionPos; }
@Override
public byte getDataDetail() { return (byte) (this.sectionPos.sectionDetailLevel -SECTION_SIZE_OFFSET); }
public byte getDataDetailLevel() { return (byte) (this.sectionPos.sectionDetailLevel -SECTION_SIZE_OFFSET); }
@Override
public byte getDataVersion() { return LATEST_VERSION; }
@@ -62,19 +63,19 @@ public class FullDataSource extends FullArrayView implements IFullDataSource
public EDhApiWorldGenerationStep getWorldGenStep() { return EDhApiWorldGenerationStep.EMPTY; }
@Override
public SingleFullArrayView tryGet(int x, int z) { return this.get(x, z); }
public SingleFullArrayView tryGet(int relativeX, int relativeZ) { return this.get(relativeX, relativeZ); }
@Override
public void update(ChunkSizedFullDataSource data)
public void update(ChunkSizedFullDataView chunkDataView)
{
LodUtil.assertTrue(this.sectionPos.getSectionBBoxPos().overlapsExactly(data.getBBoxLodPos()));
if (data.dataDetail == 0 && this.getDataDetail() == 0)
LodUtil.assertTrue(this.sectionPos.getSectionBBoxPos().overlapsExactly(chunkDataView.getLodPos()));
if (this.getDataDetailLevel() == 0)
{
DhBlockPos2D chunkBlockPos = new DhBlockPos2D(data.x * 16, data.z * 16);
DhBlockPos2D chunkBlockPos = new DhBlockPos2D(chunkDataView.pos.x * 16, chunkDataView.pos.z * 16);
DhBlockPos2D blockOffset = chunkBlockPos.subtract(this.sectionPos.getCorner().getCornerBlockPos());
LodUtil.assertTrue(blockOffset.x >= 0 && blockOffset.x < SECTION_SIZE && blockOffset.z >= 0 && blockOffset.z < SECTION_SIZE);
this.isEmpty = false;
data.shadowCopyTo(this.subView(16, blockOffset.x, blockOffset.z));
chunkDataView.shadowCopyTo(this.subView(16, blockOffset.x, blockOffset.z));
{ // DEBUG ASSERTION
for (int x = 0; x < 16; x++)
{
@@ -86,12 +87,12 @@ public class FullDataSource extends FullArrayView implements IFullDataSource
}
}
}
else if (data.dataDetail == 0 && this.getDataDetail() < 4)
else if (this.getDataDetailLevel() < 4)
{
int dataPerFull = 1 << this.getDataDetail();
int dataPerFull = 1 << this.getDataDetailLevel();
int fullSize = 16 / dataPerFull;
DhLodPos dataOffset = data.getBBoxLodPos().getCornerLodPos(this.getDataDetail());
DhLodPos baseOffset = this.sectionPos.getCorner(this.getDataDetail());
DhLodPos dataOffset = chunkDataView.getLodPos().getCornerLodPos(this.getDataDetailLevel());
DhLodPos baseOffset = this.sectionPos.getCorner(this.getDataDetailLevel());
int offsetX = dataOffset.x - baseOffset.x;
int offsetZ = dataOffset.z - baseOffset.z;
LodUtil.assertTrue(offsetX >= 0 && offsetX < SECTION_SIZE && offsetZ >= 0 && offsetZ < SECTION_SIZE);
@@ -101,26 +102,26 @@ public class FullDataSource extends FullArrayView implements IFullDataSource
for (int oz = 0; oz < fullSize; oz++)
{
SingleFullArrayView column = this.get(ox + offsetX, oz + offsetZ);
column.downsampleFrom(data.subView(dataPerFull, ox * dataPerFull, oz * dataPerFull));
column.downsampleFrom(chunkDataView.subView(dataPerFull, ox * dataPerFull, oz * dataPerFull));
}
}
}
else if (data.dataDetail == 0 && this.getDataDetail() >= 4)
else if (this.getDataDetailLevel() >= 4)
{
//FIXME: TEMPORARY
int chunkPerFull = 1 << (this.getDataDetail() - 4);
if (data.x % chunkPerFull != 0 || data.z % chunkPerFull != 0)
int chunkPerFull = 1 << (this.getDataDetailLevel() - 4);
if (chunkDataView.pos.x % chunkPerFull != 0 || chunkDataView.pos.z % chunkPerFull != 0)
{
return;
}
DhLodPos baseOffset = this.sectionPos.getCorner(this.getDataDetail());
DhLodPos dataOffset = data.getBBoxLodPos().convertToDetailLevel(this.getDataDetail());
DhLodPos baseOffset = this.sectionPos.getCorner(this.getDataDetailLevel());
DhLodPos dataOffset = chunkDataView.getLodPos().convertToDetailLevel(this.getDataDetailLevel());
int offsetX = dataOffset.x - baseOffset.x;
int offsetZ = dataOffset.z - baseOffset.z;
LodUtil.assertTrue(offsetX >= 0 && offsetX < SECTION_SIZE && offsetZ >= 0 && offsetZ < SECTION_SIZE);
this.isEmpty = false;
data.get(0, 0).deepCopyTo(this.get(offsetX, offsetZ));
chunkDataView.get(0, 0).deepCopyTo(this.get(offsetX, offsetZ));
}
else
{
@@ -136,7 +137,7 @@ public class FullDataSource extends FullArrayView implements IFullDataSource
public static FullDataSource loadData(FullDataMetaFile dataFile, BufferedInputStream bufferedInputStream, IDhLevel level) throws IOException, InterruptedException
public static CompleteFullDataSource loadData(FullDataMetaFile dataFile, BufferedInputStream bufferedInputStream, IDhLevel level) throws IOException, InterruptedException
{
DataInputStream dataInputStream = new DataInputStream(bufferedInputStream); // DO NOT CLOSE
@@ -164,7 +165,7 @@ public class FullDataSource extends FullArrayView implements IFullDataSource
if (end == IFullDataSource.NO_DATA_FLAG_BYTE)
{
// Section is empty
return new FullDataSource(dataFile.pos);
return new CompleteFullDataSource(dataFile.pos);
}
// Non-empty section
if (end != IFullDataSource.DATA_GUARD_BYTE)
@@ -211,7 +212,7 @@ public class FullDataSource extends FullArrayView implements IFullDataSource
throw new IOException("invalid id mapping end guard");
}
return new FullDataSource(dataFile.pos, mapping, data);
return new CompleteFullDataSource(dataFile.pos, mapping, data);
}
@Override
@@ -220,8 +221,8 @@ public class FullDataSource extends FullArrayView implements IFullDataSource
DataOutputStream dataOutputStream = new DataOutputStream(bufferedOutputStream); // DO NOT CLOSE
dataOutputStream.writeInt(this.getDataDetail());
dataOutputStream.writeInt(this.size);
dataOutputStream.writeInt(this.getDataDetailLevel());
dataOutputStream.writeInt(this.width);
dataOutputStream.writeInt(level.getMinY());
if (this.isEmpty)
{
@@ -231,9 +232,9 @@ public class FullDataSource extends FullArrayView implements IFullDataSource
dataOutputStream.writeInt(0xFFFFFFFF);
// Data array length
for (int x = 0; x < this.size; x++)
for (int x = 0; x < this.width; x++)
{
for (int z = 0; z < this.size; z++)
for (int z = 0; z < this.width; z++)
{
dataOutputStream.writeInt(this.get(x, z).getSingleLength());
}
@@ -241,9 +242,9 @@ public class FullDataSource extends FullArrayView implements IFullDataSource
// Data array content (only on non-empty columns)
dataOutputStream.writeInt(0xFFFFFFFF);
for (int x = 0; x < this.size; x++)
for (int x = 0; x < this.width; x++)
{
for (int z = 0; z < this.size; z++)
for (int z = 0; z < this.width; z++)
{
SingleFullArrayView column = this.get(x, z);
if (!column.doesItExist())
@@ -264,7 +265,7 @@ public class FullDataSource extends FullArrayView implements IFullDataSource
}
public static FullDataSource createEmpty(DhSectionPos pos) { return new FullDataSource(pos); }
public static CompleteFullDataSource createEmpty(DhSectionPos pos) { return new CompleteFullDataSource(pos); }
/** Returns whether data at the given posToWrite can effect the target region file at posToTest. */
public static boolean firstDataPosCanAffectSecond(DhSectionPos posToWrite, DhSectionPos posToTest)
@@ -298,7 +299,7 @@ public class FullDataSource extends FullArrayView implements IFullDataSource
}
}
public void writeFromLower(FullDataSource subData)
public void writeFromLower(CompleteFullDataSource subData)
{
LodUtil.assertTrue(this.sectionPos.overlaps(subData.sectionPos));
LodUtil.assertTrue(subData.sectionPos.sectionDetailLevel < this.sectionPos.sectionDetailLevel);
@@ -306,7 +307,7 @@ public class FullDataSource extends FullArrayView implements IFullDataSource
return;
DhSectionPos lowerSectPos = subData.sectionPos;
byte detailDiff = (byte) (this.sectionPos.sectionDetailLevel - subData.sectionPos.sectionDetailLevel);
byte targetDataDetail = this.getDataDetail();
byte targetDataDetail = this.getDataDetailLevel();
DhLodPos minDataPos = this.sectionPos.getCorner(targetDataDetail);
if (detailDiff <= SECTION_SIZE_OFFSET)
{
@@ -2,8 +2,8 @@ package com.seibel.lod.core.dataObjects.fullData.sources;
import com.seibel.lod.api.enums.worldGeneration.EDhApiWorldGenerationStep;
import com.seibel.lod.core.dataObjects.fullData.FullDataPointIdMap;
import com.seibel.lod.core.dataObjects.fullData.accessor.ChunkSizedFullDataView;
import com.seibel.lod.core.dataObjects.fullData.accessor.SingleFullArrayView;
import com.seibel.lod.core.dataObjects.fullData.sources.ChunkSizedFullDataSource;
import com.seibel.lod.core.file.fullDatafile.FullDataMetaFile;
import com.seibel.lod.core.level.IDhLevel;
import com.seibel.lod.core.pos.DhSectionPos;
@@ -13,7 +13,7 @@ import java.io.IOException;
// TODO make into an abstract class so the read(stream) method can be used as a constructor
// TODO validate how we know which file to use when (probably, TYPE_ID)
// TODO merge with FullArrayView and IFullDataView
// TODO merge with FullDataArrayView and IFullDataView
public interface IFullDataSource
{
/**
@@ -28,11 +28,11 @@ public interface IFullDataSource
public abstract DhSectionPos getSectionPos();
public abstract byte getDataDetail();
public abstract byte getDataDetailLevel();
public abstract byte getDataVersion();
public abstract EDhApiWorldGenerationStep getWorldGenStep();
public abstract void update(ChunkSizedFullDataSource data);
public abstract void update(ChunkSizedFullDataView data);
public abstract boolean isEmpty();
@@ -69,7 +69,7 @@ public interface IFullDataSource
* Attempts to get the data column for the given relative x and z position.
* @return null if the data doesn't exist
*/
public abstract SingleFullArrayView tryGet(int x, int z);
public abstract SingleFullArrayView tryGet(int relativeX, int relativeZ);
public abstract FullDataPointIdMap getMapping();
@@ -4,6 +4,11 @@ public interface IIncompleteFullDataSource extends IFullDataSource
{
void sampleFrom(IFullDataSource fullDataSource);
IFullDataSource trySelfPromote();
/**
* Attempts to convert this {@link IIncompleteFullDataSource} into a {@link CompleteFullDataSource}.
*
* @return this if the promotion failed, a new {@link CompleteFullDataSource} if successful.
*/
IFullDataSource tryPromotingToCompleteDataSource();
}
@@ -2,7 +2,8 @@ package com.seibel.lod.core.dataObjects.fullData.sources;
import com.seibel.lod.api.enums.worldGeneration.EDhApiWorldGenerationStep;
import com.seibel.lod.core.dataObjects.fullData.FullDataPointIdMap;
import com.seibel.lod.core.dataObjects.fullData.accessor.FullArrayView;
import com.seibel.lod.core.dataObjects.fullData.accessor.ChunkSizedFullDataView;
import com.seibel.lod.core.dataObjects.fullData.accessor.FullDataArrayView;
import com.seibel.lod.core.dataObjects.fullData.accessor.SingleFullArrayView;
import com.seibel.lod.core.file.fullDatafile.FullDataMetaFile;
import com.seibel.lod.core.level.IDhLevel;
@@ -18,7 +19,7 @@ import java.util.BitSet;
/**
* Handles full data with the detail level {@link SparseFullDataSource#SPARSE_UNIT_DETAIL}.
* In other words, this is the middle ground between {@link SingleChunkFullDataSource} and {@link FullDataSource}
* In other words, this is the middle ground between {@link SpottyFullDataSource} and {@link CompleteFullDataSource}
*/
public class SparseFullDataSource implements IIncompleteFullDataSource
{
@@ -42,7 +43,7 @@ public class SparseFullDataSource implements IIncompleteFullDataSource
protected final FullDataPointIdMap mapping;
private final DhSectionPos sectionPos;
private final FullArrayView[] sparseData;
private final FullDataArrayView[] sparseData;
private final DhLodPos chunkPos;
public final int chunks;
@@ -63,12 +64,12 @@ public class SparseFullDataSource implements IIncompleteFullDataSource
this.sectionPos = sectionPos;
this.chunks = 1 << (byte) (sectionPos.sectionDetailLevel - SPARSE_UNIT_DETAIL);
this.dataPerChunk = SECTION_SIZE / this.chunks;
this.sparseData = new FullArrayView[this.chunks * this.chunks];
this.sparseData = new FullDataArrayView[this.chunks * this.chunks];
this.chunkPos = sectionPos.getCorner(SPARSE_UNIT_DETAIL);
this.mapping = new FullDataPointIdMap();
}
protected SparseFullDataSource(DhSectionPos sectionPos, FullDataPointIdMap mapping, FullArrayView[] data)
protected SparseFullDataSource(DhSectionPos sectionPos, FullDataPointIdMap mapping, FullDataArrayView[] data)
{
LodUtil.assertTrue(sectionPos.sectionDetailLevel > SPARSE_UNIT_DETAIL);
LodUtil.assertTrue(sectionPos.sectionDetailLevel <= MAX_SECTION_DETAIL);
@@ -91,7 +92,7 @@ public class SparseFullDataSource implements IIncompleteFullDataSource
@Override
public DhSectionPos getSectionPos() { return this.sectionPos; }
@Override
public byte getDataDetail() { return (byte) (this.sectionPos.sectionDetailLevel -SECTION_SIZE_OFFSET); }
public byte getDataDetailLevel() { return (byte) (this.sectionPos.sectionDetailLevel - SECTION_SIZE_OFFSET); }
@Override
public byte getDataVersion() { return LATEST_VERSION; }
@@ -113,19 +114,13 @@ public class SparseFullDataSource implements IIncompleteFullDataSource
@Override
public void update(ChunkSizedFullDataSource data)
public void update(ChunkSizedFullDataView chunkDataView)
{
if (data.dataDetail != 0)
int arrayOffset = this.calculateOffset(chunkDataView.pos.x, chunkDataView.pos.z);
FullDataArrayView newArray = new FullDataArrayView(this.mapping, new long[this.dataPerChunk * this.dataPerChunk][], this.dataPerChunk);
if (this.getDataDetailLevel() == chunkDataView.detailLevel)
{
//TODO: Disable the throw and instead just ignore the data.
throw new IllegalArgumentException("SparseFullDataSource only supports dataDetail 0!");
}
int arrayOffset = this.calculateOffset(data.x, data.z);
FullArrayView newArray = new FullArrayView(this.mapping, new long[this.dataPerChunk * this.dataPerChunk][], this.dataPerChunk);
if (this.getDataDetail() == data.dataDetail)
{
data.shadowCopyTo(newArray);
chunkDataView.shadowCopyTo(newArray);
}
else
{
@@ -137,10 +132,11 @@ public class SparseFullDataSource implements IIncompleteFullDataSource
for (int zOffset = 0; zOffset < count; zOffset++)
{
SingleFullArrayView column = newArray.get(xOffset, zOffset);
column.downsampleFrom(data.subView(dataPerCount, xOffset * dataPerCount, zOffset * dataPerCount));
column.downsampleFrom(chunkDataView.subView(dataPerCount, xOffset * dataPerCount, zOffset * dataPerCount));
}
}
}
this.isEmpty = false;
this.sparseData[arrayOffset] = newArray;
}
@@ -165,9 +161,9 @@ public class SparseFullDataSource implements IIncompleteFullDataSource
{
this.sampleFrom((SparseFullDataSource) source);
}
else if (source instanceof FullDataSource)
else if (source instanceof CompleteFullDataSource)
{
this.sampleFrom((FullDataSource) source);
this.sampleFrom((CompleteFullDataSource) source);
}
else
{
@@ -190,17 +186,17 @@ public class SparseFullDataSource implements IIncompleteFullDataSource
{
for (int zOffset = 0; zOffset < sparseSource.chunks; zOffset++)
{
FullArrayView sourceChunk = sparseSource.sparseData[xOffset * sparseSource.chunks + zOffset];
FullDataArrayView sourceChunk = sparseSource.sparseData[xOffset * sparseSource.chunks + zOffset];
if (sourceChunk != null)
{
FullArrayView buff = new FullArrayView(this.mapping, new long[this.dataPerChunk * this.dataPerChunk][], this.dataPerChunk);
FullDataArrayView buff = new FullDataArrayView(this.mapping, new long[this.dataPerChunk * this.dataPerChunk][], this.dataPerChunk);
buff.downsampleFrom(sourceChunk);
this.sparseData[(xOffset + offsetX) * this.chunks + (zOffset + offsetZ)] = buff;
}
}
}
}
private void sampleFrom(FullDataSource fullSource)
private void sampleFrom(CompleteFullDataSource fullSource)
{
DhSectionPos pos = fullSource.getSectionPos();
this.isEmpty = false;
@@ -208,8 +204,8 @@ public class SparseFullDataSource implements IIncompleteFullDataSource
DhLodPos basePos = this.sectionPos.getCorner(SPARSE_UNIT_DETAIL);
DhLodPos dataPos = pos.getCorner(SPARSE_UNIT_DETAIL);
int coveredChunks = pos.getWidth(SPARSE_UNIT_DETAIL).numberOfLodSectionsWide;
int sourceDataPerChunk = SPARSE_UNIT_SIZE >>> fullSource.getDataDetail();
LodUtil.assertTrue(coveredChunks*sourceDataPerChunk == FullDataSource.SECTION_SIZE);
int sourceDataPerChunk = SPARSE_UNIT_SIZE >>> fullSource.getDataDetailLevel();
LodUtil.assertTrue(coveredChunks*sourceDataPerChunk == CompleteFullDataSource.SECTION_SIZE);
int offsetX = dataPos.x-basePos.x;
int offsetZ = dataPos.z-basePos.z;
LodUtil.assertTrue(offsetX >=0 && offsetX < this.chunks && offsetZ >=0 && offsetZ < this.chunks);
@@ -218,8 +214,8 @@ public class SparseFullDataSource implements IIncompleteFullDataSource
{
for (int zOffset = 0; zOffset < coveredChunks; zOffset++)
{
FullArrayView sourceChunk = fullSource.subView(sourceDataPerChunk, xOffset * sourceDataPerChunk, zOffset * sourceDataPerChunk);
FullArrayView buff = new FullArrayView(this.mapping, new long[this.dataPerChunk * this.dataPerChunk][], this.dataPerChunk);
FullDataArrayView sourceChunk = fullSource.subView(sourceDataPerChunk, xOffset * sourceDataPerChunk, zOffset * sourceDataPerChunk);
FullDataArrayView buff = new FullDataArrayView(this.mapping, new long[this.dataPerChunk * this.dataPerChunk][], this.dataPerChunk);
buff.downsampleFrom(sourceChunk);
this.sparseData[(xOffset + offsetX) * this.chunks + (zOffset + offsetZ)] = buff;
}
@@ -238,7 +234,7 @@ public class SparseFullDataSource implements IIncompleteFullDataSource
DataOutputStream dataOutputStream = new DataOutputStream(bufferedOutputStream);
dataOutputStream.writeShort(this.getDataDetail());
dataOutputStream.writeShort(this.getDataDetailLevel());
dataOutputStream.writeShort(SPARSE_UNIT_DETAIL);
dataOutputStream.writeInt(SECTION_SIZE);
dataOutputStream.writeInt(level.getMinY());
@@ -266,7 +262,7 @@ public class SparseFullDataSource implements IIncompleteFullDataSource
i = dataArrayIndexHasData.nextSetBit(i+1))
{
// column data length
FullArrayView array = this.sparseData[i];
FullDataArrayView array = this.sparseData[i];
LodUtil.assertTrue(array != null);
for (int x = 0; x < array.width(); x++)
{
@@ -451,12 +447,12 @@ public class SparseFullDataSource implements IIncompleteFullDataSource
throw new IOException("invalid id mapping end guard");
}
FullArrayView[] fullDataArrays = new FullArrayView[chunks * chunks];
FullDataArrayView[] fullDataArrays = new FullDataArrayView[chunks * chunks];
for (int i = 0; i < rawFullDataArrays.length; i++)
{
if (rawFullDataArrays[i] != null)
{
fullDataArrays[i] = new FullArrayView(mapping, rawFullDataArrays[i], dataPointsPerChunk);
fullDataArrays[i] = new FullDataArrayView(mapping, rawFullDataArrays[i], dataPointsPerChunk);
}
}
@@ -466,53 +462,58 @@ public class SparseFullDataSource implements IIncompleteFullDataSource
private void applyToFullDataSource(FullDataSource dataSource)
private void applyToFullDataSource(CompleteFullDataSource dataSource)
{
LodUtil.assertTrue(dataSource.getSectionPos().equals(this.sectionPos));
LodUtil.assertTrue(dataSource.getDataDetail() == this.getDataDetail());
LodUtil.assertTrue(dataSource.getDataDetailLevel() == this.getDataDetailLevel());
for (int x = 0; x < this.chunks; x++)
{
for (int z = 0; z < this.chunks; z++)
{
FullArrayView array = this.sparseData[x * this.chunks + z];
FullDataArrayView array = this.sparseData[x * this.chunks + z];
if (array == null)
continue;
// Otherwise, apply data to dataSource
dataSource.markNotEmpty();
FullArrayView view = dataSource.subView(this.dataPerChunk, x * this.dataPerChunk, z * this.dataPerChunk);
FullDataArrayView view = dataSource.subView(this.dataPerChunk, x * this.dataPerChunk, z * this.dataPerChunk);
array.shadowCopyTo(view);
}
}
}
public IFullDataSource trySelfPromote()
public IFullDataSource tryPromotingToCompleteDataSource()
{
if (this.isEmpty)
{
return this;
}
for (FullArrayView array : this.sparseData)
// promotion can only succeed if every data column is present
for (FullDataArrayView array : this.sparseData)
{
if (array == null) return this;
}
FullDataSource newSource = FullDataSource.createEmpty(this.sectionPos);
this.applyToFullDataSource(newSource);
return newSource;
if (array == null)
{
return this;
}
}
CompleteFullDataSource fullDataSource = CompleteFullDataSource.createEmpty(this.sectionPos);
this.applyToFullDataSource(fullDataSource);
return fullDataSource;
}
public SingleFullArrayView tryGet(int x, int z)
public SingleFullArrayView tryGet(int relativeX, int relativeZ)
{
LodUtil.assertTrue(x>=0 && x<SECTION_SIZE && z>=0 && z<SECTION_SIZE);
int chunkX = x / this.dataPerChunk;
int chunkZ = z / this.dataPerChunk;
FullArrayView chunk = this.sparseData[chunkX * this.chunks + chunkZ];
LodUtil.assertTrue(relativeX >=0 && relativeX <SECTION_SIZE && relativeZ >=0 && relativeZ <SECTION_SIZE);
int chunkX = relativeX / this.dataPerChunk;
int chunkZ = relativeZ / this.dataPerChunk;
FullDataArrayView chunk = this.sparseData[chunkX * this.chunks + chunkZ];
if (chunk == null)
{
return null;
}
return chunk.get(x % this.dataPerChunk, z % this.dataPerChunk);
return chunk.get(relativeX % this.dataPerChunk, relativeZ % this.dataPerChunk);
}
}
@@ -2,7 +2,8 @@ package com.seibel.lod.core.dataObjects.fullData.sources;
import com.seibel.lod.api.enums.worldGeneration.EDhApiWorldGenerationStep;
import com.seibel.lod.core.dataObjects.fullData.FullDataPointIdMap;
import com.seibel.lod.core.dataObjects.fullData.accessor.FullArrayView;
import com.seibel.lod.core.dataObjects.fullData.accessor.ChunkSizedFullDataView;
import com.seibel.lod.core.dataObjects.fullData.accessor.FullDataArrayView;
import com.seibel.lod.core.dataObjects.fullData.accessor.SingleFullArrayView;
import com.seibel.lod.core.file.fullDatafile.FullDataMetaFile;
import com.seibel.lod.core.level.IDhLevel;
@@ -16,15 +17,16 @@ import java.io.*;
import java.util.BitSet;
/**
* 1 chunk of full data (formerly SpottyDataSource)
* more data than sparse, less than complete.
* TODO there has to be a better way to name these
*/
public class SingleChunkFullDataSource extends FullArrayView implements IIncompleteFullDataSource
public class SpottyFullDataSource extends FullDataArrayView implements IIncompleteFullDataSource
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
public static final byte SECTION_SIZE_OFFSET = 6;
public static final int SECTION_SIZE = 1 << SECTION_SIZE_OFFSET;
public static final byte LATEST_VERSION = 0;
public static final long TYPE_ID = "SingleChunkFullDataSource".hashCode();
public static final long TYPE_ID = "SpottyFullDataSource".hashCode();
private final DhSectionPos sectionPos;
private final BitSet isColumnNotEmpty;
@@ -38,7 +40,7 @@ public class SingleChunkFullDataSource extends FullArrayView implements IIncompl
// constructors //
//==============//
protected SingleChunkFullDataSource(DhSectionPos sectionPos)
protected SpottyFullDataSource(DhSectionPos sectionPos)
{
super(new FullDataPointIdMap(), new long[SECTION_SIZE*SECTION_SIZE][0], SECTION_SIZE);
LodUtil.assertTrue(sectionPos.sectionDetailLevel > SparseFullDataSource.MAX_SECTION_DETAIL);
@@ -48,7 +50,7 @@ public class SingleChunkFullDataSource extends FullArrayView implements IIncompl
this.worldGenStep = EDhApiWorldGenerationStep.EMPTY;
}
private SingleChunkFullDataSource(DhSectionPos pos, FullDataPointIdMap mapping, EDhApiWorldGenerationStep worldGenStep, BitSet isColumnNotEmpty, long[][] data)
private SpottyFullDataSource(DhSectionPos pos, FullDataPointIdMap mapping, EDhApiWorldGenerationStep worldGenStep, BitSet isColumnNotEmpty, long[][] data)
{
super(mapping, data, SECTION_SIZE);
LodUtil.assertTrue(data.length == SECTION_SIZE*SECTION_SIZE);
@@ -59,7 +61,7 @@ public class SingleChunkFullDataSource extends FullArrayView implements IIncompl
this.isEmpty = false;
}
public static SingleChunkFullDataSource createEmpty(DhSectionPos pos) { return new SingleChunkFullDataSource(pos); }
public static SpottyFullDataSource createEmpty(DhSectionPos pos) { return new SpottyFullDataSource(pos); }
@@ -67,7 +69,7 @@ public class SingleChunkFullDataSource extends FullArrayView implements IIncompl
// file handling //
//===============//
public static SingleChunkFullDataSource loadData(FullDataMetaFile dataFile, BufferedInputStream bufferedInputStream, IDhLevel level) throws IOException, InterruptedException
public static SpottyFullDataSource loadData(FullDataMetaFile dataFile, BufferedInputStream bufferedInputStream, IDhLevel level) throws IOException, InterruptedException
{
DataInputStream dataInputStream = new DataInputStream(bufferedInputStream); // DO NOT CLOSE
@@ -91,7 +93,7 @@ public class SingleChunkFullDataSource extends FullArrayView implements IIncompl
if (end == IFullDataSource.NO_DATA_FLAG_BYTE)
{
// Section is empty
return new SingleChunkFullDataSource(dataFile.pos);
return new SpottyFullDataSource(dataFile.pos);
}
@@ -160,7 +162,7 @@ public class SingleChunkFullDataSource extends FullArrayView implements IIncompl
return new SingleChunkFullDataSource(dataFile.pos, mapping, worldGenStep, isColumnNotEmpty, data);
return new SpottyFullDataSource(dataFile.pos, mapping, worldGenStep, isColumnNotEmpty, data);
}
@Override
@@ -169,8 +171,8 @@ public class SingleChunkFullDataSource extends FullArrayView implements IIncompl
DataOutputStream dataOutputStream = new DataOutputStream(bufferedOutputStream); // DO NOT CLOSE
dataOutputStream.writeInt(this.getDataDetail());
dataOutputStream.writeInt(this.size);
dataOutputStream.writeInt(this.getDataDetailLevel());
dataOutputStream.writeInt(this.width);
dataOutputStream.writeInt(level.getMinY());
if (this.isEmpty)
{
@@ -216,18 +218,21 @@ public class SingleChunkFullDataSource extends FullArrayView implements IIncompl
//===============//
@Override
public void update(ChunkSizedFullDataSource data)
public void update(ChunkSizedFullDataView data)
{
LodUtil.assertTrue(this.sectionPos.getSectionBBoxPos().overlapsExactly(data.getBBoxLodPos()));
LodUtil.assertTrue(this.sectionPos.getSectionBBoxPos().overlapsExactly(data.getLodPos()));
if (data.dataDetail == 0 && this.getDataDetail() >= 4)
if (this.getDataDetailLevel() >= 4)
{
//FIXME: TEMPORARY
int chunkPerFull = 1 << (this.getDataDetail() - 4);
if (data.x % chunkPerFull != 0 || data.z % chunkPerFull != 0)
int chunkPerFull = 1 << (this.getDataDetailLevel() - 4);
if (data.pos.x % chunkPerFull != 0 || data.pos.z % chunkPerFull != 0)
{
return;
DhLodPos baseOffset = this.sectionPos.getCorner(this.getDataDetail());
DhLodPos dataOffset = data.getBBoxLodPos().convertToDetailLevel(this.getDataDetail());
}
DhLodPos baseOffset = this.sectionPos.getCorner(this.getDataDetailLevel());
DhLodPos dataOffset = data.getLodPos().convertToDetailLevel(this.getDataDetailLevel());
int offsetX = dataOffset.x - baseOffset.x;
int offsetZ = dataOffset.z - baseOffset.z;
LodUtil.assertTrue(offsetX >= 0 && offsetX < SECTION_SIZE && offsetZ >= 0 && offsetZ < SECTION_SIZE);
@@ -255,9 +260,9 @@ public class SingleChunkFullDataSource extends FullArrayView implements IIncompl
{
this.sampleFrom((SparseFullDataSource) source);
}
else if (source instanceof FullDataSource)
else if (source instanceof CompleteFullDataSource)
{
this.sampleFrom((FullDataSource) source);
this.sampleFrom((CompleteFullDataSource) source);
}
else
{
@@ -270,15 +275,15 @@ public class SingleChunkFullDataSource extends FullArrayView implements IIncompl
DhSectionPos pos = sparseSource.getSectionPos();
this.isEmpty = false;
if (this.getDataDetail() > this.sectionPos.sectionDetailLevel)
if (this.getDataDetailLevel() > this.sectionPos.sectionDetailLevel)
{
DhLodPos basePos = this.sectionPos.getCorner(this.getDataDetail());
DhLodPos dataPos = pos.getCorner(this.getDataDetail());
DhLodPos basePos = this.sectionPos.getCorner(this.getDataDetailLevel());
DhLodPos dataPos = pos.getCorner(this.getDataDetailLevel());
int offsetX = dataPos.x - basePos.x;
int offsetZ = dataPos.z - basePos.z;
LodUtil.assertTrue(offsetX >= 0 && offsetX < SECTION_SIZE && offsetZ >= 0 && offsetZ < SECTION_SIZE);
int chunksPerData = 1 << (this.getDataDetail() - SparseFullDataSource.SPARSE_UNIT_DETAIL);
int dataSpan = this.sectionPos.getWidth(this.getDataDetail()).numberOfLodSectionsWide;
int chunksPerData = 1 << (this.getDataDetailLevel() - SparseFullDataSource.SPARSE_UNIT_DETAIL);
int dataSpan = this.sectionPos.getWidth(this.getDataDetailLevel()).numberOfLodSectionsWide;
for (int xOffset = 0; xOffset < dataSpan; xOffset++)
{
@@ -302,8 +307,8 @@ public class SingleChunkFullDataSource extends FullArrayView implements IIncompl
int lowerSectionsPerData = this.sectionPos.getWidth(dataPos.detailLevel).numberOfLodSectionsWide;
if (dataPos.x % lowerSectionsPerData != 0 || dataPos.z % lowerSectionsPerData != 0) return;
DhLodPos basePos = this.sectionPos.getCorner(this.getDataDetail());
dataPos = dataPos.convertToDetailLevel(this.getDataDetail());
DhLodPos basePos = this.sectionPos.getCorner(this.getDataDetailLevel());
dataPos = dataPos.convertToDetailLevel(this.getDataDetailLevel());
int offsetX = dataPos.x - basePos.x;
int offsetZ = dataPos.z - basePos.z;
SingleFullArrayView column = sparseSource.tryGet(0, 0);
@@ -314,19 +319,19 @@ public class SingleChunkFullDataSource extends FullArrayView implements IIncompl
}
}
private void sampleFrom(FullDataSource fullSource)
private void sampleFrom(CompleteFullDataSource fullSource)
{
DhSectionPos pos = fullSource.getSectionPos();
this.isEmpty = false;
this.downsampleFrom(fullSource);
if (this.getDataDetail() > this.sectionPos.sectionDetailLevel)
if (this.getDataDetailLevel() > this.sectionPos.sectionDetailLevel)
{
DhLodPos basePos = this.sectionPos.getCorner(this.getDataDetail());
DhLodPos dataPos = pos.getCorner(this.getDataDetail());
DhLodPos basePos = this.sectionPos.getCorner(this.getDataDetailLevel());
DhLodPos dataPos = pos.getCorner(this.getDataDetailLevel());
int offsetX = dataPos.x - basePos.x;
int offsetZ = dataPos.z - basePos.z;
int dataSpan = this.sectionPos.getWidth(this.getDataDetail()).numberOfLodSectionsWide;
int dataSpan = this.sectionPos.getWidth(this.getDataDetailLevel()).numberOfLodSectionsWide;
for (int xOffset = 0; xOffset < dataSpan; xOffset++)
{
@@ -345,8 +350,8 @@ public class SingleChunkFullDataSource extends FullArrayView implements IIncompl
return;
}
DhLodPos basePos = this.sectionPos.getCorner(this.getDataDetail());
dataPos = dataPos.convertToDetailLevel(this.getDataDetail());
DhLodPos basePos = this.sectionPos.getCorner(this.getDataDetailLevel());
dataPos = dataPos.convertToDetailLevel(this.getDataDetailLevel());
int offsetX = dataPos.x - basePos.x;
int offsetZ = dataPos.z - basePos.z;
this.isColumnNotEmpty.set(offsetX * SECTION_SIZE + offsetZ, true);
@@ -355,19 +360,19 @@ public class SingleChunkFullDataSource extends FullArrayView implements IIncompl
}
@Override
public IFullDataSource trySelfPromote()
public IFullDataSource tryPromotingToCompleteDataSource()
{
// promotion can only be completed if every column has data
if (this.isEmpty)
{
return this;
}
if (this.isColumnNotEmpty.cardinality() != SECTION_SIZE * SECTION_SIZE)
else if (this.isColumnNotEmpty.cardinality() != SECTION_SIZE * SECTION_SIZE)
{
return this;
}
return new FullDataSource(this.sectionPos, this.mapping, this.dataArrays);
return new CompleteFullDataSource(this.sectionPos, this.mapping, this.dataArrays);
}
@@ -377,7 +382,7 @@ public class SingleChunkFullDataSource extends FullArrayView implements IIncompl
//
@Override
public SingleFullArrayView tryGet(int x, int z) { return this.isColumnNotEmpty.get(x * SECTION_SIZE + z) ? this.get(x, z) : null; }
public SingleFullArrayView tryGet(int relativeX, int relativeZ) { return this.isColumnNotEmpty.get(relativeX * SECTION_SIZE + relativeZ) ? this.get(relativeX, relativeZ) : null; }
@@ -388,7 +393,7 @@ public class SingleChunkFullDataSource extends FullArrayView implements IIncompl
@Override
public DhSectionPos getSectionPos() { return this.sectionPos; }
@Override
public byte getDataDetail() { return (byte) (this.sectionPos.sectionDetailLevel -SECTION_SIZE_OFFSET); }
public byte getDataDetailLevel() { return (byte) (this.sectionPos.sectionDetailLevel -SECTION_SIZE_OFFSET); }
@Override
public byte getDataVersion() { return LATEST_VERSION; }
@@ -1,9 +1,9 @@
package com.seibel.lod.core.dataObjects.render;
import com.seibel.lod.api.enums.worldGeneration.EDhApiWorldGenerationStep;
import com.seibel.lod.core.dataObjects.fullData.sources.CompleteFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.sources.IIncompleteFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.sources.IFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.sources.FullDataSource;
import com.seibel.lod.core.dataObjects.transformers.FullToColumnTransformer;
import com.seibel.lod.core.level.IDhClientLevel;
import com.seibel.lod.core.level.IDhLevel;
@@ -58,16 +58,16 @@ public class ColumnRenderLoader
}
}
/** @throws InterruptedException see {@link FullToColumnTransformer#transformFullDataToColumnData(IDhClientLevel, FullDataSource) FullToColumnTransformer#transformFullDataToColumnData} for documentation */
public ColumnRenderSource createRenderSource(IFullDataSource dataSource, IDhClientLevel level) throws InterruptedException
/** @throws InterruptedException see {@link FullToColumnTransformer#transformFullDataToColumnData(IDhClientLevel, CompleteFullDataSource) FullToColumnTransformer#transformFullDataToColumnData} for documentation */
public ColumnRenderSource createRenderSource(IFullDataSource fullDataSource, IDhClientLevel level) throws InterruptedException
{
if (dataSource instanceof FullDataSource)
if (fullDataSource instanceof CompleteFullDataSource)
{
return FullToColumnTransformer.transformFullDataToColumnData(level, (FullDataSource) dataSource);
return FullToColumnTransformer.transformFullDataToColumnData(level, (CompleteFullDataSource) fullDataSource);
}
else if (dataSource instanceof IIncompleteFullDataSource)
else if (fullDataSource instanceof IIncompleteFullDataSource)
{
return FullToColumnTransformer.transformIncompleteDataToColumnData(level, (IIncompleteFullDataSource) dataSource);
return FullToColumnTransformer.transformIncompleteDataToColumnData(level, (IIncompleteFullDataSource) fullDataSource);
}
LodUtil.assertNotReach();
@@ -6,7 +6,7 @@ import com.seibel.lod.core.dataObjects.render.columnViews.ColumnArrayView;
import com.seibel.lod.core.dataObjects.render.columnViews.ColumnQuadView;
import com.seibel.lod.core.dataObjects.render.columnViews.IColumnDataView;
import com.seibel.lod.core.dataObjects.render.bufferBuilding.ColumnRenderBuffer;
import com.seibel.lod.core.dataObjects.fullData.sources.ChunkSizedFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.accessor.ChunkSizedFullDataView;
import com.seibel.lod.core.dataObjects.transformers.FullToColumnTransformer;
import com.seibel.lod.core.level.IDhClientLevel;
import com.seibel.lod.core.pos.DhSectionPos;
@@ -296,7 +296,7 @@ public class ColumnRenderSource
}
}
public void fastWrite(ChunkSizedFullDataSource chunkData, IDhClientLevel level)
public void fastWrite(ChunkSizedFullDataView chunkData, IDhClientLevel level)
{
try
{
@@ -3,7 +3,7 @@ package com.seibel.lod.core.dataObjects.transformers;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import com.seibel.lod.core.dataObjects.fullData.sources.ChunkSizedFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.accessor.ChunkSizedFullDataView;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.logging.ConfigBasedLogger;
import com.seibel.lod.core.pos.DhChunkPos;
@@ -25,9 +25,9 @@ public class ChunkToLodBuilder
private static class Task
{
final DhChunkPos chunkPos;
final CompletableFuture<ChunkSizedFullDataSource> future;
final CompletableFuture<ChunkSizedFullDataView> future;
Task(DhChunkPos chunkPos, CompletableFuture<ChunkSizedFullDataSource> future)
Task(DhChunkPos chunkPos, CompletableFuture<ChunkSizedFullDataView> future)
{
this.chunkPos = chunkPos;
this.future = future;
@@ -44,14 +44,14 @@ public class ChunkToLodBuilder
public CompletableFuture<ChunkSizedFullDataSource> tryGenerateData(IChunkWrapper chunk)
public CompletableFuture<ChunkSizedFullDataView> tryGenerateData(IChunkWrapper chunkWrapper)
{
if (chunk == null)
if (chunkWrapper == null)
{
throw new NullPointerException("ChunkWrapper cannot be null!");
}
IChunkWrapper oldChunk = this.latestChunkToBuild.put(chunk.getChunkPos(), chunk); // an Exchange operation
IChunkWrapper oldChunk = this.latestChunkToBuild.put(chunkWrapper.getChunkPos(), chunkWrapper); // an Exchange operation
// If there's old chunk, that means we just replaced an unprocessed old request on generating data on this pos.
// if so, we can just return null to signal this, as the old request's future will instead be the proper one
// that will return the latest generated data.
@@ -61,8 +61,8 @@ public class ChunkToLodBuilder
}
// Otherwise, it means we're the first to do so. Let's submit our task to this entry.
CompletableFuture<ChunkSizedFullDataSource> future = new CompletableFuture<>();
this.taskToBuild.addLast(new Task(chunk.getChunkPos(), future));
CompletableFuture<ChunkSizedFullDataView> future = new CompletableFuture<>();
this.taskToBuild.addLast(new Task(chunkWrapper.getChunkPos(), future));
return future;
}
@@ -135,7 +135,7 @@ public class ChunkToLodBuilder
{
if (LodDataBuilder.canGenerateLodFromChunk(latestChunk))
{
ChunkSizedFullDataSource data = LodDataBuilder.createChunkData(latestChunk);
ChunkSizedFullDataView data = LodDataBuilder.createChunkData(latestChunk);
if (data != null)
{
task.future.complete(data);
@@ -1,14 +1,14 @@
package com.seibel.lod.core.dataObjects.transformers;
import com.seibel.lod.core.dataObjects.fullData.FullDataPointIdMap;
import com.seibel.lod.core.dataObjects.fullData.sources.CompleteFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.sources.IIncompleteFullDataSource;
import com.seibel.lod.core.util.RenderDataPointUtil;
import com.seibel.lod.core.dataObjects.render.ColumnRenderSource;
import com.seibel.lod.core.dataObjects.render.columnViews.ColumnArrayView;
import com.seibel.lod.core.dataObjects.render.columnViews.ColumnQuadView;
import com.seibel.lod.core.dataObjects.fullData.accessor.SingleFullArrayView;
import com.seibel.lod.core.dataObjects.fullData.sources.ChunkSizedFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.sources.FullDataSource;
import com.seibel.lod.core.dataObjects.fullData.accessor.ChunkSizedFullDataView;
import com.seibel.lod.core.level.IDhClientLevel;
import com.seibel.lod.core.pos.DhSectionPos;
import com.seibel.lod.core.config.Config;
@@ -50,13 +50,13 @@ public class FullToColumnTransformer
* @throws InterruptedException Can be caused by interrupting the thread upstream.
* Generally thrown if the method is running after the client leaves the current world.
*/
public static ColumnRenderSource transformFullDataToColumnData(IDhClientLevel level, FullDataSource data) throws InterruptedException
public static ColumnRenderSource transformFullDataToColumnData(IDhClientLevel level, CompleteFullDataSource fullDataSource) throws InterruptedException
{
final DhSectionPos pos = data.getSectionPos();
final byte dataDetail = data.getDataDetail();
final int vertSize = Config.Client.Graphics.Quality.verticalQuality.get().calculateMaxVerticalData(data.getDataDetail());
final DhSectionPos pos = fullDataSource.getSectionPos();
final byte dataDetail = fullDataSource.getDataDetailLevel();
final int vertSize = Config.Client.Graphics.Quality.verticalQuality.get().calculateMaxVerticalData(fullDataSource.getDataDetailLevel());
final ColumnRenderSource columnSource = new ColumnRenderSource(pos, vertSize, level.getMinY());
if (data.isEmpty())
if (fullDataSource.isEmpty())
{
return columnSource;
}
@@ -75,7 +75,7 @@ public class FullToColumnTransformer
throwIfThreadInterrupted();
ColumnArrayView columnArrayView = columnSource.getVerticalDataPointView(x, z);
SingleFullArrayView fullArrayView = data.get(x, z);
SingleFullArrayView fullArrayView = fullDataSource.get(x, z);
convertColumnData(level, baseX + x, baseZ + z, columnArrayView, fullArrayView, 1);
if (fullArrayView.doesItExist())
@@ -116,8 +116,8 @@ public class FullToColumnTransformer
public static ColumnRenderSource transformIncompleteDataToColumnData(IDhClientLevel level, IIncompleteFullDataSource data) throws InterruptedException
{
final DhSectionPos pos = data.getSectionPos();
final byte dataDetail = data.getDataDetail();
final int vertSize = Config.Client.Graphics.Quality.verticalQuality.get().calculateMaxVerticalData(data.getDataDetail());
final byte dataDetail = data.getDataDetailLevel();
final int vertSize = Config.Client.Graphics.Quality.verticalQuality.get().calculateMaxVerticalData(data.getDataDetailLevel());
final ColumnRenderSource columnSource = new ColumnRenderSource(pos, vertSize, level.getMinY());
if (data.isEmpty())
{
@@ -162,37 +162,33 @@ public class FullToColumnTransformer
* @throws InterruptedException Can be caused by interrupting the thread upstream.
* Generally thrown if the method is running after the client leaves the current world.
*/
public static void writeFullDataChunkToColumnData(ColumnRenderSource render, IDhClientLevel level, ChunkSizedFullDataSource data) throws InterruptedException
public static void writeFullDataChunkToColumnData(ColumnRenderSource render, IDhClientLevel level, ChunkSizedFullDataView chunkDataView) throws InterruptedException
{
if (data.dataDetail != 0)
{
throw new UnsupportedOperationException("To be implemented");
}
final DhSectionPos pos = render.getSectionPos();
final int renderOffsetX = (data.x * 16) - pos.getCorner().getCornerBlockPos().x;
final int renderOffsetZ = (data.z * 16) - pos.getCorner().getCornerBlockPos().z;
final int renderOffsetX = (chunkDataView.pos.x * LodUtil.CHUNK_WIDTH) - pos.getCorner().getCornerBlockPos().x;
final int renderOffsetZ = (chunkDataView.pos.z * LodUtil.CHUNK_WIDTH) - pos.getCorner().getCornerBlockPos().z;
final int blockX = pos.getCorner().getCornerBlockPos().x;
final int blockZ = pos.getCorner().getCornerBlockPos().z;
final int perRenderWidth = 1 << render.getDataDetail();
final int perDataWidth = 1 << data.dataDetail;
final int perDataWidth = 1 << chunkDataView.detailLevel;
render.markNotEmpty();
if (data.dataDetail == render.getDataDetail())
if (chunkDataView.detailLevel == render.getDataDetail())
{
if (renderOffsetX < 0 || renderOffsetX + 16 > render.getDataSize() || renderOffsetZ < 0 || renderOffsetZ + 16 > render.getDataSize())
if (renderOffsetX < 0 || renderOffsetX + LodUtil.CHUNK_WIDTH > render.getDataSize() || renderOffsetZ < 0 || renderOffsetZ + LodUtil.CHUNK_WIDTH > render.getDataSize())
{
throw new IllegalArgumentException("Data offset is out of bounds");
}
for (int x = 0; x < 16; x++)
for (int x = 0; x < LodUtil.CHUNK_WIDTH; x++)
{
for (int z = 0; z < 16; z++)
for (int z = 0; z < LodUtil.CHUNK_WIDTH; z++)
{
throwIfThreadInterrupted();
ColumnArrayView columnArrayView = render.getVerticalDataPointView(renderOffsetX + x, renderOffsetZ + z);
SingleFullArrayView fullArrayView = data.get(x, z);
SingleFullArrayView fullArrayView = chunkDataView.get(x, z);
convertColumnData(level, blockX + perRenderWidth * (renderOffsetX + x),
blockZ + perRenderWidth * (renderOffsetZ + z),
columnArrayView, fullArrayView, 2);
@@ -203,12 +199,12 @@ public class FullToColumnTransformer
}
}
}
render.fillDebugFlag(renderOffsetX, renderOffsetZ, 16, 16, ColumnRenderSource.DebugSourceFlag.DIRECT);
render.fillDebugFlag(renderOffsetX, renderOffsetZ, LodUtil.CHUNK_WIDTH, LodUtil.CHUNK_WIDTH, ColumnRenderSource.DebugSourceFlag.DIRECT);
}
else
{
final int dataPerRender = 1 << (render.getDataDetail() - data.dataDetail);
final int dataSize = 16 / dataPerRender;
final int dataPerRender = 1 << (render.getDataDetail() - chunkDataView.detailLevel);
final int dataSize = LodUtil.CHUNK_WIDTH / dataPerRender;
final int vertSize = render.getVerticalSize();
long[] tempRender = new long[dataPerRender * dataPerRender * vertSize];
if (renderOffsetX < 0 || renderOffsetX + dataSize > render.getDataSize() || renderOffsetZ < 0 || renderOffsetZ + dataSize > render.getDataSize())
@@ -230,7 +226,7 @@ public class FullToColumnTransformer
ColumnArrayView columnArrayView = tempQuadView.get(ox, oz);
SingleFullArrayView fullArrayView = data.get(x * dataPerRender + ox, z * dataPerRender + oz);
SingleFullArrayView fullArrayView = chunkDataView.get(x * dataPerRender + ox, z * dataPerRender + oz);
convertColumnData(level, blockX + perRenderWidth * (renderOffsetX + x) + perDataWidth * ox,
blockZ + perRenderWidth * (renderOffsetZ + z) + perDataWidth * oz,
columnArrayView, fullArrayView, 2);
@@ -1,6 +1,6 @@
package com.seibel.lod.core.dataObjects.transformers;
import com.seibel.lod.core.dataObjects.fullData.sources.ChunkSizedFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.accessor.ChunkSizedFullDataView;
import com.seibel.lod.core.util.FullDataPointUtil;
import com.seibel.lod.core.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.util.LodUtil;
@@ -12,29 +12,29 @@ import it.unimi.dsi.fastutil.longs.LongArrayList;
public class LodDataBuilder {
private static final IBlockStateWrapper AIR = SingletonInjector.INSTANCE.get(IWrapperFactory.class).getAirBlockStateWrapper();
public static ChunkSizedFullDataSource createChunkData(IChunkWrapper chunk) {
if (!canGenerateLodFromChunk(chunk)) return null;
public static ChunkSizedFullDataView createChunkData(IChunkWrapper chunkWrapper) {
if (!canGenerateLodFromChunk(chunkWrapper)) return null;
ChunkSizedFullDataSource chunkData = new ChunkSizedFullDataSource((byte)0, chunk.getChunkPos().x, chunk.getChunkPos().z);
ChunkSizedFullDataView chunkData = new ChunkSizedFullDataView(chunkWrapper.getChunkPos());
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);
LongArrayList longs = new LongArrayList(chunkWrapper.getHeight()/4);
int lastY = chunkWrapper.getMaxBuildHeight();
IBiomeWrapper biome = chunkWrapper.getBiome(x, lastY, z);
IBlockStateWrapper blockState = AIR;
int mappedId = chunkData.getMapping().addIfNotPresentAndGetId(biome, blockState);
// FIXME: The +1 offset to reproduce the old behavior. Remove this when we get per-face lighting
byte light = (byte) ((chunk.getBlockLight(x,lastY+1,z) << 4) + chunk.getSkyLight(x,lastY+1,z));
int y=chunk.getMaxY(x, z);
byte light = (byte) ((chunkWrapper.getBlockLight(x,lastY+1,z) << 4) + chunkWrapper.getSkyLight(x,lastY+1,z));
int y=chunkWrapper.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+1,z) << 4) + chunk.getSkyLight(x,y+1,z));
for (; y>=chunkWrapper.getMinBuildHeight(); y--) {
IBiomeWrapper newBiome = chunkWrapper.getBiome(x, y, z);
IBlockStateWrapper newBlockState = chunkWrapper.getBlockState(x, y, z);
byte newLight = (byte) ((chunkWrapper.getBlockLight(x,y+1,z) << 4) + chunkWrapper.getSkyLight(x,y+1,z));
if (!newBiome.equals(biome) || !newBlockState.equals(blockState)) {
longs.add(FullDataPointUtil.encode(mappedId, lastY-y, y+1 - chunk.getMinBuildHeight(), light));
longs.add(FullDataPointUtil.encode(mappedId, lastY-y, y+1 - chunkWrapper.getMinBuildHeight(), light));
biome = newBiome;
blockState = newBlockState;
mappedId = chunkData.getMapping().addIfNotPresentAndGetId(biome, blockState);
@@ -47,7 +47,7 @@ public class LodDataBuilder {
// lastY = y;
// }
}
longs.add(FullDataPointUtil.encode(mappedId, lastY-y, y+1 - chunk.getMinBuildHeight(), light));
longs.add(FullDataPointUtil.encode(mappedId, lastY-y, y+1 - chunkWrapper.getMinBuildHeight(), light));
chunkData.setSingleColumn(longs.toArray(new long[0]), x, z);
}
@@ -1,12 +1,9 @@
package com.seibel.lod.core.file.fullDatafile;
import com.google.common.collect.HashMultimap;
import com.seibel.lod.core.dataObjects.fullData.sources.IFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.sources.IIncompleteFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.sources.ChunkSizedFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.sources.FullDataSource;
import com.seibel.lod.core.dataObjects.fullData.sources.SingleChunkFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.sources.SparseFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.accessor.ChunkSizedFullDataView;
import com.seibel.lod.core.dataObjects.fullData.sources.*;
import com.seibel.lod.core.dataObjects.fullData.sources.CompleteFullDataSource;
import com.seibel.lod.core.util.FileUtil;
import com.seibel.lod.core.file.metaData.BaseMetaData;
import com.seibel.lod.core.level.IDhLevel;
@@ -37,7 +34,7 @@ public class FullDataFileHandler implements IFullDataSourceProvider
final IDhLevel level;
final File saveDir;
AtomicInteger topDetailLevel = new AtomicInteger(-1);
final int minDetailLevel = FullDataSource.SECTION_SIZE_OFFSET;
final int minDetailLevel = CompleteFullDataSource.SECTION_SIZE_OFFSET;
@@ -185,7 +182,7 @@ public class FullDataFileHandler implements IFullDataSourceProvider
//TODO: The following check is temporary as we only sample corner points, which means
// on a very different level, we may not need the entire section at all.
if (!FullDataSource.firstDataPosCanAffectSecond(basePos, subPos))
if (!CompleteFullDataSource.firstDataPosCanAffectSecond(basePos, subPos))
{
continue;
}
@@ -217,7 +214,7 @@ public class FullDataFileHandler implements IFullDataSourceProvider
private void recursiveGetDataFilesForPosition(int childIndex, DhSectionPos basePos, DhSectionPos pos, ArrayList<FullDataMetaFile> preexistingFiles, ArrayList<DhSectionPos> missingFilePositions)
{
DhSectionPos childPos = pos.getChildByIndex(childIndex);
if (FullDataSource.firstDataPosCanAffectSecond(basePos, childPos))
if (CompleteFullDataSource.firstDataPosCanAffectSecond(basePos, childPos))
{
FullDataMetaFile metaFile = this.files.get(childPos);
if (metaFile != null)
@@ -276,15 +273,15 @@ public class FullDataFileHandler implements IFullDataSourceProvider
/** This call is concurrent. I.e. it supports being called by multiple threads at the same time. */
@Override
public void write(DhSectionPos sectionPos, ChunkSizedFullDataSource chunkData)
public void write(DhSectionPos sectionPos, ChunkSizedFullDataView chunkDataView)
{
DhLodPos chunkPos = new DhLodPos((byte) (chunkData.dataDetail+4), chunkData.x, chunkData.z);
DhLodPos chunkPos = chunkDataView.getLodPos();
LodUtil.assertTrue(chunkPos.overlapsExactly(sectionPos.getSectionBBoxPos()), "Chunk "+chunkPos+" does not overlap section "+sectionPos);
chunkPos = chunkPos.convertToDetailLevel((byte) this.minDetailLevel);
this.writeChunkDataToMetaFile(new DhSectionPos(chunkPos.detailLevel, chunkPos.x, chunkPos.z), chunkData);
this.writeChunkDataToMetaFile(new DhSectionPos(chunkPos.detailLevel, chunkPos.x, chunkPos.z), chunkDataView);
}
private void writeChunkDataToMetaFile(DhSectionPos sectionPos, ChunkSizedFullDataSource chunkData)
private void writeChunkDataToMetaFile(DhSectionPos sectionPos, ChunkSizedFullDataView chunkData)
{
FullDataMetaFile metaFile = this.files.get(sectionPos);
if (metaFile != null)
@@ -346,7 +343,7 @@ public class FullDataFileHandler implements IFullDataSourceProvider
{
// None exist.
IIncompleteFullDataSource incompleteDataSource = pos.sectionDetailLevel <= SparseFullDataSource.MAX_SECTION_DETAIL ?
SparseFullDataSource.createEmpty(pos) : SingleChunkFullDataSource.createEmpty(pos);
SparseFullDataSource.createEmpty(pos) : SpottyFullDataSource.createEmpty(pos);
return CompletableFuture.completedFuture(incompleteDataSource);
}
else
@@ -362,7 +359,7 @@ public class FullDataFileHandler implements IFullDataSourceProvider
final ArrayList<CompletableFuture<Void>> futures = new ArrayList<>(existFiles.size());
final IIncompleteFullDataSource dataSource = pos.sectionDetailLevel <= SparseFullDataSource.MAX_SECTION_DETAIL ?
SparseFullDataSource.createEmpty(pos) :
SingleChunkFullDataSource.createEmpty(pos);
SpottyFullDataSource.createEmpty(pos);
for (FullDataMetaFile metaFile : existFiles)
{
@@ -383,7 +380,7 @@ public class FullDataFileHandler implements IFullDataSourceProvider
);
}
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
.thenApply((v) -> dataSource.trySelfPromote());
.thenApply((v) -> dataSource.tryPromotingToCompleteDataSource());
}
}
@@ -410,7 +407,7 @@ public class FullDataFileHandler implements IFullDataSourceProvider
if (source instanceof IIncompleteFullDataSource)
{
IFullDataSource newSource = ((IIncompleteFullDataSource) source).trySelfPromote();
IFullDataSource newSource = ((IIncompleteFullDataSource) source).tryPromotingToCompleteDataSource();
changed |= newSource != source;
source = newSource;
}
@@ -437,7 +434,7 @@ public class FullDataFileHandler implements IFullDataSourceProvider
if (sourceLocal instanceof IIncompleteFullDataSource)
{
IFullDataSource newSource = ((IIncompleteFullDataSource) sourceLocal).trySelfPromote();
IFullDataSource newSource = ((IIncompleteFullDataSource) sourceLocal).tryPromotingToCompleteDataSource();
changed |= newSource != sourceLocal;
sourceLocal = newSource;
}
@@ -11,7 +11,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
import com.seibel.lod.core.dataObjects.fullData.sources.IFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.loader.AbstractFullDataSourceLoader;
import com.seibel.lod.core.dataObjects.fullData.sources.ChunkSizedFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.accessor.ChunkSizedFullDataView;
import com.seibel.lod.core.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.file.metaData.BaseMetaData;
import com.seibel.lod.core.pos.DhLodPos;
@@ -47,7 +47,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile
//TODO: use ConcurrentAppendSingleSwapContainer<LodDataSource> instead of below:
private static class GuardedMultiAppendQueue {
ReentrantReadWriteLock appendLock = new ReentrantReadWriteLock();
ConcurrentLinkedQueue<ChunkSizedFullDataSource> queue = new ConcurrentLinkedQueue<>();
ConcurrentLinkedQueue<ChunkSizedFullDataView> queue = new ConcurrentLinkedQueue<>();
}
// ===Concurrent Write stuff===
@@ -146,11 +146,11 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile
// }
// }
public void addToWriteQueue(ChunkSizedFullDataSource chunkDataSource)
public void addToWriteQueue(ChunkSizedFullDataView chunkDataSource)
{
debugCheck();
DhLodPos chunkPos = new DhLodPos((byte) (chunkDataSource.dataDetail + 4), chunkDataSource.x, chunkDataSource.z);
LodUtil.assertTrue(pos.getSectionBBoxPos().overlapsExactly(chunkPos), "Chunk pos "+chunkPos+" doesn't overlap with section "+pos);
DhLodPos chunkLodPos = new DhLodPos(LodUtil.CHUNK_DETAIL_LEVEL, chunkDataSource.pos.x, chunkDataSource.pos.z);
LodUtil.assertTrue(pos.getSectionBBoxPos().overlapsExactly(chunkLodPos), "Chunk pos "+chunkLodPos+" doesn't overlap with section "+pos);
//LOGGER.info("Write Chunk {} to file {}", chunkPos, pos);
GuardedMultiAppendQueue writeQueue = this.writeQueue.get();
@@ -293,7 +293,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile
private static BaseMetaData makeMetaData(IFullDataSource data) {
AbstractFullDataSourceLoader loader = AbstractFullDataSourceLoader.getLoader(data.getClass(), data.getDataVersion());
return new BaseMetaData(data.getSectionPos(), -1,
data.getDataDetail(), data.getWorldGenStep(), (loader == null ? 0 : loader.datatypeId), data.getDataVersion());
data.getDataDetailLevel(), data.getWorldGenStep(), (loader == null ? 0 : loader.datatypeId), data.getDataVersion());
}
// "unchecked": Suppress casting of CompletableFuture<?> to CompletableFuture<LodDataSource>
@@ -398,7 +398,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile
{
// Write/Update data
LodUtil.assertTrue(metaData != null);
metaData.dataLevel = fullDataSource.getDataDetail();
metaData.dataLevel = fullDataSource.getDataDetailLevel();
fullDataSourceLoader = AbstractFullDataSourceLoader.getLoader(fullDataSource.getClass(), fullDataSource.getDataVersion());
LodUtil.assertTrue(fullDataSourceLoader != null, "No loader for "+fullDataSource.getClass()+" (v"+fullDataSource.getDataVersion()+")");
dataType = fullDataSource.getClass();
@@ -430,7 +430,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile
{
this.swapWriteQueue();
int count = this._backQueue.queue.size();
for (ChunkSizedFullDataSource chunk : this._backQueue.queue)
for (ChunkSizedFullDataView chunk : this._backQueue.queue)
{
fullDataSource.update(chunk);
}
@@ -2,9 +2,9 @@ package com.seibel.lod.core.file.fullDatafile;
import com.seibel.lod.core.dataObjects.fullData.sources.IFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.sources.IIncompleteFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.sources.ChunkSizedFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.accessor.ChunkSizedFullDataView;
import com.seibel.lod.core.dataObjects.fullData.sources.SparseFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.sources.SingleChunkFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.sources.SpottyFullDataSource;
import com.seibel.lod.core.generation.tasks.IWorldGenTaskTracker;
import com.seibel.lod.core.generation.WorldGenerationQueue;
import com.seibel.lod.core.generation.tasks.WorldGenResult;
@@ -92,7 +92,7 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler
}
else
{
incompleteFullDataSource = SingleChunkFullDataSource.createEmpty(pos);
incompleteFullDataSource = SpottyFullDataSource.createEmpty(pos);
}
@@ -105,7 +105,7 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler
{
// queue this section to be generated
GenTask genTask = new GenTask(pos, new WeakReference<>(incompleteFullDataSource));
worldGenQueue.submitGenTask(incompleteFullDataSource.getSectionPos().getSectionBBoxPos(), incompleteFullDataSource.getDataDetail(), genTask)
worldGenQueue.submitGenTask(incompleteFullDataSource.getSectionPos().getSectionBBoxPos(), incompleteFullDataSource.getDataDetailLevel(), genTask)
.whenComplete((genTaskResult, ex) -> this.onWorldGenTaskComplete(genTaskResult, ex, genTask, pos));
}
@@ -146,7 +146,7 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler
}
return CompletableFuture.allOf(loadDataFutures.toArray(new CompletableFuture[0]))
.thenApply((voidValue) -> incompleteFullDataSource.trySelfPromote());
.thenApply((voidValue) -> incompleteFullDataSource.tryPromotingToCompleteDataSource());
}
}
@@ -218,7 +218,7 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler
public boolean isMemoryAddressValid() { return this.targetFullDataSourceRef.get() != null; }
@Override
public Consumer<ChunkSizedFullDataSource> getOnGenTaskCompleteConsumer()
public Consumer<ChunkSizedFullDataView> getOnGenTaskCompleteConsumer()
{
if (this.loadedTargetFullDataSource == null)
{
@@ -231,7 +231,7 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler
return (chunkSizedFullDataSource) ->
{
if (chunkSizedFullDataSource.getBBoxLodPos().overlapsExactly(this.loadedTargetFullDataSource.getSectionPos().getSectionBBoxPos()))
if (chunkSizedFullDataSource.getLodPos().overlapsExactly(this.loadedTargetFullDataSource.getSectionPos().getSectionBBoxPos()))
{
GeneratedFullDataFileHandler.this.write(this.loadedTargetFullDataSource.getSectionPos(), chunkSizedFullDataSource);
}
@@ -1,7 +1,7 @@
package com.seibel.lod.core.file.fullDatafile;
import com.seibel.lod.core.dataObjects.fullData.sources.IFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.sources.ChunkSizedFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.accessor.ChunkSizedFullDataView;
import com.seibel.lod.core.file.metaData.BaseMetaData;
import com.seibel.lod.core.pos.DhSectionPos;
@@ -17,7 +17,7 @@ public interface IFullDataSourceProvider extends AutoCloseable
void addScannedFile(Collection<File> detectedFiles);
CompletableFuture<IFullDataSource> read(DhSectionPos pos);
void write(DhSectionPos sectionPos, ChunkSizedFullDataSource chunkData);
void write(DhSectionPos sectionPos, ChunkSizedFullDataView chunkData);
CompletableFuture<Void> flushAndSave();
//long getCacheVersion(DhSectionPos sectionPos);
@@ -1,7 +1,7 @@
package com.seibel.lod.core.file.renderfile;
import com.seibel.lod.core.dataObjects.render.ColumnRenderSource;
import com.seibel.lod.core.dataObjects.fullData.sources.ChunkSizedFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.accessor.ChunkSizedFullDataView;
import com.seibel.lod.core.pos.DhSectionPos;
import java.io.File;
@@ -18,7 +18,7 @@ public interface ILodRenderSourceProvider extends AutoCloseable
{
CompletableFuture<ColumnRenderSource> readAsync(DhSectionPos pos);
void addScannedFile(Collection<File> detectedFiles);
void writeChunkDataToFile(DhSectionPos sectionPos, ChunkSizedFullDataSource chunkData);
void writeChunkDataToFile(DhSectionPos sectionPos, ChunkSizedFullDataView chunkData);
CompletableFuture<Void> flushAndSaveAsync();
/** Returns true if the data was refreshed, false otherwise */
@@ -2,7 +2,7 @@ package com.seibel.lod.core.file.renderfile;
import com.seibel.lod.core.dataObjects.render.ColumnRenderLoader;
import com.seibel.lod.core.dataObjects.render.ColumnRenderSource;
import com.seibel.lod.core.dataObjects.fullData.sources.ChunkSizedFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.accessor.ChunkSizedFullDataView;
import com.seibel.lod.core.file.metaData.BaseMetaData;
import com.seibel.lod.core.level.IDhClientLevel;
import com.seibel.lod.core.level.IDhLevel;
@@ -77,9 +77,9 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile
// FIXME: This can cause concurrent modification of LodRenderSource.
// Not sure if it will cause issues or not.
public void updateChunkIfNeeded(ChunkSizedFullDataSource chunkData, IDhClientLevel level)
public void updateChunkIfNeeded(ChunkSizedFullDataView chunkDataView, IDhClientLevel level)
{
DhLodPos chunkPos = new DhLodPos((byte) (chunkData.dataDetail + 4), chunkData.x, chunkData.z);
DhLodPos chunkPos = chunkDataView.getLodPos();
LodUtil.assertTrue(this.pos.getSectionBBoxPos().overlapsExactly(chunkPos), "Chunk pos {} doesn't overlap with section {}", chunkPos, pos);
CompletableFuture<ColumnRenderSource> source = this._readCached(this.data.get());
@@ -88,7 +88,7 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile
return;
}
source.thenAccept((renderSource) -> renderSource.fastWrite(chunkData, level));
source.thenAccept((renderSource) -> renderSource.fastWrite(chunkDataView, level));
}
public CompletableFuture<Void> flushAndSave(ExecutorService renderCacheThread)
@@ -3,7 +3,7 @@ package com.seibel.lod.core.file.renderfile;
import com.google.common.collect.HashMultimap;
import com.seibel.lod.core.dataObjects.fullData.sources.IFullDataSource;
import com.seibel.lod.core.dataObjects.render.ColumnRenderSource;
import com.seibel.lod.core.dataObjects.fullData.sources.ChunkSizedFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.accessor.ChunkSizedFullDataView;
import com.seibel.lod.core.dataObjects.transformers.DataRenderTransformer;
import com.seibel.lod.core.file.fullDatafile.IFullDataSourceProvider;
import com.seibel.lod.core.level.IDhClientLevel;
@@ -214,14 +214,14 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
* TODO why is there fullData handling in the render file handler?
*/
@Override
public void writeChunkDataToFile(DhSectionPos sectionPos, ChunkSizedFullDataSource chunkData)
public void writeChunkDataToFile(DhSectionPos sectionPos, ChunkSizedFullDataView chunkDataView)
{
this.writeChunkDataToFileRecursively(sectionPos,chunkData);
this.fullDataSourceProvider.write(sectionPos, chunkData);
this.writeChunkDataToFileRecursively(sectionPos,chunkDataView);
this.fullDataSourceProvider.write(sectionPos, chunkDataView);
}
private void writeChunkDataToFileRecursively(DhSectionPos sectPos, ChunkSizedFullDataSource chunkData)
private void writeChunkDataToFileRecursively(DhSectionPos sectPos, ChunkSizedFullDataView chunkDataView)
{
if (!sectPos.getSectionBBoxPos().overlapsExactly(new DhLodPos((byte) (4 + chunkData.dataDetail), chunkData.x, chunkData.z)))
if (!sectPos.getSectionBBoxPos().overlapsExactly(chunkDataView.getLodPos()))
{
return;
}
@@ -229,17 +229,17 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
if (sectPos.sectionDetailLevel > ColumnRenderSource.SECTION_SIZE_OFFSET)
{
this.writeChunkDataToFileRecursively(sectPos.getChildByIndex(0), chunkData);
this.writeChunkDataToFileRecursively(sectPos.getChildByIndex(1), chunkData);
this.writeChunkDataToFileRecursively(sectPos.getChildByIndex(2), chunkData);
this.writeChunkDataToFileRecursively(sectPos.getChildByIndex(3), chunkData);
this.writeChunkDataToFileRecursively(sectPos.getChildByIndex(0), chunkDataView);
this.writeChunkDataToFileRecursively(sectPos.getChildByIndex(1), chunkDataView);
this.writeChunkDataToFileRecursively(sectPos.getChildByIndex(2), chunkDataView);
this.writeChunkDataToFileRecursively(sectPos.getChildByIndex(3), chunkDataView);
}
RenderMetaDataFile metaFile = this.filesBySectionPos.get(sectPos);
// Fast path: if there is a file for this section, just write to it.
if (metaFile != null)
{
metaFile.updateChunkIfNeeded(chunkData, this.level);
metaFile.updateChunkIfNeeded(chunkDataView, this.level);
}
}
@@ -2,7 +2,7 @@ package com.seibel.lod.core.file.subDimMatching;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.dataObjects.fullData.sources.IFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.sources.ChunkSizedFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.accessor.ChunkSizedFullDataView;
import com.seibel.lod.core.util.FullDataPointUtil;
import com.seibel.lod.core.dataObjects.fullData.accessor.SingleFullArrayView;
import com.seibel.lod.core.dataObjects.transformers.LodDataBuilder;
@@ -165,20 +165,20 @@ public class SubDimensionLevelMatcher implements AutoCloseable
LOGGER.info("Player block pos in dimension: [" + playerData.playerBlockPos.getX() + "," + playerData.playerBlockPos.getY() + "," + playerData.playerBlockPos.getZ() + "]");
// new chunk data
ChunkSizedFullDataSource newChunkSizedFullDataSource = LodDataBuilder.createChunkData(newlyLoadedChunk);
ChunkSizedFullDataView newChunkSizedFullDataView = LodDataBuilder.createChunkData(newlyLoadedChunk);
long[][][] newChunkData = new long[LodUtil.CHUNK_WIDTH][LodUtil.CHUNK_WIDTH][];
if (newChunkSizedFullDataSource != null)
if (newChunkSizedFullDataView != null)
{
for (int x = 0; x < LodUtil.CHUNK_WIDTH; x++)
{
for (int z = 0; z < LodUtil.CHUNK_WIDTH; z++)
{
long[] array = newChunkSizedFullDataSource.get(x, z).getRaw();
long[] array = newChunkSizedFullDataView.get(x, z).getRaw();
newChunkData[x][z] = array;
}
}
}
boolean newChunkHasData = newChunkSizedFullDataSource != null && newChunkSizedFullDataSource.nonEmptyCount() != 0;
boolean newChunkHasData = newChunkSizedFullDataView != null && newChunkSizedFullDataView.nonEmptyCount() != 0;
// check if the chunk is actually empty
if (!newChunkHasData)
@@ -3,7 +3,7 @@ package com.seibel.lod.core.generation;
import com.seibel.lod.api.enums.worldGeneration.EDhApiDistantGeneratorMode;
import com.seibel.lod.api.interfaces.override.worldGenerator.IDhApiWorldGenerator;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.dataObjects.fullData.sources.ChunkSizedFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.accessor.ChunkSizedFullDataView;
import com.seibel.lod.core.dataObjects.transformers.LodDataBuilder;
import com.seibel.lod.core.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.generation.tasks.*;
@@ -345,7 +345,7 @@ public class WorldGenerationQueue implements Closeable
LodUtil.assertTrue(taskDetailLevel >= this.minDataDetail && taskDetailLevel <= this.maxDataDetail);
DhChunkPos chunkPosMin = new DhChunkPos(taskPos.getCornerBlockPos());
LOGGER.info("Generating section "+taskPos+" with granularity "+granularity+" at "+chunkPosMin);
//LOGGER.info("Generating section "+taskPos+" with granularity "+granularity+" at "+chunkPosMin);
this.numberOfTasksQueued++;
inProgressTaskGroup.genFuture = startGenerationEvent(this.generator, chunkPosMin, granularity, taskDetailLevel, inProgressTaskGroup.group::onGenerationComplete);
@@ -500,7 +500,7 @@ public class WorldGenerationQueue implements Closeable
private static CompletableFuture<Void> startGenerationEvent(IDhApiWorldGenerator worldGenerator,
DhChunkPos chunkPosMin,
byte granularity, byte targetDataDetail,
Consumer<ChunkSizedFullDataSource> generationCompleteConsumer)
Consumer<ChunkSizedFullDataView> generationCompleteConsumer)
{
EDhApiDistantGeneratorMode generatorMode = Config.Client.WorldGenerator.distantGeneratorMode.get();
return worldGenerator.generateChunks(chunkPosMin.x, chunkPosMin.z, granularity, targetDataDetail, generatorMode, (objectArray) ->
@@ -1,6 +1,6 @@
package com.seibel.lod.core.generation.tasks;
import com.seibel.lod.core.dataObjects.fullData.sources.ChunkSizedFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.accessor.ChunkSizedFullDataView;
import java.util.function.Consumer;
@@ -13,6 +13,6 @@ public interface IWorldGenTaskTracker
/** Returns true if the task hasn't been garbage collected. */
boolean isMemoryAddressValid();
Consumer<ChunkSizedFullDataSource> getOnGenTaskCompleteConsumer();
Consumer<ChunkSizedFullDataView> getOnGenTaskCompleteConsumer();
}
@@ -1,6 +1,6 @@
package com.seibel.lod.core.generation.tasks;
import com.seibel.lod.core.dataObjects.fullData.sources.ChunkSizedFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.accessor.ChunkSizedFullDataView;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
@@ -52,6 +52,6 @@ public class SplitWorldGenTaskTracker implements IWorldGenTaskTracker
public boolean isMemoryAddressValid() { return this.isValid; }
@Override
public Consumer<ChunkSizedFullDataSource> getOnGenTaskCompleteConsumer() { return this.parentTracker.getOnGenTaskCompleteConsumer(); }
public Consumer<ChunkSizedFullDataView> getOnGenTaskCompleteConsumer() { return this.parentTracker.getOnGenTaskCompleteConsumer(); }
}
@@ -1,8 +1,7 @@
package com.seibel.lod.core.generation.tasks;
import com.seibel.lod.core.dataObjects.fullData.sources.ChunkSizedFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.accessor.ChunkSizedFullDataView;
import com.seibel.lod.core.pos.DhLodPos;
import com.seibel.lod.core.pos.DhSectionPos;
import java.util.Iterator;
import java.util.LinkedList;
@@ -29,13 +28,13 @@ public final class WorldGenTaskGroup
public void onGenerationComplete(ChunkSizedFullDataSource chunkSizedFullDataSource)
public void onGenerationComplete(ChunkSizedFullDataView chunkSizedFullDataView)
{
Iterator<WorldGenTask> tasks = this.worldGenTasks.iterator();
while (tasks.hasNext())
{
WorldGenTask task = tasks.next();
Consumer<ChunkSizedFullDataSource> onGenTaskCompleteConsumer = task.taskTracker.getOnGenTaskCompleteConsumer();
Consumer<ChunkSizedFullDataView> onGenTaskCompleteConsumer = task.taskTracker.getOnGenTaskCompleteConsumer();
if (onGenTaskCompleteConsumer == null)
{
tasks.remove();
@@ -44,7 +43,7 @@ public final class WorldGenTaskGroup
else
{
// TODO why aren't we removing the task if it has a consumer?
onGenTaskCompleteConsumer.accept(chunkSizedFullDataSource);
onGenTaskCompleteConsumer.accept(chunkSizedFullDataView);
}
}
}
@@ -1,8 +1,8 @@
package com.seibel.lod.core.level;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.dataObjects.fullData.sources.ChunkSizedFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.sources.FullDataSource;
import com.seibel.lod.core.dataObjects.fullData.accessor.ChunkSizedFullDataView;
import com.seibel.lod.core.dataObjects.fullData.sources.CompleteFullDataSource;
import com.seibel.lod.core.dataObjects.transformers.ChunkToLodBuilder;
import com.seibel.lod.core.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.file.fullDatafile.FullDataFileHandler;
@@ -172,16 +172,16 @@ public abstract class AbstractDhClientLevel implements IDhClientLevel
@Override
public void updateChunkAsync(IChunkWrapper chunk)
{
CompletableFuture<ChunkSizedFullDataSource> future = this.chunkToLodBuilder.tryGenerateData(chunk);
CompletableFuture<ChunkSizedFullDataView> future = this.chunkToLodBuilder.tryGenerateData(chunk);
if (future != null)
{
future.thenAccept(this::saveWrites);
}
}
private void saveWrites(ChunkSizedFullDataSource data)
private void saveWrites(ChunkSizedFullDataView data)
{
ClientRenderState ClientRenderState = this.ClientRenderStateRef.get();
DhLodPos pos = data.getBBoxLodPos().convertToDetailLevel(FullDataSource.SECTION_SIZE_OFFSET);
DhLodPos pos = data.getLodPos().convertToDetailLevel(CompleteFullDataSource.SECTION_SIZE_OFFSET);
if (ClientRenderState != null)
{
ClientRenderState.renderSourceFileHandler.writeChunkDataToFile(new DhSectionPos(pos.detailLevel, pos.x, pos.z), data);
@@ -1,32 +1,20 @@
package com.seibel.lod.core.level;
import com.seibel.lod.core.dataObjects.fullData.sources.ChunkSizedFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.sources.FullDataSource;
import com.seibel.lod.core.dataObjects.transformers.ChunkToLodBuilder;
import com.seibel.lod.core.file.fullDatafile.FullDataFileHandler;
import com.seibel.lod.core.file.fullDatafile.IFullDataSourceProvider;
import com.seibel.lod.core.file.structure.AbstractSaveStructure;
import com.seibel.lod.core.level.states.ClientRenderState;
import com.seibel.lod.core.logging.f3.F3Screen;
import com.seibel.lod.core.pos.DhLodPos;
import com.seibel.lod.core.pos.DhSectionPos;
import com.seibel.lod.core.util.FileScanUtil;
import com.seibel.lod.core.file.fullDatafile.RemoteFullDataFileHandler;
import com.seibel.lod.core.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.logging.DhLoggerBuilder;
import com.seibel.lod.core.pos.DhBlockPos;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.util.math.Mat4f;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockStateWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IProfilerWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IClientLevelWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
import org.apache.logging.log4j.Logger;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicReference;
/** The level used when connected to a server */