basic reformatting
This commit is contained in:
@@ -20,6 +20,6 @@ public interface ILodDataSource
|
||||
|
||||
boolean isEmpty();
|
||||
|
||||
// Saving related
|
||||
void saveData(IDhLevel level, DataMetaFile file, OutputStream dataStream) throws IOException;
|
||||
|
||||
}
|
||||
|
||||
@@ -3,34 +3,38 @@ package com.seibel.lod.core.datatype.full;
|
||||
import com.seibel.lod.core.datatype.full.accessor.FullArrayView;
|
||||
import com.seibel.lod.core.pos.DhLodPos;
|
||||
|
||||
public class ChunkSizedData extends FullArrayView {
|
||||
public final byte dataDetail;
|
||||
public final int x;
|
||||
public final int z;
|
||||
public ChunkSizedData(byte dataDetail, int x, int z) {
|
||||
super(new IdBiomeBlockStateMap(), 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);
|
||||
}
|
||||
public class ChunkSizedData extends FullArrayView
|
||||
{
|
||||
public final byte dataDetail;
|
||||
public final int x;
|
||||
public final int z;
|
||||
|
||||
public ChunkSizedData(byte dataDetail, int x, int z)
|
||||
{
|
||||
super(new IdBiomeBlockStateMap(), 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); }
|
||||
|
||||
}
|
||||
@@ -10,13 +10,16 @@ import java.io.InputStream;
|
||||
|
||||
public class FullDataLoader extends AbstractDataSourceLoader
|
||||
{
|
||||
public FullDataLoader() {
|
||||
public FullDataLoader()
|
||||
{
|
||||
super(FullDataSource.class, FullDataSource.TYPE_ID, new byte[]{FullDataSource.LATEST_VERSION});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ILodDataSource loadData(DataMetaFile dataFile, InputStream data, IDhLevel level) throws IOException {
|
||||
public ILodDataSource loadData(DataMetaFile dataFile, InputStream data, IDhLevel level) throws IOException
|
||||
{
|
||||
//TODO: Add decompressor here
|
||||
return FullDataSource.loadData(dataFile, data, level);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,223 +17,263 @@ import java.io.*;
|
||||
|
||||
public class FullDataSource extends FullArrayView implements ILodDataSource
|
||||
{ // 1 chunk
|
||||
|
||||
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();
|
||||
|
||||
private final DhSectionPos sectionPos;
|
||||
private boolean isEmpty = true;
|
||||
protected FullDataSource(DhSectionPos sectionPos) {
|
||||
|
||||
|
||||
|
||||
protected FullDataSource(DhSectionPos sectionPos)
|
||||
{
|
||||
super(new IdBiomeBlockStateMap(), new long[SECTION_SIZE*SECTION_SIZE][0], SECTION_SIZE);
|
||||
this.sectionPos = sectionPos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public DhSectionPos getSectionPos() { return sectionPos; }
|
||||
@Override
|
||||
public byte getDataDetail() { return (byte) (sectionPos.sectionDetail-SECTION_SIZE_OFFSET); }
|
||||
|
||||
@Override
|
||||
public DhSectionPos getSectionPos() {
|
||||
return sectionPos;
|
||||
}
|
||||
@Override
|
||||
public byte getDataDetail() {
|
||||
return (byte) (sectionPos.sectionDetail-SECTION_SIZE_OFFSET);
|
||||
}
|
||||
public byte getDataVersion() { return LATEST_VERSION; }
|
||||
|
||||
@Override
|
||||
public void update(ChunkSizedData data)
|
||||
{
|
||||
LodUtil.assertTrue(sectionPos.getSectionBBoxPos().overlaps(data.getBBoxLodPos()));
|
||||
if (data.dataDetail == 0 && getDataDetail() == 0)
|
||||
{
|
||||
DhBlockPos2D chunkBlockPos = new DhBlockPos2D(data.x * 16, data.z * 16);
|
||||
DhBlockPos2D blockOffset = chunkBlockPos.subtract(sectionPos.getCorner().getCorner());
|
||||
LodUtil.assertTrue(blockOffset.x >= 0 && blockOffset.x < SECTION_SIZE && blockOffset.z >= 0 && blockOffset.z < SECTION_SIZE);
|
||||
isEmpty = false;
|
||||
data.shadowCopyTo(this.subView(16, blockOffset.x, blockOffset.z));
|
||||
{ // DEBUG ASSERTION
|
||||
for (int x = 0; x < 16; x++)
|
||||
{
|
||||
for (int z = 0; z < 16; z++)
|
||||
{
|
||||
SingleFullArrayView column = this.get(x + blockOffset.x, z + blockOffset.z);
|
||||
LodUtil.assertTrue(column.doesItExist());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (data.dataDetail == 0 && getDataDetail() < 4)
|
||||
{
|
||||
int dataPerFull = 1 << getDataDetail();
|
||||
int fullSize = 16 / dataPerFull;
|
||||
DhLodPos dataOffset = data.getBBoxLodPos().getCorner(getDataDetail());
|
||||
DhLodPos baseOffset = sectionPos.getCorner(getDataDetail());
|
||||
int offsetX = dataOffset.x - baseOffset.x;
|
||||
int offsetZ = dataOffset.z - baseOffset.z;
|
||||
LodUtil.assertTrue(offsetX >= 0 && offsetX < SECTION_SIZE && offsetZ >= 0 && offsetZ < SECTION_SIZE);
|
||||
isEmpty = false;
|
||||
for (int ox = 0; ox < fullSize; ox++)
|
||||
{
|
||||
for (int oz = 0; oz < fullSize; oz++)
|
||||
{
|
||||
SingleFullArrayView column = this.get(ox + offsetX, oz + offsetZ);
|
||||
column.downsampleFrom(data.subView(dataPerFull, ox * dataPerFull, oz * dataPerFull));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (data.dataDetail == 0 && getDataDetail() >= 4)
|
||||
{
|
||||
//FIXME: TEMPORARY
|
||||
int chunkPerFull = 1 << (getDataDetail() - 4);
|
||||
if (data.x % chunkPerFull != 0 || data.z % chunkPerFull != 0)
|
||||
return;
|
||||
DhLodPos baseOffset = sectionPos.getCorner(getDataDetail());
|
||||
DhLodPos dataOffset = data.getBBoxLodPos().convertUpwardsTo(getDataDetail());
|
||||
int offsetX = dataOffset.x - baseOffset.x;
|
||||
int offsetZ = dataOffset.z - baseOffset.z;
|
||||
LodUtil.assertTrue(offsetX >= 0 && offsetX < SECTION_SIZE && offsetZ >= 0 && offsetZ < SECTION_SIZE);
|
||||
isEmpty = false;
|
||||
data.get(0, 0).deepCopyTo(get(offsetX, offsetZ));
|
||||
}
|
||||
else
|
||||
{
|
||||
LodUtil.assertNotReach();
|
||||
//TODO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getDataVersion() {
|
||||
return LATEST_VERSION;
|
||||
}
|
||||
public boolean isEmpty() { return isEmpty; }
|
||||
public void markNotEmpty() { isEmpty = false; }
|
||||
|
||||
@Override
|
||||
public void saveData(IDhLevel level, DataMetaFile file, OutputStream dataStream) throws IOException
|
||||
{
|
||||
DataOutputStream dos = new DataOutputStream(dataStream); // DO NOT CLOSE
|
||||
{
|
||||
dos.writeInt(getDataDetail());
|
||||
dos.writeInt(size);
|
||||
dos.writeInt(level.getMinY());
|
||||
if (isEmpty)
|
||||
{
|
||||
dos.writeInt(0x00000001);
|
||||
return;
|
||||
}
|
||||
dos.writeInt(0xFFFFFFFF);
|
||||
// Data array length
|
||||
for (int x = 0; x < size; x++)
|
||||
{
|
||||
for (int z = 0; z < size; z++)
|
||||
{
|
||||
dos.writeByte(get(x, z).getSingleLength());
|
||||
}
|
||||
}
|
||||
// Data array content (only on non-empty columns)
|
||||
dos.writeInt(0xFFFFFFFF);
|
||||
for (int x = 0; x < size; x++)
|
||||
{
|
||||
for (int z = 0; z < size; z++)
|
||||
{
|
||||
SingleFullArrayView column = get(x, z);
|
||||
if (!column.doesItExist())
|
||||
continue;
|
||||
long[] raw = column.getRaw();
|
||||
for (long l : raw)
|
||||
{
|
||||
dos.writeLong(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Id mapping
|
||||
dos.writeInt(0xFFFFFFFF);
|
||||
mapping.serialize(dos);
|
||||
dos.writeInt(0xFFFFFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static FullDataSource loadData(DataMetaFile dataFile, InputStream dataStream, IDhLevel level) throws IOException
|
||||
{
|
||||
DataInputStream dos = new DataInputStream(dataStream); // DO NOT CLOSE
|
||||
{
|
||||
int dataDetail = dos.readInt();
|
||||
if (dataDetail != dataFile.metaData.dataLevel)
|
||||
throw new IOException(LodUtil.formatLog("Data level mismatch: {} != {}", dataDetail, dataFile.metaData.dataLevel));
|
||||
int size = dos.readInt();
|
||||
if (size != SECTION_SIZE)
|
||||
throw new IOException(LodUtil.formatLog(
|
||||
"Section size mismatch: {} != {} (Currently only 1 section size is supported)", size, SECTION_SIZE));
|
||||
int minY = dos.readInt();
|
||||
if (minY != level.getMinY())
|
||||
LOGGER.warn("Data minY mismatch: {} != {}. Will ignore data's y level", minY, level.getMinY());
|
||||
int end = dos.readInt();
|
||||
// Data array length
|
||||
if (end == 0x00000001)
|
||||
{
|
||||
// Section is empty
|
||||
return new FullDataSource(dataFile.pos);
|
||||
}
|
||||
// Non-empty section
|
||||
if (end != 0xFFFFFFFF)
|
||||
throw new IOException("invalid header end guard");
|
||||
long[][] data = new long[size * size][];
|
||||
for (int x = 0; x < size; x++)
|
||||
{
|
||||
for (int z = 0; z < size; z++)
|
||||
{
|
||||
data[x * size + z] = new long[dos.readByte()];
|
||||
}
|
||||
}
|
||||
// Data array content (only on non-empty columns)
|
||||
end = dos.readInt();
|
||||
if (end != 0xFFFFFFFF)
|
||||
throw new IOException("invalid data length end guard");
|
||||
for (int i = 0; i < data.length; i++)
|
||||
{
|
||||
if (data[i].length == 0)
|
||||
continue;
|
||||
for (int j = 0; j < data[i].length; j++)
|
||||
{
|
||||
data[i][j] = dos.readLong();
|
||||
}
|
||||
}
|
||||
// Id mapping
|
||||
end = dos.readInt();
|
||||
if (end != 0xFFFFFFFF)
|
||||
throw new IOException("invalid data content end guard");
|
||||
IdBiomeBlockStateMap mapping = IdBiomeBlockStateMap.deserialize(new UnclosableInputStream(dos));
|
||||
end = dos.readInt();
|
||||
if (end != 0xFFFFFFFF)
|
||||
throw new IOException("invalid id mapping end guard");
|
||||
return new FullDataSource(dataFile.pos, mapping, data);
|
||||
}
|
||||
}
|
||||
|
||||
private FullDataSource(DhSectionPos pos, IdBiomeBlockStateMap mapping, long[][] data)
|
||||
{
|
||||
super(mapping, data, SECTION_SIZE);
|
||||
LodUtil.assertTrue(data.length == SECTION_SIZE * SECTION_SIZE);
|
||||
this.sectionPos = pos;
|
||||
isEmpty = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(ChunkSizedData data) {
|
||||
LodUtil.assertTrue(sectionPos.getSectionBBoxPos().overlaps(data.getBBoxLodPos()));
|
||||
if (data.dataDetail == 0 && getDataDetail() == 0) {
|
||||
DhBlockPos2D chunkBlockPos = new DhBlockPos2D(data.x * 16, data.z * 16);
|
||||
DhBlockPos2D blockOffset = chunkBlockPos.subtract(sectionPos.getCorner().getCorner());
|
||||
LodUtil.assertTrue(blockOffset.x >= 0 && blockOffset.x < SECTION_SIZE && blockOffset.z >= 0 && blockOffset.z < SECTION_SIZE);
|
||||
isEmpty = false;
|
||||
data.shadowCopyTo(this.subView(16, blockOffset.x, blockOffset.z));
|
||||
{ // DEBUG ASSERTION
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
SingleFullArrayView column = this.get(x + blockOffset.x, z + blockOffset.z);
|
||||
LodUtil.assertTrue(column.doesItExist());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (data.dataDetail == 0 && getDataDetail() < 4) {
|
||||
int dataPerFull = 1 << getDataDetail();
|
||||
int fullSize = 16 / dataPerFull;
|
||||
DhLodPos dataOffset = data.getBBoxLodPos().getCorner(getDataDetail());
|
||||
DhLodPos baseOffset = sectionPos.getCorner(getDataDetail());
|
||||
int offsetX = dataOffset.x - baseOffset.x;
|
||||
int offsetZ = dataOffset.z - baseOffset.z;
|
||||
LodUtil.assertTrue(offsetX >= 0 && offsetX < SECTION_SIZE && offsetZ >= 0 && offsetZ < SECTION_SIZE);
|
||||
isEmpty = false;
|
||||
for (int ox = 0; ox < fullSize; ox++) {
|
||||
for (int oz = 0; oz < fullSize; oz++) {
|
||||
SingleFullArrayView column = this.get(ox + offsetX, oz + offsetZ);
|
||||
column.downsampleFrom(data.subView(dataPerFull, ox * dataPerFull, oz * dataPerFull));
|
||||
}
|
||||
}
|
||||
} else if (data.dataDetail == 0 && getDataDetail() >= 4) {
|
||||
//FIXME: TEMPORARY
|
||||
int chunkPerFull = 1 << (getDataDetail() - 4);
|
||||
if (data.x % chunkPerFull != 0 || data.z % chunkPerFull != 0) return;
|
||||
DhLodPos baseOffset = sectionPos.getCorner(getDataDetail());
|
||||
DhLodPos dataOffset = data.getBBoxLodPos().convertUpwardsTo(getDataDetail());
|
||||
int offsetX = dataOffset.x - baseOffset.x;
|
||||
int offsetZ = dataOffset.z - baseOffset.z;
|
||||
LodUtil.assertTrue(offsetX >= 0 && offsetX < SECTION_SIZE && offsetZ >= 0 && offsetZ < SECTION_SIZE);
|
||||
isEmpty = false;
|
||||
data.get(0,0).deepCopyTo(get(offsetX, offsetZ));
|
||||
} else {
|
||||
LodUtil.assertNotReach();
|
||||
//TODO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return isEmpty;
|
||||
}
|
||||
public void markNotEmpty() {
|
||||
isEmpty = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveData(IDhLevel level, DataMetaFile file, OutputStream dataStream) throws IOException {
|
||||
DataOutputStream dos = new DataOutputStream(dataStream); // DO NOT CLOSE
|
||||
{
|
||||
dos.writeInt(getDataDetail());
|
||||
dos.writeInt(size);
|
||||
dos.writeInt(level.getMinY());
|
||||
if (isEmpty) {
|
||||
dos.writeInt(0x00000001);
|
||||
return;
|
||||
}
|
||||
dos.writeInt(0xFFFFFFFF);
|
||||
// Data array length
|
||||
for (int x = 0; x < size; x++) {
|
||||
for (int z = 0; z < size; z++) {
|
||||
dos.writeByte(get(x, z).getSingleLength());
|
||||
}
|
||||
}
|
||||
// Data array content (only on non-empty columns)
|
||||
dos.writeInt(0xFFFFFFFF);
|
||||
for (int x = 0; x < size; x++) {
|
||||
for (int z = 0; z < size; z++) {
|
||||
SingleFullArrayView column = get(x, z);
|
||||
if (!column.doesItExist()) continue;
|
||||
long[] raw = column.getRaw();
|
||||
for (long l : raw) {
|
||||
dos.writeLong(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Id mapping
|
||||
dos.writeInt(0xFFFFFFFF);
|
||||
mapping.serialize(dos);
|
||||
dos.writeInt(0xFFFFFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static FullDataSource loadData(DataMetaFile dataFile, InputStream dataStream, IDhLevel level) throws IOException {
|
||||
DataInputStream dos = new DataInputStream(dataStream); // DO NOT CLOSE
|
||||
{
|
||||
int dataDetail = dos.readInt();
|
||||
if(dataDetail != dataFile.metaData.dataLevel)
|
||||
throw new IOException(LodUtil.formatLog("Data level mismatch: {} != {}", dataDetail, dataFile.metaData.dataLevel));
|
||||
int size = dos.readInt();
|
||||
if (size != SECTION_SIZE)
|
||||
throw new IOException(LodUtil.formatLog(
|
||||
"Section size mismatch: {} != {} (Currently only 1 section size is supported)", size, SECTION_SIZE));
|
||||
int minY = dos.readInt();
|
||||
if (minY != level.getMinY())
|
||||
LOGGER.warn("Data minY mismatch: {} != {}. Will ignore data's y level", minY, level.getMinY());
|
||||
int end = dos.readInt();
|
||||
// Data array length
|
||||
if (end == 0x00000001) {
|
||||
// Section is empty
|
||||
return new FullDataSource(dataFile.pos);
|
||||
}
|
||||
// Non-empty section
|
||||
if (end != 0xFFFFFFFF) throw new IOException("invalid header end guard");
|
||||
long[][] data = new long[size*size][];
|
||||
for (int x = 0; x < size; x++) {
|
||||
for (int z = 0; z < size; z++) {
|
||||
data[x*size+z] = new long[dos.readByte()];
|
||||
}
|
||||
}
|
||||
// Data array content (only on non-empty columns)
|
||||
end = dos.readInt();
|
||||
if (end != 0xFFFFFFFF) throw new IOException("invalid data length end guard");
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
if (data[i].length == 0) continue;
|
||||
for (int j = 0; j < data[i].length; j++) {
|
||||
data[i][j] = dos.readLong();
|
||||
}
|
||||
}
|
||||
// Id mapping
|
||||
end = dos.readInt();
|
||||
if (end != 0xFFFFFFFF) throw new IOException("invalid data content end guard");
|
||||
IdBiomeBlockStateMap mapping = IdBiomeBlockStateMap.deserialize(new UnclosableInputStream(dos));
|
||||
end = dos.readInt();
|
||||
if (end != 0xFFFFFFFF) throw new IOException("invalid id mapping end guard");
|
||||
return new FullDataSource(dataFile.pos, mapping, data);
|
||||
}
|
||||
}
|
||||
|
||||
private FullDataSource(DhSectionPos pos, IdBiomeBlockStateMap mapping, long[][] data) {
|
||||
super(mapping, data, SECTION_SIZE);
|
||||
LodUtil.assertTrue(data.length == SECTION_SIZE*SECTION_SIZE);
|
||||
this.sectionPos = pos;
|
||||
isEmpty = false;
|
||||
}
|
||||
|
||||
public static FullDataSource createEmpty(DhSectionPos pos) {
|
||||
return new FullDataSource(pos);
|
||||
}
|
||||
|
||||
public static boolean neededForPosition(DhSectionPos posToWrite, DhSectionPos posToTest) {
|
||||
if (!posToWrite.overlaps(posToTest)) return false;
|
||||
if (posToTest.sectionDetail > posToWrite.sectionDetail) return false;
|
||||
if (posToWrite.sectionDetail - posToTest.sectionDetail <= SECTION_SIZE_OFFSET) return true;
|
||||
byte sectPerData = (byte) (1 << (posToWrite.sectionDetail - posToTest.sectionDetail - SECTION_SIZE_OFFSET));
|
||||
return posToTest.sectionX % sectPerData == 0 && posToTest.sectionZ % sectPerData == 0;
|
||||
}
|
||||
|
||||
public void writeFromLower(FullDataSource subData) {
|
||||
LodUtil.assertTrue(sectionPos.overlaps(subData.sectionPos));
|
||||
LodUtil.assertTrue(subData.sectionPos.sectionDetail < sectionPos.sectionDetail);
|
||||
if (!neededForPosition(sectionPos, subData.sectionPos)) return;
|
||||
DhSectionPos lowerSectPos = subData.sectionPos;
|
||||
byte detailDiff = (byte) (sectionPos.sectionDetail - subData.sectionPos.sectionDetail);
|
||||
byte targetDataDetail = getDataDetail();
|
||||
DhLodPos minDataPos = sectionPos.getCorner(targetDataDetail);
|
||||
if (detailDiff <= SECTION_SIZE_OFFSET) {
|
||||
int count = 1 << detailDiff;
|
||||
int dataPerCount = SECTION_SIZE / count;
|
||||
DhLodPos subDataPos = lowerSectPos.getSectionBBoxPos().getCorner(targetDataDetail);
|
||||
int dataOffsetX = subDataPos.x - minDataPos.x;
|
||||
int dataOffsetZ = subDataPos.z - minDataPos.z;
|
||||
LodUtil.assertTrue(dataOffsetX >= 0 && dataOffsetX < SECTION_SIZE && dataOffsetZ >= 0 && dataOffsetZ < SECTION_SIZE);
|
||||
|
||||
for (int ox = 0; ox < count; ox++) {
|
||||
for (int oz = 0; oz < count; oz++) {
|
||||
SingleFullArrayView column = this.get(ox + dataOffsetX, oz + dataOffsetZ);
|
||||
column.downsampleFrom(subData.subView(dataPerCount, ox * dataPerCount, oz * dataPerCount));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Count == 1
|
||||
DhLodPos subDataPos = lowerSectPos.getSectionBBoxPos().convertUpwardsTo(targetDataDetail);
|
||||
int dataOffsetX = subDataPos.x - minDataPos.x;
|
||||
int dataOffsetZ = subDataPos.z - minDataPos.z;
|
||||
LodUtil.assertTrue(dataOffsetX >= 0 && dataOffsetX < SECTION_SIZE && dataOffsetZ >= 0 && dataOffsetZ < SECTION_SIZE);
|
||||
subData.get(0,0).deepCopyTo(get(dataOffsetX, dataOffsetZ));
|
||||
}
|
||||
}
|
||||
public static FullDataSource createEmpty(DhSectionPos pos) { return new FullDataSource(pos); }
|
||||
|
||||
public static boolean neededForPosition(DhSectionPos posToWrite, DhSectionPos posToTest)
|
||||
{
|
||||
if (!posToWrite.overlaps(posToTest))
|
||||
return false;
|
||||
if (posToTest.sectionDetail > posToWrite.sectionDetail)
|
||||
return false;
|
||||
if (posToWrite.sectionDetail - posToTest.sectionDetail <= SECTION_SIZE_OFFSET)
|
||||
return true;
|
||||
byte sectPerData = (byte) (1 << (posToWrite.sectionDetail - posToTest.sectionDetail - SECTION_SIZE_OFFSET));
|
||||
return posToTest.sectionX % sectPerData == 0 && posToTest.sectionZ % sectPerData == 0;
|
||||
}
|
||||
|
||||
public void writeFromLower(FullDataSource subData)
|
||||
{
|
||||
LodUtil.assertTrue(sectionPos.overlaps(subData.sectionPos));
|
||||
LodUtil.assertTrue(subData.sectionPos.sectionDetail < sectionPos.sectionDetail);
|
||||
if (!neededForPosition(sectionPos, subData.sectionPos))
|
||||
return;
|
||||
DhSectionPos lowerSectPos = subData.sectionPos;
|
||||
byte detailDiff = (byte) (sectionPos.sectionDetail - subData.sectionPos.sectionDetail);
|
||||
byte targetDataDetail = getDataDetail();
|
||||
DhLodPos minDataPos = sectionPos.getCorner(targetDataDetail);
|
||||
if (detailDiff <= SECTION_SIZE_OFFSET)
|
||||
{
|
||||
int count = 1 << detailDiff;
|
||||
int dataPerCount = SECTION_SIZE / count;
|
||||
DhLodPos subDataPos = lowerSectPos.getSectionBBoxPos().getCorner(targetDataDetail);
|
||||
int dataOffsetX = subDataPos.x - minDataPos.x;
|
||||
int dataOffsetZ = subDataPos.z - minDataPos.z;
|
||||
LodUtil.assertTrue(dataOffsetX >= 0 && dataOffsetX < SECTION_SIZE && dataOffsetZ >= 0 && dataOffsetZ < SECTION_SIZE);
|
||||
|
||||
for (int ox = 0; ox < count; ox++)
|
||||
{
|
||||
for (int oz = 0; oz < count; oz++)
|
||||
{
|
||||
SingleFullArrayView column = this.get(ox + dataOffsetX, oz + dataOffsetZ);
|
||||
column.downsampleFrom(subData.subView(dataPerCount, ox * dataPerCount, oz * dataPerCount));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Count == 1
|
||||
DhLodPos subDataPos = lowerSectPos.getSectionBBoxPos().convertUpwardsTo(targetDataDetail);
|
||||
int dataOffsetX = subDataPos.x - minDataPos.x;
|
||||
int dataOffsetZ = subDataPos.z - minDataPos.z;
|
||||
LodUtil.assertTrue(dataOffsetX >= 0 && dataOffsetX < SECTION_SIZE && dataOffsetZ >= 0 && dataOffsetZ < SECTION_SIZE);
|
||||
subData.get(0, 0).deepCopyTo(get(dataOffsetX, dataOffsetZ));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,99 +11,121 @@ import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
// WARNING: This is not THREAD-SAFE!
|
||||
public class IdBiomeBlockStateMap {
|
||||
public static final IWrapperFactory FACTORY = SingletonInjector.INSTANCE.get(IWrapperFactory.class);
|
||||
|
||||
public static final class Entry {
|
||||
public final IBiomeWrapper biome;
|
||||
public final IBlockStateWrapper blockState;
|
||||
public Entry(IBiomeWrapper biome, IBlockStateWrapper blockState) {
|
||||
this.biome = biome;
|
||||
this.blockState = blockState;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(biome, blockState);
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other == this) return true;
|
||||
if (!(other instanceof Entry)) return false;
|
||||
return ((Entry) other).biome.equals(biome) && ((Entry) other).blockState.equals(blockState);
|
||||
}
|
||||
|
||||
public String serialize() {
|
||||
return biome.serialize() + " " + blockState.serialize();
|
||||
}
|
||||
|
||||
public static Entry deserialize(String str) throws IOException {
|
||||
String[] strs = str.split(" ");
|
||||
if (strs.length != 2) throw new IOException("Failed to deserialize BiomeBlockStateEntry");
|
||||
IBiomeWrapper biome = FACTORY.deserializeBiomeWrapper(strs[0]);
|
||||
IBlockStateWrapper blockState = FACTORY.deserializeBlockStateWrapper(strs[1]);
|
||||
return new Entry(biome, blockState);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final ArrayList<Entry> entries = new ArrayList<>();
|
||||
final ConcurrentHashMap<Entry, Integer> idMap = new ConcurrentHashMap<>(); // FIXME: Improve performance
|
||||
|
||||
public Entry get(int id) {
|
||||
return entries.get(id);
|
||||
}
|
||||
|
||||
public int setAndGetId(IBiomeWrapper biome, IBlockStateWrapper blockState) {
|
||||
return idMap.computeIfAbsent(new Entry(biome, blockState), (e) -> {
|
||||
int id = entries.size();
|
||||
entries.add(e);
|
||||
return id;
|
||||
});
|
||||
}
|
||||
public int setAndGetId(Entry biomeBlockStateEntry) {
|
||||
return idMap.computeIfAbsent(biomeBlockStateEntry, (e) -> {
|
||||
int id = entries.size();
|
||||
entries.add(e);
|
||||
return id;
|
||||
});
|
||||
}
|
||||
|
||||
public int[] computeAndMergeMapFrom(IdBiomeBlockStateMap target) {
|
||||
ArrayList<Entry> mergeEntry = target.entries;
|
||||
int[] mapper = new int[mergeEntry.size()];
|
||||
for (int i=0; i<mergeEntry.size(); i++) {
|
||||
mapper[i] = setAndGetId(mergeEntry.get(i));
|
||||
}
|
||||
return mapper;
|
||||
}
|
||||
|
||||
void serialize(OutputStream os) throws IOException {
|
||||
DataOutputStream dos = new DataOutputStream(os); // DO NOT CLOSE!
|
||||
dos.writeInt(entries.size());
|
||||
for (Entry e : entries) {
|
||||
dos.writeUTF(e.serialize());
|
||||
}
|
||||
}
|
||||
static IdBiomeBlockStateMap deserialize(InputStream is) throws IOException {
|
||||
DataInputStream dis = new DataInputStream(is); // DO NOT CLOSE!
|
||||
int size = dis.readInt();
|
||||
IdBiomeBlockStateMap map = new IdBiomeBlockStateMap();
|
||||
for (int i = 0; i < size; i++) {
|
||||
map.entries.add(Entry.deserialize(dis.readUTF()));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other == this) return true;
|
||||
/** WARNING: This is not THREAD-SAFE! */
|
||||
public class IdBiomeBlockStateMap
|
||||
{
|
||||
public static final IWrapperFactory FACTORY = SingletonInjector.INSTANCE.get(IWrapperFactory.class);
|
||||
|
||||
public static final class Entry
|
||||
{
|
||||
public final IBiomeWrapper biome;
|
||||
public final IBlockStateWrapper blockState;
|
||||
|
||||
public Entry(IBiomeWrapper biome, IBlockStateWrapper blockState)
|
||||
{
|
||||
this.biome = biome;
|
||||
this.blockState = blockState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(biome, blockState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other)
|
||||
{
|
||||
if (other == this)
|
||||
return true;
|
||||
if (!(other instanceof Entry))
|
||||
return false;
|
||||
return ((Entry) other).biome.equals(biome) && ((Entry) other).blockState.equals(blockState);
|
||||
}
|
||||
|
||||
public String serialize() { return biome.serialize() + " " + blockState.serialize(); }
|
||||
|
||||
public static Entry deserialize(String str) throws IOException
|
||||
{
|
||||
String[] strs = str.split(" ");
|
||||
if (strs.length != 2)
|
||||
throw new IOException("Failed to deserialize BiomeBlockStateEntry");
|
||||
|
||||
IBiomeWrapper biome = FACTORY.deserializeBiomeWrapper(strs[0]);
|
||||
IBlockStateWrapper blockState = FACTORY.deserializeBlockStateWrapper(strs[1]);
|
||||
return new Entry(biome, blockState);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final ArrayList<Entry> entries = new ArrayList<>();
|
||||
final ConcurrentHashMap<Entry, Integer> idMap = new ConcurrentHashMap<>(); // FIXME: Improve performance
|
||||
|
||||
public Entry get(int id) { return entries.get(id); }
|
||||
|
||||
public int setAndGetId(IBiomeWrapper biome, IBlockStateWrapper blockState)
|
||||
{
|
||||
return idMap.computeIfAbsent(new Entry(biome, blockState), (e) -> {
|
||||
int id = entries.size();
|
||||
entries.add(e);
|
||||
return id;
|
||||
});
|
||||
}
|
||||
|
||||
public int setAndGetId(Entry biomeBlockStateEntry)
|
||||
{
|
||||
return idMap.computeIfAbsent(biomeBlockStateEntry, (e) -> {
|
||||
int id = entries.size();
|
||||
entries.add(e);
|
||||
return id;
|
||||
});
|
||||
}
|
||||
|
||||
public int[] computeAndMergeMapFrom(IdBiomeBlockStateMap target)
|
||||
{
|
||||
ArrayList<Entry> mergeEntry = target.entries;
|
||||
int[] mapper = new int[mergeEntry.size()];
|
||||
for (int i = 0; i < mergeEntry.size(); i++)
|
||||
{
|
||||
mapper[i] = setAndGetId(mergeEntry.get(i));
|
||||
}
|
||||
return mapper;
|
||||
}
|
||||
|
||||
void serialize(OutputStream os) throws IOException
|
||||
{
|
||||
DataOutputStream dos = new DataOutputStream(os); // DO NOT CLOSE!
|
||||
dos.writeInt(entries.size());
|
||||
for (Entry e : entries)
|
||||
{
|
||||
dos.writeUTF(e.serialize());
|
||||
}
|
||||
}
|
||||
|
||||
static IdBiomeBlockStateMap deserialize(InputStream is) throws IOException
|
||||
{
|
||||
DataInputStream dis = new DataInputStream(is); // DO NOT CLOSE!
|
||||
int size = dis.readInt();
|
||||
IdBiomeBlockStateMap map = new IdBiomeBlockStateMap();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
map.entries.add(Entry.deserialize(dis.readUTF()));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other)
|
||||
{
|
||||
if (other == this)
|
||||
return true;
|
||||
// if (!(other instanceof IdBiomeBlockStateMap)) return false;
|
||||
// IdBiomeBlockStateMap otherMap = (IdBiomeBlockStateMap) other;
|
||||
// if (entries.size() != otherMap.entries.size()) return false;
|
||||
// for (int i=0; i<entries.size(); i++) {
|
||||
// if (!entries.get(i).equals(otherMap.entries.get(i))) return false;
|
||||
// }
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,92 +4,111 @@ import com.seibel.lod.core.datatype.full.FullFormat;
|
||||
import com.seibel.lod.core.datatype.full.IdBiomeBlockStateMap;
|
||||
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 IdBiomeBlockStateMap mapping;
|
||||
|
||||
public FullArrayView(IdBiomeBlockStateMap mapping, long[][] dataArrays, int size) {
|
||||
if (dataArrays.length != size*size)
|
||||
throw new IllegalArgumentException(
|
||||
"tried constructing dataArrayView with invalid input!");
|
||||
this.dataArrays = dataArrays;
|
||||
this.size = size;
|
||||
this.dataSize = size;
|
||||
this.mapping = mapping;
|
||||
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!");
|
||||
dataArrays = source.dataArrays;
|
||||
this.size = size;
|
||||
this.dataSize = source.dataSize;
|
||||
mapping = source.mapping;
|
||||
offset = source.offset + offsetX * dataSize + offsetZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdBiomeBlockStateMap getMapping() {
|
||||
return mapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingleFullArrayView get(int index) {
|
||||
return get(index/size, index%size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingleFullArrayView get(int x, int z) {
|
||||
return new SingleFullArrayView(mapping, dataArrays, x*size + z + offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int width() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullArrayView subView(int size, int ox, int oz) {
|
||||
return new FullArrayView(this, size, ox, oz);
|
||||
}
|
||||
|
||||
//WARNING: It will potentially share the underlying array object!
|
||||
public void shadowCopyTo(FullArrayView target) {
|
||||
if (target.size != size)
|
||||
throw new IllegalArgumentException("Target view must have same size as this view");
|
||||
if (target.mapping.equals(mapping)) {
|
||||
for (int x = 0; x < size; x++) {
|
||||
System.arraycopy(dataArrays, offset + x * dataSize,
|
||||
target.dataArrays, target.offset + x * target.dataSize, size);
|
||||
}
|
||||
}
|
||||
else {
|
||||
int[] map = target.mapping.computeAndMergeMapFrom(mapping);
|
||||
for (int x = 0; x < size; x++) {
|
||||
for (int o=0; o<size; o++) {
|
||||
long[] sourceData = dataArrays[offset + x * dataSize + o];
|
||||
long[] newData = new long[sourceData.length];
|
||||
for (int i = 0; i < newData.length; i++) {
|
||||
newData[i] = FullFormat.remap(map, sourceData[i]);
|
||||
}
|
||||
target.dataArrays[target.offset + x * target.dataSize + o] = newData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void downsampleFrom(FullArrayView source) {
|
||||
LodUtil.assertTrue(source.size > size && source.size % size == 0);
|
||||
int dataPerUnit = source.size / size;
|
||||
for (int ox = 0; ox < size; ox++) {
|
||||
for (int oz = 0; oz < size; oz++) {
|
||||
SingleFullArrayView column = get(ox, oz);
|
||||
column.downsampleFrom(source.subView(dataPerUnit, ox * dataPerUnit, oz * dataPerUnit));
|
||||
}
|
||||
}
|
||||
}
|
||||
public class FullArrayView implements IFullDataView
|
||||
{
|
||||
protected final long[][] dataArrays;
|
||||
protected final int offset;
|
||||
protected final int size;
|
||||
protected final int dataSize;
|
||||
protected final IdBiomeBlockStateMap mapping;
|
||||
|
||||
public FullArrayView(IdBiomeBlockStateMap mapping, long[][] dataArrays, int size)
|
||||
{
|
||||
if (dataArrays.length != size * size)
|
||||
throw new IllegalArgumentException(
|
||||
"tried constructing dataArrayView with invalid input!");
|
||||
this.dataArrays = dataArrays;
|
||||
this.size = size;
|
||||
this.dataSize = size;
|
||||
this.mapping = mapping;
|
||||
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!");
|
||||
dataArrays = source.dataArrays;
|
||||
this.size = size;
|
||||
this.dataSize = source.dataSize;
|
||||
mapping = source.mapping;
|
||||
offset = source.offset + offsetX * dataSize + offsetZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdBiomeBlockStateMap getMapping()
|
||||
{
|
||||
return mapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingleFullArrayView get(int index)
|
||||
{
|
||||
return get(index / size, index % size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingleFullArrayView get(int x, int z)
|
||||
{
|
||||
return new SingleFullArrayView(mapping, dataArrays, x * size + z + offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int width()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullArrayView subView(int size, int ox, int oz)
|
||||
{
|
||||
return new FullArrayView(this, size, ox, oz);
|
||||
}
|
||||
|
||||
/** WARNING: It will potentially share the underlying array object! */
|
||||
public void shadowCopyTo(FullArrayView target)
|
||||
{
|
||||
if (target.size != size)
|
||||
throw new IllegalArgumentException("Target view must have same size as this view");
|
||||
if (target.mapping.equals(mapping))
|
||||
{
|
||||
for (int x = 0; x < size; x++)
|
||||
{
|
||||
System.arraycopy(dataArrays, offset + x * dataSize,
|
||||
target.dataArrays, target.offset + x * target.dataSize, size);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int[] map = target.mapping.computeAndMergeMapFrom(mapping);
|
||||
for (int x = 0; x < size; x++)
|
||||
{
|
||||
for (int o = 0; o < size; o++)
|
||||
{
|
||||
long[] sourceData = dataArrays[offset + x * dataSize + o];
|
||||
long[] newData = new long[sourceData.length];
|
||||
for (int i = 0; i < newData.length; i++)
|
||||
{
|
||||
newData[i] = FullFormat.remap(map, sourceData[i]);
|
||||
}
|
||||
target.dataArrays[target.offset + x * target.dataSize + o] = newData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void downsampleFrom(FullArrayView source)
|
||||
{
|
||||
LodUtil.assertTrue(source.size > size && source.size % size == 0);
|
||||
int dataPerUnit = source.size / size;
|
||||
for (int ox = 0; ox < size; ox++)
|
||||
{
|
||||
for (int oz = 0; oz < size; oz++)
|
||||
{
|
||||
SingleFullArrayView column = get(ox, oz);
|
||||
column.downsampleFrom(source.subView(dataPerUnit, ox * dataPerUnit, oz * dataPerUnit));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,27 +5,39 @@ import com.seibel.lod.core.util.LodUtil;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
public interface IFullDataView {
|
||||
IdBiomeBlockStateMap getMapping();
|
||||
|
||||
SingleFullArrayView get(int index);
|
||||
SingleFullArrayView get(int x, int z);
|
||||
int width();
|
||||
default Iterator<SingleFullArrayView> iterator() {
|
||||
return new Iterator<SingleFullArrayView>() {
|
||||
private int index = 0;
|
||||
private final int size = width()*width();
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return index < size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingleFullArrayView next() {
|
||||
LodUtil.assertTrue(hasNext(), "No more data to iterate!");
|
||||
return get(index++);
|
||||
}
|
||||
};
|
||||
}
|
||||
IFullDataView subView(int size, int ox, int oz);
|
||||
public interface IFullDataView
|
||||
{
|
||||
IdBiomeBlockStateMap getMapping();
|
||||
|
||||
SingleFullArrayView get(int index);
|
||||
|
||||
SingleFullArrayView get(int x, int z);
|
||||
|
||||
int width();
|
||||
|
||||
/** Returns an iterator that */
|
||||
default Iterator<SingleFullArrayView> iterator()
|
||||
{
|
||||
return new Iterator<SingleFullArrayView>()
|
||||
{
|
||||
private int index = 0;
|
||||
private final int size = width() * width();
|
||||
|
||||
@Override
|
||||
public boolean hasNext()
|
||||
{
|
||||
return index < size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingleFullArrayView next()
|
||||
{
|
||||
LodUtil.assertTrue(hasNext(), "No more data to iterate!");
|
||||
return get(index++);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
IFullDataView subView(int size, int ox, int oz);
|
||||
|
||||
}
|
||||
|
||||
+102
-93
@@ -3,97 +3,106 @@ package com.seibel.lod.core.datatype.full.accessor;
|
||||
import com.seibel.lod.core.datatype.full.FullFormat;
|
||||
import com.seibel.lod.core.datatype.full.IdBiomeBlockStateMap;
|
||||
|
||||
public class SingleFullArrayView implements IFullDataView {
|
||||
private final long[][] dataArrays;
|
||||
private final int offset;
|
||||
private final IdBiomeBlockStateMap mapping;
|
||||
public SingleFullArrayView(IdBiomeBlockStateMap mapping, long[][] dataArrays, int offset) {
|
||||
this.dataArrays = dataArrays;
|
||||
this.offset = offset;
|
||||
this.mapping = mapping;
|
||||
}
|
||||
|
||||
public boolean doesItExist() {
|
||||
return dataArrays[offset].length!=0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdBiomeBlockStateMap getMapping() {
|
||||
return mapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingleFullArrayView get(int index) {
|
||||
if (index != 0) throw new IllegalArgumentException("Only contains 1 column of full data!");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingleFullArrayView get(int x, int z) {
|
||||
if (x != 0 || z != 0) throw new IllegalArgumentException("Only contains 1 column of full data!");
|
||||
return this;
|
||||
}
|
||||
public long[] getRaw() {
|
||||
return dataArrays[offset];
|
||||
}
|
||||
|
||||
public long getSingle(int yIndex) {
|
||||
return dataArrays[offset][yIndex];
|
||||
}
|
||||
public void setSingle(int yIndex, long value) {
|
||||
dataArrays[offset][yIndex] = value;
|
||||
}
|
||||
public void setNew(long[] newArray) {
|
||||
dataArrays[offset] = newArray;
|
||||
}
|
||||
|
||||
public int getSingleLength() { return dataArrays[offset].length; }
|
||||
|
||||
@Override
|
||||
public int width() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IFullDataView subView(int size, int ox, int oz) {
|
||||
if (size != 1 || ox != 1 || oz != 1)
|
||||
throw new IllegalArgumentException("Getting invalid range of subView from SingleFullArrayView!");
|
||||
return this;
|
||||
}
|
||||
|
||||
//WARNING: It may potentially share the underlying array object!
|
||||
public void shadowCopyTo(SingleFullArrayView target) {
|
||||
if (target.mapping.equals(mapping)) {
|
||||
target.dataArrays[target.offset] = dataArrays[offset];
|
||||
}
|
||||
else {
|
||||
int[] map = target.mapping.computeAndMergeMapFrom(mapping);
|
||||
long[] sourceData = dataArrays[offset];
|
||||
long[] newData = new long[sourceData.length];
|
||||
for (int i = 0; i < newData.length; i++) {
|
||||
newData[i] = FullFormat.remap(map, sourceData[i]);
|
||||
}
|
||||
target.dataArrays[target.offset] = newData;
|
||||
}
|
||||
}
|
||||
public void deepCopyTo(SingleFullArrayView target) {
|
||||
if (target.mapping.equals(mapping)) {
|
||||
target.dataArrays[target.offset] = dataArrays[offset].clone();
|
||||
}
|
||||
else {
|
||||
int[] map = target.mapping.computeAndMergeMapFrom(mapping);
|
||||
long[] sourceData = dataArrays[offset];
|
||||
long[] newData = new long[sourceData.length];
|
||||
for (int i = 0; i < newData.length; i++) {
|
||||
newData[i] = FullFormat.remap(map, sourceData[i]);
|
||||
}
|
||||
target.dataArrays[target.offset] = newData;
|
||||
}
|
||||
}
|
||||
|
||||
public void downsampleFrom(IFullDataView source) {
|
||||
//TODO: Temp downsample method
|
||||
SingleFullArrayView firstColumn = source.get(0);
|
||||
firstColumn.deepCopyTo(this);
|
||||
}
|
||||
public class SingleFullArrayView implements IFullDataView
|
||||
{
|
||||
private final long[][] dataArrays;
|
||||
private final int offset;
|
||||
private final IdBiomeBlockStateMap mapping;
|
||||
|
||||
public SingleFullArrayView(IdBiomeBlockStateMap mapping, long[][] dataArrays, int offset)
|
||||
{
|
||||
this.dataArrays = dataArrays;
|
||||
this.offset = offset;
|
||||
this.mapping = mapping;
|
||||
}
|
||||
|
||||
public boolean doesItExist() { return dataArrays[offset].length != 0; }
|
||||
|
||||
@Override
|
||||
public IdBiomeBlockStateMap getMapping() { return mapping; }
|
||||
|
||||
@Override
|
||||
public SingleFullArrayView get(int index)
|
||||
{
|
||||
if (index != 0)
|
||||
throw new IllegalArgumentException("Only contains 1 column of full data!");
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingleFullArrayView get(int x, int z)
|
||||
{
|
||||
if (x != 0 || z != 0)
|
||||
throw new IllegalArgumentException("Only contains 1 column of full data!");
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public long[] getRaw() { return dataArrays[offset]; }
|
||||
|
||||
public long getSingle(int yIndex) { return dataArrays[offset][yIndex]; }
|
||||
public void setSingle(int yIndex, long value) { dataArrays[offset][yIndex] = value; }
|
||||
|
||||
public void setNew(long[] newArray) { dataArrays[offset] = newArray; }
|
||||
|
||||
public int getSingleLength() { return dataArrays[offset].length; }
|
||||
|
||||
@Override
|
||||
public int width() { return 1; }
|
||||
|
||||
@Override
|
||||
public IFullDataView subView(int size, int ox, int oz)
|
||||
{
|
||||
if (size != 1 || ox != 1 || oz != 1)
|
||||
throw new IllegalArgumentException("Getting invalid range of subView from SingleFullArrayView!");
|
||||
return this;
|
||||
}
|
||||
|
||||
/** WARNING: It may potentially share the underlying array object! */
|
||||
public void shadowCopyTo(SingleFullArrayView target)
|
||||
{
|
||||
if (target.mapping.equals(mapping))
|
||||
{
|
||||
target.dataArrays[target.offset] = dataArrays[offset];
|
||||
}
|
||||
else
|
||||
{
|
||||
int[] map = target.mapping.computeAndMergeMapFrom(mapping);
|
||||
long[] sourceData = dataArrays[offset];
|
||||
long[] newData = new long[sourceData.length];
|
||||
for (int i = 0; i < newData.length; i++)
|
||||
{
|
||||
newData[i] = FullFormat.remap(map, sourceData[i]);
|
||||
}
|
||||
target.dataArrays[target.offset] = newData;
|
||||
}
|
||||
}
|
||||
|
||||
public void deepCopyTo(SingleFullArrayView target)
|
||||
{
|
||||
if (target.mapping.equals(mapping))
|
||||
{
|
||||
target.dataArrays[target.offset] = dataArrays[offset].clone();
|
||||
}
|
||||
else
|
||||
{
|
||||
int[] map = target.mapping.computeAndMergeMapFrom(mapping);
|
||||
long[] sourceData = dataArrays[offset];
|
||||
long[] newData = new long[sourceData.length];
|
||||
for (int i = 0; i < newData.length; i++)
|
||||
{
|
||||
newData[i] = FullFormat.remap(map, sourceData[i]);
|
||||
}
|
||||
target.dataArrays[target.offset] = newData;
|
||||
}
|
||||
}
|
||||
|
||||
public void downsampleFrom(IFullDataView source)
|
||||
{
|
||||
//TODO: Temp downsample method
|
||||
SingleFullArrayView firstColumn = source.get(0);
|
||||
firstColumn.deepCopyTo(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user