Add a mutable DhSectionPos

This commit is contained in:
James Seibel
2023-09-15 07:34:37 -05:00
parent 2cee805645
commit 1ae1f1f36f
23 changed files with 241 additions and 187 deletions
@@ -113,7 +113,7 @@ public class FullDataDownSampler
// The source occupies only 1 datapoint in the target
// FIXME: TEMP method for down-sampling: take only the corner column
int sourceSectionPerTargetData = 1 << (detailDiff - CompleteFullDataSource.SECTION_SIZE_OFFSET);
if (srcPos.sectionX % sourceSectionPerTargetData != 0 || srcPos.sectionZ % sourceSectionPerTargetData != 0)
if (srcPos.getX() % sourceSectionPerTargetData != 0 || srcPos.getZ() % sourceSectionPerTargetData != 0)
{
return;
}
@@ -332,8 +332,8 @@ public class CompleteFullDataSource extends FullDataArrayAccessor implements IFu
DhLodPos baseOffset = this.sectionPos.getMinCornerLodPos(this.getDataDetailLevel());
DhSectionPos dataOffset = chunkDataView.getSectionPos().convertNewToDetailLevel(this.getDataDetailLevel());
int offsetX = dataOffset.sectionX - baseOffset.x;
int offsetZ = dataOffset.sectionZ - baseOffset.z;
int offsetX = dataOffset.getX() - baseOffset.x;
int offsetZ = dataOffset.getZ() - baseOffset.z;
LodUtil.assertTrue(offsetX >= 0 && offsetX < WIDTH && offsetZ >= 0 && offsetZ < WIDTH);
this.isEmpty = false;
@@ -361,13 +361,13 @@ public class CompleteFullDataSource extends FullDataArrayAccessor implements IFu
// the testPosition is outside the writePosition
return false;
}
else if (posToTest.sectionDetailLevel > posToWrite.sectionDetailLevel)
else if (posToTest.getDetailLevel() > posToWrite.getDetailLevel())
{
// the testPosition is larger (aka is less detailed) than the writePosition,
// more detailed sections shouldn't be updated by lower detail sections
return false;
}
else if (posToWrite.sectionDetailLevel - posToTest.sectionDetailLevel <= SECTION_SIZE_OFFSET)
else if (posToWrite.getDetailLevel() - posToTest.getDetailLevel() <= SECTION_SIZE_OFFSET)
{
// if the difference in detail levels is very large, the posToWrite
// may be skipped, due to how we sample large detail levels by only
@@ -380,9 +380,9 @@ public class CompleteFullDataSource extends FullDataArrayAccessor implements IFu
{
// the difference in detail levels is very large,
// check if the posToWrite is in a corner of posToTest
byte sectPerData = (byte) BitShiftUtil.powerOfTwo(posToWrite.sectionDetailLevel - posToTest.sectionDetailLevel - SECTION_SIZE_OFFSET);
byte sectPerData = (byte) BitShiftUtil.powerOfTwo(posToWrite.getDetailLevel() - posToTest.getDetailLevel() - SECTION_SIZE_OFFSET);
LodUtil.assertTrue(sectPerData != 0);
return posToTest.sectionX % sectPerData == 0 && posToTest.sectionZ % sectPerData == 0;
return posToTest.getX() % sectPerData == 0 && posToTest.getZ() % sectPerData == 0;
}
}
@@ -395,7 +395,7 @@ public class CompleteFullDataSource extends FullDataArrayAccessor implements IFu
@Override
public DhSectionPos getSectionPos() { return this.sectionPos; }
@Override
public byte getDataDetailLevel() { return (byte) (this.sectionPos.sectionDetailLevel - SECTION_SIZE_OFFSET); }
public byte getDataDetailLevel() { return (byte) (this.sectionPos.getDetailLevel() - SECTION_SIZE_OFFSET); }
@Override
public byte getBinaryDataFormatVersion() { return DATA_FORMAT_VERSION; }
@@ -419,14 +419,14 @@ public class CompleteFullDataSource extends FullDataArrayAccessor implements IFu
public void updateFromLowerCompleteSource(CompleteFullDataSource subData)
{
LodUtil.assertTrue(this.sectionPos.overlapsExactly(subData.sectionPos));
LodUtil.assertTrue(subData.sectionPos.sectionDetailLevel < this.sectionPos.sectionDetailLevel);
LodUtil.assertTrue(subData.sectionPos.getDetailLevel() < this.sectionPos.getDetailLevel());
if (!firstDataPosCanAffectSecond(this.sectionPos, subData.sectionPos))
{
return;
}
DhSectionPos lowerSectPos = subData.sectionPos;
byte detailDiff = (byte) (this.sectionPos.sectionDetailLevel - subData.sectionPos.sectionDetailLevel);
byte detailDiff = (byte) (this.sectionPos.getDetailLevel() - subData.sectionPos.getDetailLevel());
byte targetDataDetail = this.getDataDetailLevel();
DhLodPos minDataPos = this.sectionPos.getMinCornerLodPos(targetDataDetail);
if (detailDiff <= SECTION_SIZE_OFFSET)
@@ -96,11 +96,11 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo
public static HighDetailIncompleteFullDataSource createEmpty(DhSectionPos pos) { return new HighDetailIncompleteFullDataSource(pos); }
private HighDetailIncompleteFullDataSource(DhSectionPos sectionPos)
{
LodUtil.assertTrue(sectionPos.sectionDetailLevel > SPARSE_UNIT_DETAIL);
LodUtil.assertTrue(sectionPos.sectionDetailLevel <= MAX_SECTION_DETAIL);
LodUtil.assertTrue(sectionPos.getDetailLevel() > SPARSE_UNIT_DETAIL);
LodUtil.assertTrue(sectionPos.getDetailLevel() <= MAX_SECTION_DETAIL);
this.sectionPos = sectionPos;
this.sectionCount = BitShiftUtil.powerOfTwo(sectionPos.sectionDetailLevel - SPARSE_UNIT_DETAIL);
this.sectionCount = BitShiftUtil.powerOfTwo(sectionPos.getDetailLevel() - SPARSE_UNIT_DETAIL);
this.dataPointsPerSection = SECTION_SIZE / this.sectionCount;
this.sparseData = new FullDataArrayAccessor[this.sectionCount * this.sectionCount];
@@ -110,11 +110,11 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo
protected HighDetailIncompleteFullDataSource(DhSectionPos sectionPos, FullDataPointIdMap mapping, FullDataArrayAccessor[] data)
{
LodUtil.assertTrue(sectionPos.sectionDetailLevel > SPARSE_UNIT_DETAIL);
LodUtil.assertTrue(sectionPos.sectionDetailLevel <= MAX_SECTION_DETAIL);
LodUtil.assertTrue(sectionPos.getDetailLevel() > SPARSE_UNIT_DETAIL);
LodUtil.assertTrue(sectionPos.getDetailLevel() <= MAX_SECTION_DETAIL);
this.sectionPos = sectionPos;
this.sectionCount = 1 << (byte) (sectionPos.sectionDetailLevel - SPARSE_UNIT_DETAIL);
this.sectionCount = 1 << (byte) (sectionPos.getDetailLevel() - SPARSE_UNIT_DETAIL);
this.dataPointsPerSection = SECTION_SIZE / this.sectionCount;
LodUtil.assertTrue(this.sectionCount * this.sectionCount == data.length);
@@ -144,8 +144,8 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo
@Override
public FullDataSourceSummaryData readSourceSummaryInfo(FullDataMetaFile dataFile, DhDataInputStream inputStream, IDhLevel level) throws IOException
{
LodUtil.assertTrue(dataFile.pos.sectionDetailLevel > SPARSE_UNIT_DETAIL);
LodUtil.assertTrue(dataFile.pos.sectionDetailLevel <= MAX_SECTION_DETAIL);
LodUtil.assertTrue(dataFile.pos.getDetailLevel() > SPARSE_UNIT_DETAIL);
LodUtil.assertTrue(dataFile.pos.getDetailLevel() <= MAX_SECTION_DETAIL);
int dataDetail = inputStream.readShort();
if (dataDetail != dataFile.baseMetaData.dataLevel)
@@ -255,7 +255,7 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo
{
// calculate the number of chunks and dataPoints based on the sparseDetail and sectionSize
// TODO these values should be constant, should we still be calculating them like this?
int chunks = BitShiftUtil.powerOfTwo(dataFile.pos.sectionDetailLevel - SPARSE_UNIT_DETAIL);
int chunks = BitShiftUtil.powerOfTwo(dataFile.pos.getDetailLevel() - SPARSE_UNIT_DETAIL);
int dataPointsPerChunk = SECTION_SIZE / chunks;
@@ -421,7 +421,7 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo
@Override
public DhSectionPos getSectionPos() { return this.sectionPos; }
@Override
public byte getDataDetailLevel() { return (byte) (this.sectionPos.sectionDetailLevel - SECTION_SIZE_OFFSET); }
public byte getDataDetailLevel() { return (byte) (this.sectionPos.getDetailLevel() - SECTION_SIZE_OFFSET); }
@Override
public byte getBinaryDataFormatVersion() { return DATA_FORMAT_VERSION; }
@@ -488,7 +488,7 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo
public void sampleFrom(IFullDataSource fullDataSource)
{
DhSectionPos pos = fullDataSource.getSectionPos();
LodUtil.assertTrue(pos.sectionDetailLevel < this.sectionPos.sectionDetailLevel);
LodUtil.assertTrue(pos.getDetailLevel() < this.sectionPos.getDetailLevel());
LodUtil.assertTrue(pos.overlapsExactly(this.sectionPos));
if (fullDataSource.isEmpty())
{
@@ -84,7 +84,7 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp
private LowDetailIncompleteFullDataSource(DhSectionPos sectionPos)
{
super(new FullDataPointIdMap(sectionPos), new long[WIDTH * WIDTH][0], WIDTH);
LodUtil.assertTrue(sectionPos.sectionDetailLevel > HighDetailIncompleteFullDataSource.MAX_SECTION_DETAIL);
LodUtil.assertTrue(sectionPos.getDetailLevel() > HighDetailIncompleteFullDataSource.MAX_SECTION_DETAIL);
this.sectionPos = sectionPos;
this.isColumnNotEmpty = new BitSet(WIDTH * WIDTH);
@@ -295,7 +295,7 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp
@Override
public DhSectionPos getSectionPos() { return this.sectionPos; }
@Override
public byte getDataDetailLevel() { return (byte) (this.sectionPos.sectionDetailLevel - SECTION_SIZE_OFFSET); }
public byte getDataDetailLevel() { return (byte) (this.sectionPos.getDetailLevel() - SECTION_SIZE_OFFSET); }
@Override
public byte getBinaryDataFormatVersion() { return DATA_FORMAT_VERSION; }
@@ -331,8 +331,8 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp
DhLodPos baseOffset = this.sectionPos.getMinCornerLodPos(this.getDataDetailLevel());
DhSectionPos dataOffset = data.getSectionPos().convertNewToDetailLevel(this.getDataDetailLevel());
int offsetX = dataOffset.sectionX - baseOffset.x;
int offsetZ = dataOffset.sectionZ - baseOffset.z;
int offsetX = dataOffset.getX() - baseOffset.x;
int offsetZ = dataOffset.getZ() - baseOffset.z;
LodUtil.assertTrue(offsetX >= 0 && offsetX < WIDTH && offsetZ >= 0 && offsetZ < WIDTH);
this.isEmpty = false;
@@ -353,7 +353,7 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp
public void sampleFrom(IFullDataSource fullDataSource)
{
DhSectionPos pos = fullDataSource.getSectionPos();
LodUtil.assertTrue(pos.sectionDetailLevel < this.sectionPos.sectionDetailLevel);
LodUtil.assertTrue(pos.getDetailLevel() < this.sectionPos.getDetailLevel());
LodUtil.assertTrue(pos.overlapsExactly(this.sectionPos));
if (fullDataSource.isEmpty())
@@ -389,7 +389,7 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp
this.isEmpty = false;
if (this.getDataDetailLevel() > this.sectionPos.sectionDetailLevel)
if (this.getDataDetailLevel() > this.sectionPos.getDetailLevel())
{
DhLodPos dataLodPos = pos.getMinCornerLodPos(this.getDataDetailLevel());
@@ -445,7 +445,7 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp
this.isEmpty = false;
this.downsampleFrom(completeSource);
if (this.getDataDetailLevel() > this.sectionPos.sectionDetailLevel) // TODO what does this mean?
if (this.getDataDetailLevel() > this.sectionPos.getDetailLevel()) // TODO what does this mean?
{
DhLodPos thisLodPos = this.sectionPos.getMinCornerLodPos(this.getDataDetailLevel());
DhLodPos dataLodPos = pos.getMinCornerLodPos(this.getDataDetailLevel());
@@ -488,7 +488,7 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp
this.downsampleFrom(spottySource);
if (this.getDataDetailLevel() > this.sectionPos.sectionDetailLevel)
if (this.getDataDetailLevel() > this.sectionPos.getDetailLevel())
{
DhLodPos thisLodPos = this.sectionPos.getMinCornerLodPos(this.getDataDetailLevel());
DhLodPos dataLodPos = pos.getMinCornerLodPos(this.getDataDetailLevel());
@@ -574,12 +574,12 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp
{
if (!posToWrite.overlapsExactly(posToTest))
return false;
if (posToTest.sectionDetailLevel > posToWrite.sectionDetailLevel)
if (posToTest.getDetailLevel() > posToWrite.getDetailLevel())
return false;
if (posToWrite.sectionDetailLevel - posToTest.sectionDetailLevel <= SECTION_SIZE_OFFSET)
if (posToWrite.getDetailLevel() - posToTest.getDetailLevel() <= SECTION_SIZE_OFFSET)
return true;
byte sectPerData = (byte) (1 << (posToWrite.sectionDetailLevel - posToTest.sectionDetailLevel - SECTION_SIZE_OFFSET));
return posToTest.sectionX % sectPerData == 0 && posToTest.sectionZ % sectPerData == 0;
byte sectPerData = (byte) (1 << (posToWrite.getDetailLevel() - posToTest.getDetailLevel() - SECTION_SIZE_OFFSET));
return posToTest.getX() % sectPerData == 0 && posToTest.getZ() % sectPerData == 0;
}
@@ -103,7 +103,7 @@ public interface IFullDataSource
while (posList.size() > 0)
{
DhSectionPos pos = posList.remove();
if (pos.sectionDetailLevel > highestGeneratorDetailLevel)
if (pos.getDetailLevel() > highestGeneratorDetailLevel)
{
pos.forEachChild((childPos) -> { posList.push(childPos); });
}
@@ -127,20 +127,20 @@ public interface IFullDataSource
int sourceRelWidth = this.getWidthInDataPoints();
if (quadrantPos.sectionDetailLevel < highestGeneratorDetailLevel)
if (quadrantPos.getDetailLevel() < highestGeneratorDetailLevel)
{
throw new IllegalArgumentException("detail level lower than world generator can accept.");
}
else if (quadrantPos.sectionDetailLevel == highestGeneratorDetailLevel)
else if (quadrantPos.getDetailLevel() == highestGeneratorDetailLevel)
{
// we are at the highest detail level the world generator can accept,
// we either need to generate this whole section, or not at all
// TODO combine duplicate code
byte childDetailLevel = (byte) (quadrantPos.sectionDetailLevel);
byte childDetailLevel = (byte) (quadrantPos.getDetailLevel());
int quadrantDetailLevelDiff = this.getSectionPos().sectionDetailLevel - childDetailLevel;
int quadrantDetailLevelDiff = this.getSectionPos().getDetailLevel() - childDetailLevel;
int widthInSecPos = BitShiftUtil.powerOfTwo(quadrantDetailLevelDiff);
int relWidthForSecPos = sourceRelWidth / widthInSecPos;
@@ -149,8 +149,8 @@ public interface IFullDataSource
int minRelX = inputPos.sectionX - minSecPos.sectionX;
int minRelZ = inputPos.sectionZ - minSecPos.sectionZ;
int minRelX = inputPos.getX() - minSecPos.getX();
int minRelZ = inputPos.getZ() - minSecPos.getZ();
int maxRelX = minRelX + 1;
int maxRelZ = minRelZ + 1;
@@ -187,11 +187,11 @@ public interface IFullDataSource
// TODO comment
// TODO combine duplicate code
byte childDetailLevel = (byte) (quadrantPos.sectionDetailLevel - 1);
byte childDetailLevel = (byte) (quadrantPos.getDetailLevel() - 1);
for (int i = 0; i < 4; i++)
{
int quadrantDetailLevelDiff = this.getSectionPos().sectionDetailLevel - childDetailLevel;
int quadrantDetailLevelDiff = this.getSectionPos().getDetailLevel() - childDetailLevel;
int widthInSecPos = BitShiftUtil.powerOfTwo(quadrantDetailLevelDiff);
int relWidthForSecPos = sourceRelWidth / widthInSecPos;
@@ -200,8 +200,8 @@ public interface IFullDataSource
int minRelX = inputPos.sectionX - minSecPos.sectionX;
int minRelZ = inputPos.sectionZ - minSecPos.sectionZ;
int minRelX = inputPos.getX() - minSecPos.getX();
int minRelZ = inputPos.getZ() - minSecPos.getZ();
int maxRelX = minRelX + 1;
int maxRelZ = minRelZ + 1;
@@ -109,7 +109,7 @@ public class ColumnRenderSource
*/
public ColumnRenderSource(DhSectionPos sectionPos, ColumnRenderLoader.ParsedColumnData parsedColumnData, IDhLevel level) throws IOException
{
if (sectionPos.sectionDetailLevel - SECTION_SIZE_OFFSET != parsedColumnData.detailLevel)
if (sectionPos.getDetailLevel() - SECTION_SIZE_OFFSET != parsedColumnData.detailLevel)
{
throw new IOException("Invalid data: detail level does not match");
}
@@ -360,7 +360,7 @@ public class ColumnRenderSource
}
this.fillDebugFlag(blockOffsetX, blockOffsetZ, LodUtil.CHUNK_WIDTH, LodUtil.CHUNK_WIDTH, ColumnRenderSource.DebugSourceFlag.DIRECT);
}
else if (chunkDataView.detailLevel < this.getDataDetail() && this.getDataDetail() <= chunkDataView.getSectionPos().sectionDetailLevel)
else if (chunkDataView.detailLevel < this.getDataDetail() && this.getDataDetail() <= chunkDataView.getSectionPos().getDetailLevel())
{
this.markNotEmpty();
// multiple chunk data points converting to 1 column data point
@@ -390,14 +390,14 @@ public class ColumnRenderSource
}
this.fillDebugFlag(relStartX, relStartZ, columnsInChunk, columnsInChunk, ColumnRenderSource.DebugSourceFlag.DIRECT);
}
else if (chunkDataView.getSectionPos().sectionDetailLevel < this.getDataDetail())
else if (chunkDataView.getSectionPos().getDetailLevel() < this.getDataDetail())
{
// The entire chunk is being converted to a single column data point, possibly.
DhLodPos dataCornerPos = chunkDataView.getSectionPos().getMinCornerLodPos(chunkDataView.detailLevel);
DhLodPos sourceCornerPos = renderSourcePos.getMinCornerLodPos(this.getDataDetail());
DhLodPos sourceStartingChangePos = dataCornerPos.convertToDetailLevel(this.getDataDetail());
int chunksPerColumn = sourceStartingChangePos.getWidthAtDetail(chunkDataView.getSectionPos().sectionDetailLevel);
if (chunkDataView.getSectionPos().sectionX % chunksPerColumn != 0 || chunkDataView.getSectionPos().sectionZ % chunksPerColumn != 0)
int chunksPerColumn = sourceStartingChangePos.getWidthAtDetail(chunkDataView.getSectionPos().getDetailLevel());
if (chunkDataView.getSectionPos().getX() % chunksPerColumn != 0 || chunkDataView.getSectionPos().getZ() % chunksPerColumn != 0)
{
return false; // not a multiple of the column size, so no change
}
@@ -443,7 +443,7 @@ public class ColumnRenderSource
public DhSectionPos getSectionPos() { return this.sectionPos; }
public byte getDataDetail() { return (byte) (this.sectionPos.sectionDetailLevel - SECTION_SIZE_OFFSET); }
public byte getDataDetail() { return (byte) (this.sectionPos.getDetailLevel() - SECTION_SIZE_OFFSET); }
/** @return how many data points wide this {@link ColumnRenderSource} is. */
public int getWidthInDataPoints() { return BitShiftUtil.powerOfTwo(this.getDetailOffset()); }
@@ -88,11 +88,11 @@ public class FullDataFileHandler implements IFullDataSourceProvider
MetaFileScanUtil.IAddUnloadedFileFunc addUnloadedFileFunc = (pos, file) ->
{
this.unloadedFileBySectionPos.put(pos, file);
this.topDetailLevelRef.updateAndGet(oldDetailLevel -> Math.max(oldDetailLevel, pos.sectionDetailLevel));
this.topDetailLevelRef.updateAndGet(oldDetailLevel -> Math.max(oldDetailLevel, pos.getDetailLevel()));
};
MetaFileScanUtil.IAddLoadedMetaFileFunc addLoadedMetaFileFunc = (pos, loadedMetaFile) ->
{
this.topDetailLevelRef.updateAndGet(oldDetailLevel -> Math.max(oldDetailLevel, pos.sectionDetailLevel));
this.topDetailLevelRef.updateAndGet(oldDetailLevel -> Math.max(oldDetailLevel, pos.getDetailLevel()));
this.metaFileBySectionPos.put(pos, (FullDataMetaFile) loadedMetaFile);
};
@@ -119,7 +119,7 @@ public class FullDataFileHandler implements IFullDataSourceProvider
@Override
public CompletableFuture<IFullDataSource> readAsync(DhSectionPos pos)
{
this.topDetailLevelRef.updateAndGet(oldDetailLevel -> Math.max(oldDetailLevel, pos.sectionDetailLevel));
this.topDetailLevelRef.updateAndGet(oldDetailLevel -> Math.max(oldDetailLevel, pos.getDetailLevel()));
FullDataMetaFile metaFile = this.getLoadOrMakeFile(pos, true);
if (metaFile == null)
{
@@ -173,7 +173,7 @@ public class FullDataFileHandler implements IFullDataSourceProvider
try
{
metaFile = FullDataMetaFile.createFromExistingFile(this, this.level, fileToLoad);
this.topDetailLevelRef.updateAndGet(oldDetailLevel -> Math.max(oldDetailLevel, pos.sectionDetailLevel));
this.topDetailLevelRef.updateAndGet(oldDetailLevel -> Math.max(oldDetailLevel, pos.getDetailLevel()));
this.metaFileBySectionPos.put(pos, metaFile);
return metaFile;
}
@@ -208,7 +208,7 @@ public class FullDataFileHandler implements IFullDataSourceProvider
return null;
}
this.topDetailLevelRef.updateAndGet(oldDetailLevel -> Math.max(oldDetailLevel, pos.sectionDetailLevel));
this.topDetailLevelRef.updateAndGet(oldDetailLevel -> Math.max(oldDetailLevel, pos.getDetailLevel()));
// This is a CAS with expected null value.
FullDataMetaFile metaFileCas = this.metaFileBySectionPos.putIfAbsent(pos, metaFile);
@@ -225,10 +225,10 @@ public class FullDataFileHandler implements IFullDataSourceProvider
DhSectionPos effectivePos, DhSectionPos posAreaToGet,
ArrayList<FullDataMetaFile> preexistingFiles, ArrayList<DhSectionPos> missingFilePositions)
{
byte sectionDetail = posAreaToGet.sectionDetailLevel;
byte sectionDetail = posAreaToGet.getDetailLevel();
boolean allEmpty = true;
final DhSectionPos subPos = new DhSectionPos((byte)0, 0, 0);
final DhSectionPos.DhMutableSectionPos subPos = new DhSectionPos.DhMutableSectionPos((byte)0, 0, 0);
// get all existing files for this position
outerLoop:
@@ -294,7 +294,7 @@ public class FullDataFileHandler implements IFullDataSourceProvider
// we have reached a populated leaf node in the quad tree
preexistingFiles.add(metaFile);
}
else if (childPos.sectionDetailLevel == this.minDetailLevel)
else if (childPos.getDetailLevel() == this.minDetailLevel)
{
// we have reached an empty leaf node in the quad tree
missingFilePositions.add(childPos);
@@ -334,7 +334,7 @@ public class FullDataFileHandler implements IFullDataSourceProvider
metaFile.addToWriteQueue(chunkData);
}
if (sectionPos.sectionDetailLevel <= this.topDetailLevelRef.get())
if (sectionPos.getDetailLevel() <= this.topDetailLevelRef.get())
{
// recursively attempt to get the meta file for this position
this.writeChunkDataToMetaFile(sectionPos.getParentPos(), chunkData);
@@ -369,7 +369,7 @@ public class FullDataFileHandler implements IFullDataSourceProvider
protected IIncompleteFullDataSource makeEmptyDataSource(DhSectionPos pos)
{
return pos.sectionDetailLevel <= HighDetailIncompleteFullDataSource.MAX_SECTION_DETAIL ?
return pos.getDetailLevel() <= HighDetailIncompleteFullDataSource.MAX_SECTION_DETAIL ?
HighDetailIncompleteFullDataSource.createEmpty(pos) :
LowDetailIncompleteFullDataSource.createEmpty(pos);
}
@@ -431,7 +431,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I
@Override
public void debugRender(DebugRenderer debugRenderer)
{
if (this.pos.sectionDetailLevel > DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL)
if (this.pos.getDetailLevel() > DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL)
{
return;
}
@@ -555,7 +555,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I
new DataObjSoftTracker(this, fullDataSource);
}
if (this.pos.sectionDetailLevel == DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL)
if (this.pos.getDetailLevel() == DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL)
{
DebugRenderer.makeParticle(new DebugRenderer.BoxParticle(
new DebugRenderer.Box(this.pos, 64f, 72f, 0.03f, Color.green.darker()),
@@ -25,7 +25,6 @@ import java.nio.channels.Channels;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.FileChannel;
import java.nio.file.*;
import java.util.concurrent.locks.ReentrantLock;
import java.util.zip.Adler32;
import java.util.zip.CheckedOutputStream;
@@ -231,11 +230,11 @@ public abstract class AbstractMetaDataContainerFile
fileChannel.position(0);
ByteBuffer buffer = ByteBuffer.allocate(METADATA_SIZE_IN_BYTES);
buffer.putInt(METADATA_IDENTITY_BYTES);
buffer.putInt(this.pos.sectionX);
buffer.putInt(this.pos.getX());
buffer.putInt(Integer.MIN_VALUE); // Unused - y pos
buffer.putInt(this.pos.sectionZ);
buffer.putInt(this.pos.getZ());
buffer.putInt(this.baseMetaData.checksum);
buffer.put(this.pos.sectionDetailLevel);
buffer.put(this.pos.getDetailLevel());
buffer.put(this.baseMetaData.dataLevel);
buffer.put(this.baseMetaData.binaryDataFormatVersion);
buffer.put(this.baseMetaData.worldGenStep != null ? this.baseMetaData.worldGenStep.value : EDhApiWorldGenerationStep.EMPTY.value); // TODO this null check shouldn't be necessary
@@ -197,7 +197,7 @@ public class RenderDataMetaFile extends AbstractMetaDataContainerFile implements
// create an empty render source
byte dataDetailLevel = (byte) (this.pos.sectionDetailLevel - ColumnRenderSource.SECTION_SIZE_OFFSET);
byte dataDetailLevel = (byte) (this.pos.getDetailLevel() - ColumnRenderSource.SECTION_SIZE_OFFSET);
int verticalSize = Config.Client.Advanced.Graphics.Quality.verticalQuality.get().calculateMaxVerticalData(dataDetailLevel);
ColumnRenderSource newColumnRenderSource = new ColumnRenderSource(this.pos, verticalSize, this.clientLevel.getMinY());
@@ -23,7 +23,6 @@ import com.seibel.distanthorizons.core.dataObjects.fullData.accessor.ChunkSizedF
import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
import com.seibel.distanthorizons.core.pos.DhLodPos;
import com.seibel.distanthorizons.core.pos.DhSectionPos;
import com.seibel.distanthorizons.core.dataObjects.render.ColumnRenderSource;
import com.seibel.distanthorizons.core.file.fullDatafile.IFullDataSourceProvider;
@@ -98,11 +97,11 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
MetaFileScanUtil.IAddUnloadedFileFunc addUnloadedFileFunc = (pos, file) ->
{
this.unloadedFileBySectionPos.put(pos, file);
this.topDetailLevelRef.updateAndGet(oldDetailLevel -> Math.max(oldDetailLevel, pos.sectionDetailLevel));
this.topDetailLevelRef.updateAndGet(oldDetailLevel -> Math.max(oldDetailLevel, pos.getDetailLevel()));
};
MetaFileScanUtil.IAddLoadedMetaFileFunc addLoadedMetaFileFunc = (pos, loadedMetaFile) ->
{
this.topDetailLevelRef.updateAndGet(oldDetailLevel -> Math.max(oldDetailLevel, pos.sectionDetailLevel));
this.topDetailLevelRef.updateAndGet(oldDetailLevel -> Math.max(oldDetailLevel, pos.getDetailLevel()));
this.metaFileBySectionPos.put(pos, (RenderDataMetaFile) loadedMetaFile);
};
@@ -195,7 +194,7 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
try
{
metaFile = RenderDataMetaFile.createFromExistingFile(this.fullDataSourceProvider, this.clientLevel, fileToLoad);
this.topDetailLevelRef.updateAndGet(currentTopDetailLevel -> Math.max(currentTopDetailLevel, pos.sectionDetailLevel));
this.topDetailLevelRef.updateAndGet(currentTopDetailLevel -> Math.max(currentTopDetailLevel, pos.getDetailLevel()));
this.metaFileBySectionPos.put(pos, metaFile);
return metaFile;
}
@@ -221,7 +220,7 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
// due to a rare issue where the file may already exist but isn't in the file list
metaFile = RenderDataMetaFile.createFromExistingOrNewFile(this.clientLevel, this.fullDataSourceProvider, pos, this.computeRenderFilePath(pos));
this.topDetailLevelRef.updateAndGet(newDetailLevel -> Math.max(newDetailLevel, pos.sectionDetailLevel));
this.topDetailLevelRef.updateAndGet(newDetailLevel -> Math.max(newDetailLevel, pos.getDetailLevel()));
// Compare And Swap to handle a concurrency issue where multiple threads created the same Meta File at the same time
RenderDataMetaFile metaFileCas = this.metaFileBySectionPos.putIfAbsent(pos, metaFile);
@@ -256,14 +255,14 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
DhSectionPos boundingPos = chunk.getSectionPos();
DhSectionPos minSectionPos = boundingPos.convertNewToDetailLevel(sectionDetailLevel);
DhSectionPos fileSectionPos = new DhSectionPos((byte)0, 0, 0);
DhSectionPos.DhMutableSectionPos fileSectionPos = new DhSectionPos.DhMutableSectionPos((byte)0, 0, 0);
int width = (sectionDetailLevel > boundingPos.sectionDetailLevel) ? 1 : boundingPos.getWidthCountForLowerDetailedSection(sectionDetailLevel);
int width = (sectionDetailLevel > boundingPos.getDetailLevel()) ? 1 : boundingPos.getWidthCountForLowerDetailedSection(sectionDetailLevel);
for (int xOffset = 0; xOffset < width; xOffset++)
{
for (int zOffset = 0; zOffset < width; zOffset++)
{
fileSectionPos.mutate(sectionDetailLevel, minSectionPos.sectionX + xOffset, minSectionPos.sectionZ + zOffset);
fileSectionPos.mutate(sectionDetailLevel, minSectionPos.getX() + xOffset, minSectionPos.getZ() + zOffset);
RenderDataMetaFile metaFile = this.metaFileBySectionPos.get(fileSectionPos); // bypass the getLoadOrMakeFile() since we only want cached files.
if (metaFile != null)
{
@@ -28,7 +28,6 @@ import com.seibel.distanthorizons.core.generation.tasks.*;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.pos.DhLodPos;
import com.seibel.distanthorizons.core.pos.DhSectionPos;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dataObjects.transformers.LodDataBuilder;
@@ -45,7 +44,6 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
import org.apache.logging.log4j.Logger;
import java.awt.*;
import java.io.Closeable;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.Consumer;
@@ -159,7 +157,7 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
}
// Assert that the data at least can fill in 1 single ChunkSizedFullDataAccessor
LodUtil.assertTrue(pos.sectionDetailLevel > requiredDataDetail + LodUtil.CHUNK_DETAIL_LEVEL);
LodUtil.assertTrue(pos.getDetailLevel() > requiredDataDetail + LodUtil.CHUNK_DETAIL_LEVEL);
//if (this.waitingTaskQuadTree.isSectionPosInBounds(requestPos))
@@ -393,14 +391,14 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
// split up the task and add each one to the tree
LinkedList<CompletableFuture<WorldGenResult>> childFutures = new LinkedList<>();
DhSectionPos sectionPos = new DhSectionPos(closestTask.pos.sectionDetailLevel, closestTask.pos.sectionX, closestTask.pos.sectionZ);
DhSectionPos sectionPos = new DhSectionPos(closestTask.pos.getDetailLevel(), closestTask.pos.getX(), closestTask.pos.getZ());
WorldGenTask finalClosestTask = closestTask;
sectionPos.forEachChild((childDhSectionPos) ->
{
CompletableFuture<WorldGenResult> newFuture = new CompletableFuture<>();
childFutures.add(newFuture);
WorldGenTask newGenTask = new WorldGenTask(childDhSectionPos, childDhSectionPos.sectionDetailLevel, finalClosestTask.taskTracker, newFuture);
WorldGenTask newGenTask = new WorldGenTask(childDhSectionPos, childDhSectionPos.getDetailLevel(), finalClosestTask.taskTracker, newFuture);
waitingTasks.put(newGenTask.pos, newGenTask);
//this.waitingTaskQuadTree.setValue(new DhSectionPos(childDhSectionPos.sectionDetailLevel, childDhSectionPos.sectionX, childDhSectionPos.sectionZ), newGenTask);
@@ -421,7 +419,7 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
{
byte taskDetailLevel = inProgressTaskGroup.group.dataDetail;
DhSectionPos taskPos = inProgressTaskGroup.group.pos;
byte granularity = (byte) (taskPos.sectionDetailLevel - taskDetailLevel);
byte granularity = (byte) (taskPos.getDetailLevel() - taskDetailLevel);
LodUtil.assertTrue(granularity >= this.minGranularity && granularity <= this.maxGranularity);
LodUtil.assertTrue(taskDetailLevel >= this.smallestDataDetail && taskDetailLevel <= this.largestDataDetail);
@@ -436,7 +434,7 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
//StackTraceElement[] stackTrace = this.alreadyGeneratedPosHashSet.get(inProgressTaskGroup.group.pos);
// sending a success result is necessary to make sure the render sections are reloaded correctly
inProgressTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(new DhSectionPos(granularity, taskPos.sectionX, taskPos.sectionZ))));
inProgressTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(new DhSectionPos(granularity, taskPos.getX(), taskPos.getZ()))));
return;
}
this.alreadyGeneratedPosHashSet.put(inProgressTaskGroup.group.pos, Thread.currentThread().getStackTrace());
@@ -470,7 +468,7 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
else
{
//LOGGER.info("Section generation at "+pos+" completed");
inProgressTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(new DhSectionPos(granularity, taskPos.sectionX, taskPos.sectionZ))));
inProgressTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(new DhSectionPos(granularity, taskPos.getX(), taskPos.getZ()))));
}
boolean worked = this.inProgressGenTasksByLodPos.remove(taskPos, inProgressTaskGroup);
LodUtil.assertTrue(worked);
@@ -686,7 +684,7 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
private boolean canGeneratePos(byte worldGenTaskGroupDetailLevel /*when in doubt use 0*/ , DhSectionPos taskPos)
{
byte granularity = (byte) (taskPos.sectionDetailLevel - worldGenTaskGroupDetailLevel);
byte granularity = (byte) (taskPos.getDetailLevel() - worldGenTaskGroupDetailLevel);
return (granularity >= this.minGranularity && granularity <= this.maxGranularity);
}
@@ -59,7 +59,7 @@ public class DhServerLevel extends DhLevel implements IDhServerLevel
public void saveWrites(ChunkSizedFullDataAccessor data)
{
DhSectionPos pos = data.getSectionPos();
pos.convertSelfToDetailLevel(CompleteFullDataSource.SECTION_SIZE_OFFSET);
pos = pos.convertNewToDetailLevel(CompleteFullDataSource.SECTION_SIZE_OFFSET);
this.getFileHandler().writeChunkDataToFile(pos, data);
}
@@ -47,7 +47,7 @@ public class DhLodPos implements Comparable<DhLodPos>
this.x = x;
this.z = z;
}
public DhLodPos(DhSectionPos sectionPos) { this(sectionPos.sectionDetailLevel, sectionPos.sectionX, sectionPos.sectionZ); }
public DhLodPos(DhSectionPos sectionPos) { this(sectionPos.getDetailLevel(), sectionPos.getX(), sectionPos.getZ()); }
@@ -41,7 +41,6 @@ import java.util.function.Consumer;
* With those thoughts in mind we decided on a smallest section size of 32 data points square (IE 2x2 chunks).
*
* @author Leetom
* @version 2022-11-6
*/
public class DhSectionPos
{
@@ -56,12 +55,12 @@ public class DhSectionPos
public final static byte SECTION_REGION_DETAIL_LEVEL = SECTION_MINIMUM_DETAIL_LEVEL + LodUtil.REGION_DETAIL_LEVEL;
public byte sectionDetailLevel;
protected byte detailLevel;
/** in a sectionDetailLevel grid */
public int sectionX;
protected int x;
/** in a sectionDetailLevel grid */
public int sectionZ;
protected int z;
@@ -69,11 +68,11 @@ public class DhSectionPos
// constructors //
//==============//
public DhSectionPos(byte sectionDetailLevel, int sectionX, int sectionZ)
public DhSectionPos(byte detailLevel, int x, int z)
{
this.sectionDetailLevel = sectionDetailLevel;
this.sectionX = sectionX;
this.sectionZ = sectionZ;
this.detailLevel = detailLevel;
this.x = x;
this.z = z;
}
public DhSectionPos(DhBlockPos blockPos)
@@ -95,9 +94,9 @@ public class DhSectionPos
public DhSectionPos(byte detailLevel, DhLodPos dhLodPos)
{
this.sectionDetailLevel = detailLevel;
this.sectionX = dhLodPos.x;
this.sectionZ = dhLodPos.z;
this.detailLevel = detailLevel;
this.x = dhLodPos.x;
this.z = dhLodPos.z;
}
@@ -106,36 +105,6 @@ public class DhSectionPos
// converters //
//============//
/**
* Overwrites this section pos with the given input. <br>
* Can be useful to prevent duplicate allocations in high traffic loops but should
* be used sparingly as it could accidentally cause bugs due to unexpected modifications.
*/
public void mutate(byte sectionDetailLevel, int sectionX, int sectionZ)
{
this.sectionDetailLevel = sectionDetailLevel;
this.sectionX = sectionX;
this.sectionZ = sectionZ;
}
/** uses the absolute detail level aka detail levels like {@link LodUtil#CHUNK_DETAIL_LEVEL} instead of the dhSectionPos detailLevels. */
public void convertSelfToDetailLevel(byte newDetailLevel)
{
// logic originally taken from DhLodPos
if (newDetailLevel >= this.sectionDetailLevel)
{
this.sectionX = Math.floorDiv(this.sectionX, BitShiftUtil.powerOfTwo(newDetailLevel - this.sectionDetailLevel));
this.sectionZ = Math.floorDiv(this.sectionZ, BitShiftUtil.powerOfTwo(newDetailLevel - this.sectionDetailLevel));
}
else
{
this.sectionX = this.sectionX * BitShiftUtil.powerOfTwo(this.sectionDetailLevel - newDetailLevel);
this.sectionZ = this.sectionZ * BitShiftUtil.powerOfTwo(this.sectionDetailLevel - newDetailLevel);
}
this.sectionDetailLevel = newDetailLevel;
}
/**
* uses the absolute detail level aka detail levels like {@link LodUtil#CHUNK_DETAIL_LEVEL} instead of the dhSectionPos detailLevels.
*
@@ -143,12 +112,41 @@ public class DhSectionPos
*/
public DhSectionPos convertNewToDetailLevel(byte newSectionDetailLevel)
{
DhSectionPos newPos = new DhSectionPos(this.sectionDetailLevel, this.sectionX, this.sectionZ);
DhSectionPos newPos = new DhSectionPos(this.detailLevel, this.x, this.z);
newPos.convertSelfToDetailLevel(newSectionDetailLevel);
return newPos;
}
/** uses the absolute detail level aka detail levels like {@link LodUtil#CHUNK_DETAIL_LEVEL} instead of the dhSectionPos detailLevels. */
protected void convertSelfToDetailLevel(byte newDetailLevel)
{
// logic originally taken from DhLodPos
if (newDetailLevel >= this.detailLevel)
{
this.x = Math.floorDiv(this.x, BitShiftUtil.powerOfTwo(newDetailLevel - this.detailLevel));
this.z = Math.floorDiv(this.z, BitShiftUtil.powerOfTwo(newDetailLevel - this.detailLevel));
}
else
{
this.x = this.x * BitShiftUtil.powerOfTwo(this.detailLevel - newDetailLevel);
this.z = this.z * BitShiftUtil.powerOfTwo(this.detailLevel - newDetailLevel);
}
this.detailLevel = newDetailLevel;
}
//==================//
// property getters //
//==================//
public byte getDetailLevel() { return this.detailLevel; }
public int getX() { return this.x; }
public int getZ() { return this.z; }
//=========//
@@ -156,16 +154,16 @@ public class DhSectionPos
//=========//
/** @return the corner with the smallest X and Z coordinate */
public DhLodPos getMinCornerLodPos() { return this.getMinCornerLodPos((byte) (this.sectionDetailLevel - 1)); }
public DhLodPos getMinCornerLodPos() { return this.getMinCornerLodPos((byte) (this.detailLevel - 1)); }
/** @return the corner with the smallest X and Z coordinate */
public DhLodPos getMinCornerLodPos(byte returnDetailLevel)
{
LodUtil.assertTrue(returnDetailLevel <= this.sectionDetailLevel, "returnDetailLevel must be less than sectionDetail");
LodUtil.assertTrue(returnDetailLevel <= this.detailLevel, "returnDetailLevel must be less than sectionDetail");
byte offset = (byte) (this.sectionDetailLevel - returnDetailLevel);
byte offset = (byte) (this.detailLevel - returnDetailLevel);
return new DhLodPos(returnDetailLevel,
this.sectionX * BitShiftUtil.powerOfTwo(offset),
this.sectionZ * BitShiftUtil.powerOfTwo(offset));
this.x * BitShiftUtil.powerOfTwo(offset),
this.z * BitShiftUtil.powerOfTwo(offset));
}
/**
@@ -180,13 +178,13 @@ public class DhSectionPos
*/
public int getWidthCountForLowerDetailedSection(byte returnDetailLevel)
{
LodUtil.assertTrue(returnDetailLevel <= this.sectionDetailLevel, "returnDetailLevel must be less than sectionDetail");
byte offset = (byte) (this.sectionDetailLevel - returnDetailLevel);
LodUtil.assertTrue(returnDetailLevel <= this.detailLevel, "returnDetailLevel must be less than sectionDetail");
byte offset = (byte) (this.detailLevel - returnDetailLevel);
return BitShiftUtil.powerOfTwo(offset);
}
/** @return how wide this section is in blocks */
public int getBlockWidth() { return BitShiftUtil.powerOfTwo(this.sectionDetailLevel); }
public int getBlockWidth() { return BitShiftUtil.powerOfTwo(this.detailLevel); }
public DhBlockPos2D getCenterBlockPos() { return new DhBlockPos2D(this.getCenterBlockPosX(), this.getCenterBlockPosZ()); }
@@ -195,9 +193,9 @@ public class DhSectionPos
public int getCenterBlockPosZ() { return this.getCenterBlockPos(false); }
private int getCenterBlockPos(boolean returnX)
{
int centerBlockPos = returnX ? this.sectionX : this.sectionZ;
int centerBlockPos = returnX ? this.x : this.z;
if (this.sectionDetailLevel == 0)
if (this.detailLevel == 0)
{
// already at block detail level, no conversion necessary
return centerBlockPos;
@@ -205,12 +203,12 @@ public class DhSectionPos
// we can't get the center of the position at block level, only attempt to get the position offset for detail levels above 0
int positionOffset = 0;
if (this.sectionDetailLevel != 1)
if (this.detailLevel != 1)
{
positionOffset = BitShiftUtil.powerOfTwo(this.sectionDetailLevel - 1);
positionOffset = BitShiftUtil.powerOfTwo(this.detailLevel - 1);
}
return (centerBlockPos * BitShiftUtil.powerOfTwo(this.sectionDetailLevel)) + positionOffset;
return (centerBlockPos * BitShiftUtil.powerOfTwo(this.detailLevel)) + positionOffset;
}
@@ -236,31 +234,31 @@ public class DhSectionPos
{
throw new IllegalArgumentException("child0to3 must be between 0 and 3");
}
if (this.sectionDetailLevel <= 0)
if (this.detailLevel <= 0)
{
throw new IllegalStateException("section detail must be greater than 0");
}
return new DhSectionPos((byte) (this.sectionDetailLevel - 1),
this.sectionX * 2 + (child0to3 & 1),
this.sectionZ * 2 + BitShiftUtil.half(child0to3 & 2));
return new DhSectionPos((byte) (this.detailLevel - 1),
this.x * 2 + (child0to3 & 1),
this.z * 2 + BitShiftUtil.half(child0to3 & 2));
}
/** Returns this position's child index in its parent */
public int getChildIndexOfParent() { return (this.sectionX & 1) + BitShiftUtil.square(this.sectionZ & 1); }
public int getChildIndexOfParent() { return (this.x & 1) + BitShiftUtil.square(this.z & 1); }
public DhSectionPos getParentPos() { return new DhSectionPos((byte) (this.sectionDetailLevel + 1), BitShiftUtil.half(this.sectionX), BitShiftUtil.half(this.sectionZ)); }
public DhSectionPos getParentPos() { return new DhSectionPos((byte) (this.detailLevel + 1), BitShiftUtil.half(this.x), BitShiftUtil.half(this.z)); }
public DhSectionPos getAdjacentPos(EDhDirection dir)
{
return new DhSectionPos(this.sectionDetailLevel,
this.sectionX + dir.getNormal().x,
this.sectionZ + dir.getNormal().z);
return new DhSectionPos(this.detailLevel,
this.x + dir.getNormal().x,
this.z + dir.getNormal().z);
}
public DhLodPos getSectionBBoxPos() { return new DhLodPos(this.sectionDetailLevel, this.sectionX, this.sectionZ); }
public DhLodPos getSectionBBoxPos() { return new DhLodPos(this.detailLevel, this.x, this.z); }
@@ -275,17 +273,17 @@ public class DhSectionPos
{
return true;
}
else if (this.sectionDetailLevel == other.sectionDetailLevel)
else if (this.detailLevel == other.detailLevel)
{
return false;
}
else if (this.sectionDetailLevel > other.sectionDetailLevel)
else if (this.detailLevel > other.detailLevel)
{
return this.equals(other.convertNewToDetailLevel(this.sectionDetailLevel));
return this.equals(other.convertNewToDetailLevel(this.detailLevel));
}
else
{
return other.equals(this.convertNewToDetailLevel(other.sectionDetailLevel));
return other.equals(this.convertNewToDetailLevel(other.detailLevel));
}
}
@@ -319,7 +317,7 @@ public class DhSectionPos
/** Applies the given consumer to all children of the position at the given section detail level. */
public void forEachChildAtLevel(byte sectionDetailLevel, Consumer<DhSectionPos> callback)
{
if (sectionDetailLevel == this.sectionDetailLevel)
if (sectionDetailLevel == this.detailLevel)
{
callback.accept(this);
return;
@@ -338,7 +336,7 @@ public class DhSectionPos
//===============//
/** Serialize() is different from toString() as it must NEVER be changed, and should be in a short format */
public String serialize() { return "[" + this.sectionDetailLevel + ',' + this.sectionX + ',' + this.sectionZ + ']'; }
public String serialize() { return "[" + this.detailLevel + ',' + this.x + ',' + this.z + ']'; }
@Nullable
public static DhSectionPos deserialize(String value)
@@ -357,7 +355,7 @@ public class DhSectionPos
//===========//
@Override
public String toString() { return "{" + this.sectionDetailLevel + "*" + this.sectionX + "," + this.sectionZ + "}"; }
public String toString() { return "{" + this.detailLevel + "*" + this.x + "," + this.z + "}"; }
@Override
public boolean equals(Object obj)
@@ -372,17 +370,77 @@ public class DhSectionPos
}
DhSectionPos that = (DhSectionPos) obj;
return this.sectionDetailLevel == that.sectionDetailLevel &&
this.sectionX == that.sectionX &&
this.sectionZ == that.sectionZ;
return this.detailLevel == that.detailLevel &&
this.x == that.x &&
this.z == that.z;
}
@Override
public int hashCode()
{
return Integer.hashCode(this.sectionDetailLevel) ^ // XOR
Integer.hashCode(this.sectionX) ^ // XOR
Integer.hashCode(this.sectionZ);
return Integer.hashCode(this.detailLevel) ^ // XOR
Integer.hashCode(this.x) ^ // XOR
Integer.hashCode(this.z);
}
//=============//
// sub classes //
//=============//
/**
* Identical to {@link DhSectionPos} except it is mutable.
* See {@link DhSectionPos} for full documentation.
*
* @see DhSectionPos
*/
public static class DhMutableSectionPos extends DhSectionPos
{
//==============//
// constructors //
//==============//
public DhMutableSectionPos(byte sectionDetailLevel, int sectionX, int sectionZ) { super(sectionDetailLevel, sectionX, sectionZ); }
public DhMutableSectionPos(DhBlockPos blockPos) { super(blockPos); }
public DhMutableSectionPos(DhBlockPos2D blockPos) { super(blockPos); }
public DhMutableSectionPos(DhChunkPos chunkPos) { super(chunkPos); }
public DhMutableSectionPos(byte detailLevel, DhLodPos dhLodPos) { super(detailLevel, dhLodPos); }
//============//
// converters //
//============//
/**
* Overwrites this section pos with the given input. <br>
* Can be useful to prevent duplicate allocations in high traffic loops but should
* be used sparingly as it could accidentally cause bugs due to unexpected modifications.
*/
public void mutate(byte sectionDetailLevel, int sectionX, int sectionZ)
{
this.detailLevel = sectionDetailLevel;
this.x = sectionX;
this.z = sectionZ;
}
@Override
public void convertSelfToDetailLevel(byte newDetailLevel) { super.convertSelfToDetailLevel(newDetailLevel); }
//==================//
// property getters //
//==================//
public void setDetailLevel(byte sectionDetailLevel) { this.detailLevel = sectionDetailLevel; }
public void setX(int sectionX) { this.x = sectionX; }
public void setZ(int sectionZ) { this.z = sectionZ; }
}
}
@@ -143,7 +143,7 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements AutoClose
{
// walk up the tree until we hit the root node
// this is done so any high detail changes flow up to the lower detail render sections as well
while (pos.sectionDetailLevel <= this.treeMinDetailLevel)
while (pos.getDetailLevel() <= this.treeMinDetailLevel)
{
try
{
@@ -223,7 +223,7 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements AutoClose
expectedDetailLevel += DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL;
if (sectionPos.sectionDetailLevel > expectedDetailLevel)
if (sectionPos.getDetailLevel() > expectedDetailLevel)
{
// section detail level too high //
boolean canThisPosRender = renderSection.isRenderingEnabled();
@@ -273,7 +273,7 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements AutoClose
}
}
// TODO this should only equal the expected detail level, the (expectedDetailLevel-1) is a temporary fix to prevent corners from being cut out
else if (sectionPos.sectionDetailLevel == expectedDetailLevel || sectionPos.sectionDetailLevel == expectedDetailLevel - 1)
else if (sectionPos.getDetailLevel() == expectedDetailLevel || sectionPos.getDetailLevel() == expectedDetailLevel - 1)
{
// this is the detail level we want to render //
// prepare this section for rendering
@@ -160,7 +160,7 @@ public class LodRenderSection implements IDebugRenderable
public void reload(ILodRenderSourceProvider renderDataProvider)
{
// debug rendering
if (this.pos.sectionDetailLevel == DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL)
if (this.pos.getDetailLevel() == DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL)
{
DebugRenderer.makeParticle(
new DebugRenderer.BoxParticle(
@@ -324,7 +324,7 @@ public class LodRenderSection implements IDebugRenderable
if (this.canBuildBuffer())
{
// debug
if (this.pos.sectionDetailLevel == DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL)
if (this.pos.getDetailLevel() == DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL)
{
DebugRenderer.makeParticle(
new DebugRenderer.BoxParticle(
@@ -161,7 +161,7 @@ public class RenderBufferHandler
return abPosDifference;
}
return loadedBufferA.pos.sectionDetailLevel - loadedBufferB.pos.sectionDetailLevel; // If all else fails, sort by detail
return loadedBufferA.pos.getDetailLevel() - loadedBufferB.pos.getDetailLevel(); // If all else fails, sort by detail
};
// Build the sorted list
@@ -183,17 +183,17 @@ public class QuadNode<T>
throw new IllegalArgumentException("Input section pos " + inputSectionPos + " outside of this quadNode's pos: " + this.sectionPos + ", this node's blockPos: " + this.sectionPos.convertNewToDetailLevel(LodUtil.BLOCK_DETAIL_LEVEL) + " block width: " + this.sectionPos.getBlockWidth() + " input detail level: " + inputSectionPos.convertNewToDetailLevel(LodUtil.BLOCK_DETAIL_LEVEL) + " width: " + inputSectionPos.getBlockWidth());
}
if (inputSectionPos.sectionDetailLevel > this.sectionPos.sectionDetailLevel)
if (inputSectionPos.getDetailLevel() > this.sectionPos.getDetailLevel())
{
throw new IllegalArgumentException("detail level higher than this node. Node Detail level: " + this.sectionPos.sectionDetailLevel + " input detail level: " + inputSectionPos.sectionDetailLevel);
throw new IllegalArgumentException("detail level higher than this node. Node Detail level: " + this.sectionPos.getDetailLevel() + " input detail level: " + inputSectionPos.getDetailLevel());
}
if (inputSectionPos.sectionDetailLevel == this.sectionPos.sectionDetailLevel && !inputSectionPos.equals(this.sectionPos))
if (inputSectionPos.getDetailLevel() == this.sectionPos.getDetailLevel() && !inputSectionPos.equals(this.sectionPos))
{
throw new IllegalArgumentException("Node and input detail level are equal, however positions are not; this tree doesn't contain the requested position. Node pos: " + this.sectionPos + ", input pos: " + inputSectionPos);
}
if (inputSectionPos.sectionDetailLevel < this.minimumDetailLevel)
if (inputSectionPos.getDetailLevel() < this.minimumDetailLevel)
{
throw new IllegalArgumentException("Input position is requesting a detail level lower than what this node can provide. Node minimum detail level: " + this.minimumDetailLevel + ", input pos: " + inputSectionPos);
}
@@ -201,7 +201,7 @@ public class QuadNode<T>
// get/set logic
if (inputSectionPos.sectionDetailLevel == this.sectionPos.sectionDetailLevel)
if (inputSectionPos.getDetailLevel() == this.sectionPos.getDetailLevel())
{
// this node is the requested position
if (replaceValue)
@@ -130,8 +130,8 @@ public class QuadTree<T>
DhSectionPos rootPos = pos.convertNewToDetailLevel(this.treeMinDetailLevel);
int ringListPosX = rootPos.sectionX;
int ringListPosZ = rootPos.sectionZ;
int ringListPosX = rootPos.getX();
int ringListPosZ = rootPos.getZ();
QuadNode<T> topQuadNode = this.topRingList.get(ringListPosX, ringListPosZ);
if (topQuadNode == null)
@@ -163,7 +163,7 @@ public class QuadTree<T>
public boolean isSectionPosInBounds(DhSectionPos testPos)
{
// check if the testPos is within the detail level limits of the tree
boolean detailLevelWithinBounds = this.treeMaxDetailLevel <= testPos.sectionDetailLevel && testPos.sectionDetailLevel <= this.treeMinDetailLevel;
boolean detailLevelWithinBounds = this.treeMaxDetailLevel <= testPos.getDetailLevel() && testPos.getDetailLevel() <= this.treeMinDetailLevel;
if (!detailLevelWithinBounds)
{
return false;
@@ -175,8 +175,8 @@ public class QuadTree<T>
DhLodPos treeCornerPos = new DhLodPos((byte) 0, treeBlockCorner.x, treeBlockCorner.z);
DhSectionPos inputSectionCorner = testPos.convertNewToDetailLevel((byte) 0);
DhLodPos inputCornerPos = new DhLodPos((byte) 0, inputSectionCorner.sectionX, inputSectionCorner.sectionZ);
int inputBlockWidth = BitShiftUtil.powerOfTwo(testPos.sectionDetailLevel);
DhLodPos inputCornerPos = new DhLodPos((byte) 0, inputSectionCorner.getX(), inputSectionCorner.getZ());
int inputBlockWidth = BitShiftUtil.powerOfTwo(testPos.getDetailLevel());
return DoSquaresOverlap(treeCornerPos, this.widthInBlocks, inputCornerPos, inputBlockWidth);
}
@@ -36,7 +36,7 @@ public class QuadNodeChildIndexIterator<T> implements Iterator<Integer>
public QuadNodeChildIndexIterator(QuadNode<T> parentNode, boolean returnNullChildPos)
{
// only get the children if this section isn't at the bottom of the tree
if (parentNode.sectionPos.sectionDetailLevel > parentNode.minimumDetailLevel)
if (parentNode.sectionPos.getDetailLevel() > parentNode.minimumDetailLevel)
{
// go over each child pos
for (int i = 0; i < 4; i++)
@@ -46,7 +46,7 @@ public class QuadTreeNodeIterator<T> implements Iterator<QuadNode<T>>
this.onlyReturnLeafValues = onlyReturnLeafValues;
// TODO the naming conversion for these are flipped in a lot of places
this.highestDetailLevel = rootNode.minimumDetailLevel;
this.iteratorDetailLevel = rootNode.sectionPos.sectionDetailLevel;
this.iteratorDetailLevel = rootNode.sectionPos.getDetailLevel();
if (!this.onlyReturnLeafValues)
+5 -5
View File
@@ -649,7 +649,7 @@ public class QuadTreeTest
DhSectionPos sectionPos = directChildIterator.next();
QuadNode<Integer> childNode = node.getNode(sectionPos);
Assert.assertTrue("Child node recurred too low. Min detail level: " + minDetailLevel + ", node detail level: " + childNode.sectionPos.sectionDetailLevel, childNode.sectionPos.sectionDetailLevel >= minDetailLevel);
Assert.assertTrue("Child node recurred too low. Min detail level: " + minDetailLevel + ", node detail level: " + childNode.sectionPos.getDetailLevel(), childNode.sectionPos.getDetailLevel() >= minDetailLevel);
recursivelyCreateNodeChildren(childNode, minDetailLevel, minimumDetailLevelReachedRef);
childNodesIterated = true;
@@ -657,9 +657,9 @@ public class QuadTreeTest
// keep track of how far down the tree we have gone
if (node.sectionPos.sectionDetailLevel < minimumDetailLevelReachedRef.get())
if (node.sectionPos.getDetailLevel() < minimumDetailLevelReachedRef.get())
{
minimumDetailLevelReachedRef.set(node.sectionPos.sectionDetailLevel);
minimumDetailLevelReachedRef.set(node.sectionPos.getDetailLevel());
}
@@ -667,11 +667,11 @@ public class QuadTreeTest
// assertions
if (childNodesCreated)
{
Assert.assertTrue("node children created below minimum detail level", node.sectionPos.sectionDetailLevel >= minDetailLevel);
Assert.assertTrue("node children created below minimum detail level", node.sectionPos.getDetailLevel() >= minDetailLevel);
}
if (childNodesIterated)
{
Assert.assertTrue("node children iterated below minimum detail level", node.sectionPos.sectionDetailLevel - 1 >= minDetailLevel);
Assert.assertTrue("node children iterated below minimum detail level", node.sectionPos.getDetailLevel() - 1 >= minDetailLevel);
}
}