diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EGlProfileMode.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EGlProfileMode.java
new file mode 100644
index 000000000..acf2f8181
--- /dev/null
+++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EGlProfileMode.java
@@ -0,0 +1,30 @@
+/*
+ * This file is part of the Distant Horizons mod
+ * licensed under the GNU LGPL v3 License.
+ *
+ * Copyright (C) 2020-2023 James Seibel
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.seibel.distanthorizons.api.enums.config;
+
+/**
+ * @since API 1.0.0
+ */
+public enum EGlProfileMode
+{
+ CORE,
+ COMPAT,
+ ANY;
+}
diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/BitShiftUtil.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/BitShiftUtil.java
index 9ad2e34f8..8bd3b2512 100644
--- a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/BitShiftUtil.java
+++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/BitShiftUtil.java
@@ -30,7 +30,7 @@ public class BitShiftUtil
{
/**
* Equivalent to:
- * {@literal 1 << value0, }
+ * {@literal 1 << value, }
* 2^value,
* Math.pow(2, value)
*
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java b/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java
index 87d6db72f..6aad47dc6 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java
@@ -19,6 +19,7 @@
package com.seibel.distanthorizons.core;
+import com.seibel.distanthorizons.core.file.DataSourceReferenceTracker;
import com.seibel.distanthorizons.coreapi.ModInfo;
import com.seibel.distanthorizons.core.world.DhApiWorldProxy;
import com.seibel.distanthorizons.core.api.external.methods.config.DhApiConfig;
@@ -67,6 +68,8 @@ public class Initializer
DhApi.Delayed.worldProxy = DhApiWorldProxy.INSTANCE;
DhApi.Delayed.renderProxy = DhApiRenderProxy.INSTANCE;
+ DataSourceReferenceTracker.startGarbageCollectorBackgroundThread();
+
}
}
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java
index 62d552d73..3d1821bc1 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java
@@ -1176,21 +1176,35 @@ public class Config
+ "")
.build();
+ // TODO temporary test, remove me
public static ConfigEntry skipChunkLoadUpdates = new ConfigEntry.Builder()
.set(false)
.comment("")
.build();
+ // TODO temporary test, remove me
public static ConfigEntry skipChunkUnloadUpdates = new ConfigEntry.Builder()
.set(false)
.comment("")
.build();
+ // TODO temporary test, remove me
public static ConfigEntry skipFullDataUpdateQueue = new ConfigEntry.Builder()
.set(false)
.comment("")
.build();
+ // TODO temporary test, remove me
+ public static ConfigEntry glProfileMode = new ConfigEntry.Builder()
+ .set(EGlProfileMode.CORE)
+ .comment("")
+ .build();
+ // TODO temporary test, remove me
+ public static ConfigEntry glForwardCompatibilityMode = new ConfigEntry.Builder()
+ .set(true)
+ .comment("")
+ .build();
+
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/FullDataDownSampler.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/FullDataDownSampler.java
index 513f2594c..3b333bf4a 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/FullDataDownSampler.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/FullDataDownSampler.java
@@ -47,15 +47,17 @@ public class FullDataDownSampler
ArrayList> futures;
DhLodPos basePos = target.getSectionPos().getSectionBBoxPos().getCornerLodPos(CompleteFullDataSource.SECTION_SIZE_OFFSET);
+
+
if (sectionSizeNeeded <= CompleteFullDataSource.SECTION_SIZE_OFFSET)
{
futures = new ArrayList<>(sectionSizeNeeded * sectionSizeNeeded);
- for (int ox = 0; ox < sectionSizeNeeded; ox++)
+ for (int xOffset = 0; xOffset < sectionSizeNeeded; xOffset++)
{
- for (int oz = 0; oz < sectionSizeNeeded; oz++)
+ for (int zOffset = 0; zOffset < sectionSizeNeeded; zOffset++)
{
CompletableFuture future = provider.readAsync(new DhSectionPos(
- CompleteFullDataSource.SECTION_SIZE_OFFSET, basePos.x + ox, basePos.z + oz));
+ CompleteFullDataSource.SECTION_SIZE_OFFSET, basePos.x + xOffset, basePos.z + zOffset));
future = future.whenComplete((source, ex) -> {
if (ex == null && source != null && source instanceof CompleteFullDataSource)
{
@@ -74,12 +76,12 @@ public class FullDataDownSampler
{
futures = new ArrayList<>(CompleteFullDataSource.WIDTH * CompleteFullDataSource.WIDTH);
int multiplier = sectionSizeNeeded / CompleteFullDataSource.WIDTH;
- for (int ox = 0; ox < CompleteFullDataSource.WIDTH; ox++)
+ for (int xOffset = 0; xOffset < CompleteFullDataSource.WIDTH; xOffset++)
{
- for (int oz = 0; oz < CompleteFullDataSource.WIDTH; oz++)
+ for (int zOffset = 0; zOffset < CompleteFullDataSource.WIDTH; zOffset++)
{
CompletableFuture future = provider.readAsync(new DhSectionPos(
- CompleteFullDataSource.SECTION_SIZE_OFFSET, basePos.x + ox * multiplier, basePos.z + oz * multiplier));
+ CompleteFullDataSource.SECTION_SIZE_OFFSET, basePos.x + xOffset * multiplier, basePos.z + zOffset * multiplier));
future = future.whenComplete((source, ex) -> {
if (ex == null && source != null && source instanceof CompleteFullDataSource)
{
@@ -99,7 +101,7 @@ public class FullDataDownSampler
public static void downSample(CompleteFullDataSource target, CompleteFullDataSource source)
{
- LodUtil.assertTrue(target.getSectionPos().overlaps(source.getSectionPos()));
+ LodUtil.assertTrue(target.getSectionPos().overlapsExactly(source.getSectionPos()));
LodUtil.assertTrue(target.getDataDetailLevel() > source.getDataDetailLevel());
byte detailDiff = (byte) (target.getDataDetailLevel() - source.getDataDetailLevel());
@@ -111,11 +113,11 @@ 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;
}
- DhLodPos trgOffset = trgPos.getCorner(target.getDataDetailLevel());
+ DhLodPos trgOffset = trgPos.getMinCornerLodPos(target.getDataDetailLevel());
DhLodPos srcOffset = srcPos.getSectionBBoxPos().convertToDetailLevel(target.getDataDetailLevel());
int offsetX = trgOffset.x - srcOffset.x;
int offsetZ = trgOffset.z - srcOffset.z;
@@ -131,7 +133,7 @@ public class FullDataDownSampler
int srcDataPerTrgData = 1 << detailDiff;
int overlappedTrgDataSize = CompleteFullDataSource.WIDTH / srcDataPerTrgData;
- DhLodPos trgOffset = trgPos.getCorner(target.getDataDetailLevel());
+ DhLodPos trgOffset = trgPos.getMinCornerLodPos(target.getDataDetailLevel());
DhLodPos srcOffset = srcPos.getSectionBBoxPos().getCornerLodPos(target.getDataDetailLevel());
int offsetX = trgOffset.x - srcOffset.x;
int offsetZ = trgOffset.z - srcOffset.z;
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/accessor/ChunkSizedFullDataAccessor.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/accessor/ChunkSizedFullDataAccessor.java
index 4c1135e44..881e1e5a5 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/accessor/ChunkSizedFullDataAccessor.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/accessor/ChunkSizedFullDataAccessor.java
@@ -21,11 +21,9 @@ package com.seibel.distanthorizons.core.dataObjects.fullData.accessor;
import com.seibel.distanthorizons.core.dataObjects.fullData.FullDataPointIdMap;
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.interfaces.IFullDataSource;
-import com.seibel.distanthorizons.core.dataObjects.fullData.sources.interfaces.IStreamableFullDataSource;
import com.seibel.distanthorizons.core.level.IDhLevel;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
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.util.FullDataPointUtil;
import com.seibel.distanthorizons.core.util.LodUtil;
@@ -46,19 +44,22 @@ public class ChunkSizedFullDataAccessor extends FullDataArrayAccessor
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
- public final DhChunkPos pos;
+ public final DhChunkPos chunkPos;
+ public final DhSectionPos sectionPos;
+
// TODO replace this var with LodUtil.BLOCK_DETAIL_LEVEL
public final byte detailLevel = LodUtil.BLOCK_DETAIL_LEVEL;
- public ChunkSizedFullDataAccessor(DhChunkPos pos)
+ public ChunkSizedFullDataAccessor(DhChunkPos chunkPos)
{
- super(new FullDataPointIdMap(new DhSectionPos(pos)),
+ super(new FullDataPointIdMap(new DhSectionPos(chunkPos)),
new long[LodUtil.CHUNK_WIDTH * LodUtil.CHUNK_WIDTH][0],
LodUtil.CHUNK_WIDTH);
- this.pos = pos;
+ this.chunkPos = chunkPos;
+ this.sectionPos = new DhSectionPos(LodUtil.CHUNK_DETAIL_LEVEL, this.chunkPos.x, this.chunkPos.z);
}
@@ -237,9 +238,9 @@ public class ChunkSizedFullDataAccessor extends FullDataArrayAccessor
public long emptyCount() { return (LodUtil.CHUNK_WIDTH * LodUtil.CHUNK_WIDTH) - this.nonEmptyCount(); }
- public DhLodPos getLodPos() { return new DhLodPos(LodUtil.CHUNK_DETAIL_LEVEL, this.pos.x, this.pos.z); }
+ public DhSectionPos getSectionPos() { return this.sectionPos; }
@Override
- public String toString() { return this.pos + " " + this.nonEmptyCount(); }
+ public String toString() { return this.chunkPos + " " + this.nonEmptyCount(); }
}
\ No newline at end of file
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/CompleteFullDataSource.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/CompleteFullDataSource.java
index 4e151fe15..fad706b66 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/CompleteFullDataSource.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/CompleteFullDataSource.java
@@ -280,11 +280,11 @@ public class CompleteFullDataSource extends FullDataArrayAccessor implements IFu
@Override
public void update(ChunkSizedFullDataAccessor chunkDataView)
{
- LodUtil.assertTrue(this.sectionPos.getSectionBBoxPos().overlapsExactly(chunkDataView.getLodPos()));
+ LodUtil.assertTrue(this.sectionPos.overlapsExactly(chunkDataView.getSectionPos()));
if (this.getDataDetailLevel() == LodUtil.BLOCK_DETAIL_LEVEL)
{
- DhBlockPos2D chunkBlockPos = new DhBlockPos2D(chunkDataView.pos.x * LodUtil.CHUNK_WIDTH, chunkDataView.pos.z * LodUtil.CHUNK_WIDTH);
- DhBlockPos2D blockOffset = chunkBlockPos.subtract(this.sectionPos.getCorner().getCornerBlockPos());
+ DhBlockPos2D chunkBlockPos = new DhBlockPos2D(chunkDataView.chunkPos.x * LodUtil.CHUNK_WIDTH, chunkDataView.chunkPos.z * LodUtil.CHUNK_WIDTH);
+ DhBlockPos2D blockOffset = chunkBlockPos.subtract(this.sectionPos.getMinCornerLodPos().getCornerBlockPos());
LodUtil.assertTrue(blockOffset.x >= 0 && blockOffset.x < WIDTH && blockOffset.z >= 0 && blockOffset.z < WIDTH);
this.isEmpty = false;
@@ -306,8 +306,8 @@ public class CompleteFullDataSource extends FullDataArrayAccessor implements IFu
{
int dataPerFull = 1 << this.getDataDetailLevel();
int fullSize = LodUtil.CHUNK_WIDTH / dataPerFull;
- DhLodPos dataOffset = chunkDataView.getLodPos().getCornerLodPos(this.getDataDetailLevel());
- DhLodPos baseOffset = this.sectionPos.getCorner(this.getDataDetailLevel());
+ DhLodPos dataOffset = chunkDataView.getSectionPos().getMinCornerLodPos(this.getDataDetailLevel());
+ DhLodPos baseOffset = this.sectionPos.getMinCornerLodPos(this.getDataDetailLevel());
int offsetX = dataOffset.x - baseOffset.x;
int offsetZ = dataOffset.z - baseOffset.z;
@@ -327,16 +327,16 @@ public class CompleteFullDataSource extends FullDataArrayAccessor implements IFu
{
//FIXME: TEMPORARY
int chunkPerFull = 1 << (this.getDataDetailLevel() - LodUtil.CHUNK_DETAIL_LEVEL);
- if (chunkDataView.pos.x % chunkPerFull != 0 || chunkDataView.pos.z % chunkPerFull != 0)
+ if (chunkDataView.chunkPos.x % chunkPerFull != 0 || chunkDataView.chunkPos.z % chunkPerFull != 0)
{
return;
}
- DhLodPos baseOffset = this.sectionPos.getCorner(this.getDataDetailLevel());
- DhLodPos dataOffset = chunkDataView.getLodPos().convertToDetailLevel(this.getDataDetailLevel());
+ DhLodPos baseOffset = this.sectionPos.getMinCornerLodPos(this.getDataDetailLevel());
+ DhSectionPos dataOffset = chunkDataView.getSectionPos().convertNewToDetailLevel(this.getDataDetailLevel());
- int offsetX = dataOffset.x - baseOffset.x;
- int offsetZ = dataOffset.z - 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;
@@ -359,18 +359,18 @@ public class CompleteFullDataSource extends FullDataArrayAccessor implements IFu
/** Returns whether data at the given posToWrite can effect the target region file at posToTest. */
public static boolean firstDataPosCanAffectSecond(DhSectionPos posToWrite, DhSectionPos posToTest)
{
- if (!posToWrite.overlaps(posToTest))
+ if (!posToWrite.overlapsExactly(posToTest))
{
// 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
@@ -383,9 +383,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;
}
}
@@ -419,7 +419,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 long getTypeId() { return TYPE_ID; }
@@ -445,17 +445,17 @@ public class CompleteFullDataSource extends FullDataArrayAccessor implements IFu
public void updateFromLowerCompleteSource(CompleteFullDataSource subData)
{
- LodUtil.assertTrue(this.sectionPos.overlaps(subData.sectionPos));
- LodUtil.assertTrue(subData.sectionPos.sectionDetailLevel < this.sectionPos.sectionDetailLevel);
+ LodUtil.assertTrue(this.sectionPos.overlapsExactly(subData.sectionPos));
+ 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.getCorner(targetDataDetail);
+ DhLodPos minDataPos = this.sectionPos.getMinCornerLodPos(targetDataDetail);
if (detailDiff <= SECTION_SIZE_OFFSET)
{
int count = 1 << detailDiff;
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/HighDetailIncompleteFullDataSource.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/HighDetailIncompleteFullDataSource.java
index aac0d0b13..ab3388136 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/HighDetailIncompleteFullDataSource.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/HighDetailIncompleteFullDataSource.java
@@ -96,30 +96,30 @@ 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];
- this.chunkPos = sectionPos.getCorner(SPARSE_UNIT_DETAIL);
+ this.chunkPos = sectionPos.getMinCornerLodPos(SPARSE_UNIT_DETAIL);
this.mapping = new FullDataPointIdMap(sectionPos);
}
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);
this.sparseData = data;
- this.chunkPos = sectionPos.getCorner(SPARSE_UNIT_DETAIL);
+ this.chunkPos = sectionPos.getMinCornerLodPos(SPARSE_UNIT_DETAIL);
this.isEmpty = false;
this.mapping = mapping;
}
@@ -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 (dataFile.baseMetaData != null && 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;
@@ -422,7 +422,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 long getTypeId() { return TYPE_ID; }
@@ -460,7 +460,7 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo
@Override
public void update(ChunkSizedFullDataAccessor chunkDataView)
{
- int arrayOffset = this.calculateOffset(chunkDataView.pos.x, chunkDataView.pos.z);
+ int arrayOffset = this.calculateOffset(chunkDataView.chunkPos.x, chunkDataView.chunkPos.z);
FullDataArrayAccessor newArray = new FullDataArrayAccessor(this.mapping, new long[this.dataPointsPerSection * this.dataPointsPerSection][], this.dataPointsPerSection);
if (this.getDataDetailLevel() == chunkDataView.detailLevel)
{
@@ -492,8 +492,8 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo
public void sampleFrom(IFullDataSource fullDataSource)
{
DhSectionPos pos = fullDataSource.getSectionPos();
- LodUtil.assertTrue(pos.sectionDetailLevel < this.sectionPos.sectionDetailLevel);
- LodUtil.assertTrue(pos.overlaps(this.sectionPos));
+ LodUtil.assertTrue(pos.getDetailLevel() < this.sectionPos.getDetailLevel());
+ LodUtil.assertTrue(pos.overlapsExactly(this.sectionPos));
if (fullDataSource.isEmpty())
{
return;
@@ -524,10 +524,10 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo
DhSectionPos pos = completeDataSource.getSectionPos();
this.isEmpty = false;
- DhLodPos basePos = this.sectionPos.getCorner(SPARSE_UNIT_DETAIL);
- DhLodPos dataPos = pos.getCorner(SPARSE_UNIT_DETAIL);
+ DhLodPos basePos = this.sectionPos.getMinCornerLodPos(SPARSE_UNIT_DETAIL);
+ DhLodPos dataPos = pos.getMinCornerLodPos(SPARSE_UNIT_DETAIL);
- int coveredChunks = pos.getWidth(SPARSE_UNIT_DETAIL).numberOfLodSectionsWide;
+ int coveredChunks = pos.getWidthCountForLowerDetailedSection(SPARSE_UNIT_DETAIL);
int sourceDataPerChunk = SPARSE_UNIT_SIZE >>> completeDataSource.getDataDetailLevel();
LodUtil.assertTrue((coveredChunks * sourceDataPerChunk) == CompleteFullDataSource.WIDTH);
@@ -551,8 +551,8 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo
DhSectionPos pos = sparseDataSource.getSectionPos();
this.isEmpty = false;
- DhLodPos basePos = this.sectionPos.getCorner(SPARSE_UNIT_DETAIL);
- DhLodPos dataPos = pos.getCorner(SPARSE_UNIT_DETAIL);
+ DhLodPos basePos = this.sectionPos.getMinCornerLodPos(SPARSE_UNIT_DETAIL);
+ DhLodPos dataPos = pos.getMinCornerLodPos(SPARSE_UNIT_DETAIL);
int offsetX = dataPos.x - basePos.x;
int offsetZ = dataPos.z - basePos.z;
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/LowDetailIncompleteFullDataSource.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/LowDetailIncompleteFullDataSource.java
index 8b3c327fa..9e9fa81d3 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/LowDetailIncompleteFullDataSource.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/LowDetailIncompleteFullDataSource.java
@@ -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 long getTypeId() { return TYPE_ID; }
@Override
@@ -320,21 +320,21 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp
@Override
public void update(ChunkSizedFullDataAccessor data)
{
- LodUtil.assertTrue(this.sectionPos.getSectionBBoxPos().overlapsExactly(data.getLodPos()));
+ LodUtil.assertTrue(this.sectionPos.overlapsExactly(data.getSectionPos()));
if (this.getDataDetailLevel() >= 4)
{
//FIXME: TEMPORARY
int chunkPerFull = 1 << (this.getDataDetailLevel() - 4);
- if (data.pos.x % chunkPerFull != 0 || data.pos.z % chunkPerFull != 0)
+ if (data.chunkPos.x % chunkPerFull != 0 || data.chunkPos.z % chunkPerFull != 0)
{
return;
}
- DhLodPos baseOffset = this.sectionPos.getCorner(this.getDataDetailLevel());
- DhLodPos dataOffset = data.getLodPos().convertToDetailLevel(this.getDataDetailLevel());
- int offsetX = dataOffset.x - baseOffset.x;
- int offsetZ = dataOffset.z - baseOffset.z;
+ DhLodPos baseOffset = this.sectionPos.getMinCornerLodPos(this.getDataDetailLevel());
+ DhSectionPos dataOffset = data.getSectionPos().convertNewToDetailLevel(this.getDataDetailLevel());
+ 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;
@@ -355,8 +355,8 @@ 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.overlaps(this.sectionPos));
+ LodUtil.assertTrue(pos.getDetailLevel() < this.sectionPos.getDetailLevel());
+ LodUtil.assertTrue(pos.overlapsExactly(this.sectionPos));
if (fullDataSource.isEmpty())
{
@@ -386,21 +386,21 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp
private void sampleFrom(HighDetailIncompleteFullDataSource sparseSource)
{
- DhLodPos thisLodPos = this.sectionPos.getCorner(this.getDataDetailLevel());
+ DhLodPos thisLodPos = this.sectionPos.getMinCornerLodPos(this.getDataDetailLevel());
DhSectionPos pos = sparseSource.getSectionPos();
this.isEmpty = false;
- if (this.getDataDetailLevel() > this.sectionPos.sectionDetailLevel)
+ if (this.getDataDetailLevel() > this.sectionPos.getDetailLevel())
{
- DhLodPos dataLodPos = pos.getCorner(this.getDataDetailLevel());
+ DhLodPos dataLodPos = pos.getMinCornerLodPos(this.getDataDetailLevel());
int offsetX = dataLodPos.x - thisLodPos.x;
int offsetZ = dataLodPos.z - thisLodPos.z;
LodUtil.assertTrue(offsetX >= 0 && offsetX < WIDTH && offsetZ >= 0 && offsetZ < WIDTH);
int chunksPerData = 1 << (this.getDataDetailLevel() - HighDetailIncompleteFullDataSource.SPARSE_UNIT_DETAIL);
- int dataSpan = this.sectionPos.getWidth(this.getDataDetailLevel()).numberOfLodSectionsWide;
+ int dataSpan = this.sectionPos.getWidthCountForLowerDetailedSection(this.getDataDetailLevel());
for (int xOffset = 0; xOffset < dataSpan; xOffset++)
{
@@ -421,7 +421,7 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp
else
{
DhLodPos dataLodPos = pos.getSectionBBoxPos();
- int lowerSectionsPerData = this.sectionPos.getWidth(dataLodPos.detailLevel).numberOfLodSectionsWide;
+ int lowerSectionsPerData = this.sectionPos.getWidthCountForLowerDetailedSection(dataLodPos.detailLevel);
if (dataLodPos.x % lowerSectionsPerData != 0 || dataLodPos.z % lowerSectionsPerData != 0)
{
return;
@@ -447,14 +447,14 @@ 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.getCorner(this.getDataDetailLevel());
- DhLodPos dataLodPos = pos.getCorner(this.getDataDetailLevel());
+ DhLodPos thisLodPos = this.sectionPos.getMinCornerLodPos(this.getDataDetailLevel());
+ DhLodPos dataLodPos = pos.getMinCornerLodPos(this.getDataDetailLevel());
int offsetX = dataLodPos.x - thisLodPos.x;
int offsetZ = dataLodPos.z - thisLodPos.z;
- int dataWidth = this.sectionPos.getWidth(this.getDataDetailLevel()).numberOfLodSectionsWide;
+ int dataWidth = this.sectionPos.getWidthCountForLowerDetailedSection(this.getDataDetailLevel());
for (int xOffset = 0; xOffset < dataWidth; xOffset++)
{
@@ -467,14 +467,14 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp
else
{
DhLodPos dataPos = pos.getSectionBBoxPos();
- int lowerSectionsPerData = this.sectionPos.getWidth(dataPos.detailLevel).numberOfLodSectionsWide;
+ int lowerSectionsPerData = this.sectionPos.getWidthCountForLowerDetailedSection(dataPos.detailLevel);
if (dataPos.x % lowerSectionsPerData != 0 || dataPos.z % lowerSectionsPerData != 0)
{
return;
}
- DhLodPos basePos = this.sectionPos.getCorner(this.getDataDetailLevel());
+ DhLodPos basePos = this.sectionPos.getMinCornerLodPos(this.getDataDetailLevel());
dataPos = dataPos.convertToDetailLevel(this.getDataDetailLevel());
int offsetX = dataPos.x - basePos.x;
int offsetZ = dataPos.z - basePos.z;
@@ -490,14 +490,14 @@ 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.getCorner(this.getDataDetailLevel());
- DhLodPos dataLodPos = pos.getCorner(this.getDataDetailLevel());
+ DhLodPos thisLodPos = this.sectionPos.getMinCornerLodPos(this.getDataDetailLevel());
+ DhLodPos dataLodPos = pos.getMinCornerLodPos(this.getDataDetailLevel());
int offsetX = dataLodPos.x - thisLodPos.x;
int offsetZ = dataLodPos.z - thisLodPos.z;
- int dataWidth = this.sectionPos.getWidth(this.getDataDetailLevel()).numberOfLodSectionsWide;
+ int dataWidth = this.sectionPos.getWidthCountForLowerDetailedSection(this.getDataDetailLevel());
for (int xOffset = 0; xOffset < dataWidth; xOffset++)
{
@@ -510,14 +510,14 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp
else
{
DhLodPos dataPos = pos.getSectionBBoxPos();
- int lowerSectionsPerData = this.sectionPos.getWidth(dataPos.detailLevel).numberOfLodSectionsWide;
+ int lowerSectionsPerData = this.sectionPos.getWidthCountForLowerDetailedSection(dataPos.detailLevel);
if (dataPos.x % lowerSectionsPerData != 0 || dataPos.z % lowerSectionsPerData != 0)
{
return;
}
- DhLodPos basePos = this.sectionPos.getCorner(this.getDataDetailLevel());
+ DhLodPos basePos = this.sectionPos.getMinCornerLodPos(this.getDataDetailLevel());
dataPos = dataPos.convertToDetailLevel(this.getDataDetailLevel());
int offsetX = dataPos.x - basePos.x;
int offsetZ = dataPos.z - basePos.z;
@@ -573,14 +573,14 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp
public static boolean neededForPosition(DhSectionPos posToWrite, DhSectionPos posToTest)
{
- if (!posToWrite.overlaps(posToTest))
+ 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;
}
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/interfaces/IFullDataSource.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/interfaces/IFullDataSource.java
index bcf456b07..f0599441e 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/interfaces/IFullDataSource.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/interfaces/IFullDataSource.java
@@ -104,7 +104,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); });
}
@@ -128,30 +128,30 @@ 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;
- DhSectionPos minSecPos = this.getSectionPos().convertToDetailLevel(childDetailLevel);
+ DhSectionPos minSecPos = this.getSectionPos().convertNewToDetailLevel(childDetailLevel);
DhSectionPos inputPos = quadrantPos;
- 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;
@@ -188,21 +188,21 @@ 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;
- DhSectionPos minSecPos = this.getSectionPos().convertToDetailLevel(childDetailLevel);
+ DhSectionPos minSecPos = this.getSectionPos().convertNewToDetailLevel(childDetailLevel);
DhSectionPos inputPos = quadrantPos.getChildByIndex(i);
- 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;
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderLoader.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderLoader.java
index 013f964dc..45d34b8cf 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderLoader.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderLoader.java
@@ -20,16 +20,10 @@
package com.seibel.distanthorizons.core.dataObjects.render;
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiWorldGenerationStep;
-import com.seibel.distanthorizons.core.dataObjects.fullData.sources.interfaces.IFullDataSource;
-import com.seibel.distanthorizons.core.dataObjects.fullData.sources.interfaces.IIncompleteFullDataSource;
-import com.seibel.distanthorizons.core.file.renderfile.RenderMetaDataFile;
-import com.seibel.distanthorizons.core.level.IDhClientLevel;
+import com.seibel.distanthorizons.core.file.renderfile.RenderDataMetaFile;
import com.seibel.distanthorizons.core.level.IDhLevel;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
-import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.objects.dataStreams.DhDataInputStream;
-import com.seibel.distanthorizons.core.dataObjects.fullData.sources.CompleteFullDataSource;
-import com.seibel.distanthorizons.core.dataObjects.transformers.FullDataToRenderDataTransformer;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
@@ -37,7 +31,7 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
- * Handles loading and parsing {@link RenderMetaDataFile}s to create {@link ColumnRenderSource}s.
+ * Handles loading and parsing {@link RenderDataMetaFile}s to create {@link ColumnRenderSource}s.
*
* Please see the {@link ColumnRenderLoader#loadRenderSource} method to see what
* file versions this class can handle.
@@ -54,7 +48,7 @@ public class ColumnRenderLoader
- public ColumnRenderSource loadRenderSource(RenderMetaDataFile dataFile, DhDataInputStream inputStream, IDhLevel level) throws IOException
+ public ColumnRenderSource loadRenderSource(RenderDataMetaFile dataFile, DhDataInputStream inputStream, IDhLevel level) throws IOException
{
int dataFileVersion = dataFile.baseMetaData.binaryDataFormatVersion;
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderSource.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderSource.java
index 0fc4ea570..ece6027b7 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderSource.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderSource.java
@@ -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");
}
@@ -308,16 +308,16 @@ public class ColumnRenderSource
*/
public boolean updateWithChunkData(ChunkSizedFullDataAccessor chunkDataView, IDhClientLevel level)
{
- final String errorMessagePrefix = "Unable to complete fastWrite for RenderSource pos: [" + this.sectionPos + "] and chunk pos: [" + chunkDataView.pos + "]. Error:";
+ final String errorMessagePrefix = "Unable to complete fastWrite for RenderSource pos: [" + this.sectionPos + "] and chunk pos: [" + chunkDataView.chunkPos + "]. Error:";
final DhSectionPos renderSourcePos = this.getSectionPos();
- final int sourceBlockX = renderSourcePos.getCorner().getCornerBlockPos().x;
- final int sourceBlockZ = renderSourcePos.getCorner().getCornerBlockPos().z;
+ final int sourceBlockX = renderSourcePos.getMinCornerLodPos().getCornerBlockPos().x;
+ final int sourceBlockZ = renderSourcePos.getMinCornerLodPos().getCornerBlockPos().z;
// offset between the incoming chunk data and this render source
- final int blockOffsetX = (chunkDataView.pos.x * LodUtil.CHUNK_WIDTH) - sourceBlockX;
- final int blockOffsetZ = (chunkDataView.pos.z * LodUtil.CHUNK_WIDTH) - sourceBlockZ;
+ final int blockOffsetX = (chunkDataView.chunkPos.x * LodUtil.CHUNK_WIDTH) - sourceBlockX;
+ final int blockOffsetZ = (chunkDataView.chunkPos.z * LodUtil.CHUNK_WIDTH) - sourceBlockZ;
final int sourceDataPointBlockWidth = BitShiftUtil.powerOfTwo(this.getDataDetail());
@@ -360,27 +360,27 @@ 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.getLodPos().detailLevel)
+ else if (chunkDataView.detailLevel < this.getDataDetail() && this.getDataDetail() <= chunkDataView.getSectionPos().getDetailLevel())
{
this.markNotEmpty();
// multiple chunk data points converting to 1 column data point
- DhLodPos dataCornerPos = chunkDataView.getLodPos().getCornerLodPos(chunkDataView.detailLevel);
- DhLodPos sourceCornerPos = renderSourcePos.getCorner(this.getDataDetail());
+ DhLodPos dataCornerPos = chunkDataView.getSectionPos().getMinCornerLodPos(chunkDataView.detailLevel);
+ DhLodPos sourceCornerPos = renderSourcePos.getMinCornerLodPos(this.getDataDetail());
DhLodPos sourceStartingChangePos = dataCornerPos.convertToDetailLevel(this.getDataDetail());
int relStartX = Math.floorMod(sourceStartingChangePos.x, this.getWidthInDataPoints());
int relStartZ = Math.floorMod(sourceStartingChangePos.z, this.getWidthInDataPoints());
int dataToSourceScale = sourceCornerPos.getWidthAtDetail(chunkDataView.detailLevel);
- int columnsInChunk = chunkDataView.getLodPos().getWidthAtDetail(this.getDataDetail());
+ int columnsInChunk = chunkDataView.getSectionPos().getWidthCountForLowerDetailedSection(this.getDataDetail());
- for (int ox = 0; ox < columnsInChunk; ox++)
+ for (int xOffset = 0; xOffset < columnsInChunk; xOffset++)
{
- for (int oz = 0; oz < columnsInChunk; oz++)
+ for (int zOffset = 0; zOffset < columnsInChunk; zOffset++)
{
- int relSourceX = relStartX + ox;
- int relSourceZ = relStartZ + oz;
+ int relSourceX = relStartX + xOffset;
+ int relSourceZ = relStartZ + zOffset;
ColumnArrayView columnArrayView = this.getVerticalDataPointView(relSourceX, relSourceZ);
int hash = columnArrayView.getDataHash();
- SingleColumnFullDataAccessor fullArrayView = chunkDataView.get(ox * dataToSourceScale, oz * dataToSourceScale);
+ SingleColumnFullDataAccessor fullArrayView = chunkDataView.get(xOffset * dataToSourceScale, zOffset * dataToSourceScale);
FullDataToRenderDataTransformer.convertColumnData(level,
sourceBlockX + sourceDataPointBlockWidth * relSourceX,
sourceBlockZ + sourceDataPointBlockWidth * relSourceZ,
@@ -390,14 +390,14 @@ public class ColumnRenderSource
}
this.fillDebugFlag(relStartX, relStartZ, columnsInChunk, columnsInChunk, ColumnRenderSource.DebugSourceFlag.DIRECT);
}
- else if (chunkDataView.getLodPos().detailLevel < 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.getLodPos().getCornerLodPos(chunkDataView.detailLevel);
- DhLodPos sourceCornerPos = renderSourcePos.getCorner(this.getDataDetail());
+ DhLodPos dataCornerPos = chunkDataView.getSectionPos().getMinCornerLodPos(chunkDataView.detailLevel);
+ DhLodPos sourceCornerPos = renderSourcePos.getMinCornerLodPos(this.getDataDetail());
DhLodPos sourceStartingChangePos = dataCornerPos.convertToDetailLevel(this.getDataDetail());
- int chunksPerColumn = sourceStartingChangePos.getWidthAtDetail(chunkDataView.getLodPos().detailLevel);
- if (chunkDataView.getLodPos().x % chunksPerColumn != 0 || chunkDataView.getLodPos().z % 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()); }
@@ -526,7 +526,7 @@ public class ColumnRenderSource
stringBuilder.append(this.sectionPos);
stringBuilder.append(LINE_DELIMITER);
- int size = this.sectionPos.getWidth().numberOfLodSectionsWide;
+ int size = 1;
for (int z = 0; z < size; z++)
{
for (int x = 0; x < size; x++)
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java
index 168c3e283..a5b25e158 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java
@@ -125,7 +125,7 @@ public class ColumnRenderBufferBuilder
if (buffer == null)
{
- buffer = new ColumnRenderBuffer(new DhBlockPos(renderSource.sectionPos.getCorner().getCornerBlockPos(), clientLevel.getMinY()), renderSource.sectionPos);
+ buffer = new ColumnRenderBuffer(new DhBlockPos(renderSource.sectionPos.getMinCornerLodPos().getCornerBlockPos(), clientLevel.getMinY()), renderSource.sectionPos);
}
try
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java
index 40e707746..1438996ab 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java
@@ -132,12 +132,12 @@ public class FullDataToRenderDataTransformer
if (dataDetail == columnSource.getDataDetail())
{
- int baseX = pos.getCorner().getCornerBlockPos().x;
- int baseZ = pos.getCorner().getCornerBlockPos().z;
+ int baseX = pos.getMinCornerLodPos().getCornerBlockPos().x;
+ int baseZ = pos.getMinCornerLodPos().getCornerBlockPos().z;
- for (int x = 0; x < pos.getWidth(dataDetail).numberOfLodSectionsWide; x++)
+ for (int x = 0; x < pos.getWidthCountForLowerDetailedSection(dataDetail); x++)
{
- for (int z = 0; z < pos.getWidth(dataDetail).numberOfLodSectionsWide; z++)
+ for (int z = 0; z < pos.getWidthCountForLowerDetailedSection(dataDetail); z++)
{
throwIfThreadInterrupted();
@@ -182,11 +182,11 @@ public class FullDataToRenderDataTransformer
if (dataDetail == columnSource.getDataDetail())
{
- int baseX = pos.getCorner().getCornerBlockPos().x;
- int baseZ = pos.getCorner().getCornerBlockPos().z;
- for (int x = 0; x < pos.getWidth(dataDetail).numberOfLodSectionsWide; x++)
+ int baseX = pos.getMinCornerLodPos().getCornerBlockPos().x;
+ int baseZ = pos.getMinCornerLodPos().getCornerBlockPos().z;
+ for (int x = 0; x < pos.getWidthCountForLowerDetailedSection(dataDetail); x++)
{
- for (int z = 0; z < pos.getWidth(dataDetail).numberOfLodSectionsWide; z++)
+ for (int z = 0; z < pos.getWidthCountForLowerDetailedSection(dataDetail); z++)
{
throwIfThreadInterrupted();
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/DataSourceReferenceTracker.java b/core/src/main/java/com/seibel/distanthorizons/core/file/DataSourceReferenceTracker.java
new file mode 100644
index 000000000..2e7f7d51a
--- /dev/null
+++ b/core/src/main/java/com/seibel/distanthorizons/core/file/DataSourceReferenceTracker.java
@@ -0,0 +1,233 @@
+/*
+ * This file is part of the Distant Horizons mod
+ * licensed under the GNU LGPL v3 License.
+ *
+ * Copyright (C) 2020-2023 James Seibel
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.seibel.distanthorizons.core.file;
+
+import com.seibel.distanthorizons.core.dataObjects.fullData.sources.interfaces.IFullDataSource;
+import com.seibel.distanthorizons.core.dataObjects.render.ColumnRenderSource;
+import com.seibel.distanthorizons.core.file.fullDatafile.FullDataMetaFile;
+import com.seibel.distanthorizons.core.file.metaData.AbstractMetaDataContainerFile;
+import com.seibel.distanthorizons.core.file.renderfile.RenderDataMetaFile;
+import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
+import com.seibel.distanthorizons.core.util.ThreadUtil;
+import org.apache.logging.log4j.Logger;
+
+import java.io.Closeable;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Keeps track of {@link FullDataMetaFile} and {@link RenderDataMetaFile}'s
+ * and handles freeing their underlying data sources if they go unused for a certain amount of time.
+ */
+public class DataSourceReferenceTracker
+{
+ private static final Logger LOGGER = DhLoggerBuilder.getLogger();
+ private static final boolean LOG_GARBAGE_COLLECTIONS = false;
+
+ /** How often the garbage collector thread will run */
+ private static final long MS_BETWEEN_GARBAGE_CHECKS = TimeUnit.SECONDS.toMillis(60);
+ /** How long a data source has to go unused before it can be freed */
+ private static final long MS_TO_EXPIRE_DATA_SOURCE = TimeUnit.SECONDS.toMillis(60);
+
+
+ // these queues are populated by the JVM's garbage collector after the assigned soft reference is freed
+ private static final ReferenceQueue FULL_DATA_GARBAGE_COLLECTED_QUEUE = new ReferenceQueue<>();
+ private static final ReferenceQueue RENDER_DATA_GARBAGE_COLLECTED_QUEUE = new ReferenceQueue<>();
+
+ // TODO using a ConcurrentHashMap may or may not be the best choice here
+ private static final Set FULL_DATA_SOFT_REFS = ConcurrentHashMap.newKeySet();
+ private static final Set RENDER_DATA_SOFT_REFS = ConcurrentHashMap.newKeySet();
+
+ private static final ThreadPoolExecutor GARBAGE_COLLECTOR_THREAD = ThreadUtil.makeSingleThreadPool("DataSourceReferenceTracker", ThreadUtil.MINIMUM_RELATIVE_PRIORITY);
+
+
+
+ //=================//
+ // collector logic //
+ //=================//
+
+ /** Warning: this should not be called more than once. */
+ public static void startGarbageCollectorBackgroundThread() { /*GARBAGE_COLLECTOR_THREAD.execute(() -> garbageCollectorLoop());*/ }
+ private static void garbageCollectorLoop()
+ {
+ while(true)
+ {
+ try
+ {
+ runGarbageCollection();
+ Thread.sleep(MS_BETWEEN_GARBAGE_CHECKS);
+ }
+ catch (InterruptedException e)
+ {
+ LOGGER.error("Garbage collector thread interrupted.", e);
+ }
+ catch (Exception e)
+ {
+ LOGGER.error("Unexpected data source garbage collector exception: " + e.getMessage(), e);
+ }
+ }
+ }
+
+ public static void runGarbageCollection()
+ {
+ removeGarbageCollectedDataSources();
+ removeExpiredDataSources();
+ }
+ private static void removeGarbageCollectedDataSources()
+ {
+ FullDataSourceSoftRef garbageCollectedFullDataSoftRef = (FullDataSourceSoftRef) FULL_DATA_GARBAGE_COLLECTED_QUEUE.poll();
+ while (garbageCollectedFullDataSoftRef != null)
+ {
+ if (LOG_GARBAGE_COLLECTIONS)
+ {
+ LOGGER.info("Full Data at pos: " + garbageCollectedFullDataSoftRef.metaFile.pos + " has been soft released.");
+ }
+ garbageCollectedFullDataSoftRef.close();
+
+ garbageCollectedFullDataSoftRef = (FullDataSourceSoftRef) FULL_DATA_GARBAGE_COLLECTED_QUEUE.poll();
+ }
+
+ RenderDataSourceSoftRef renderSoftRef = (RenderDataSourceSoftRef) RENDER_DATA_GARBAGE_COLLECTED_QUEUE.poll();
+ while (renderSoftRef != null)
+ {
+ if (LOG_GARBAGE_COLLECTIONS)
+ {
+ LOGGER.info("Render Data at pos: " + renderSoftRef.metaFile.pos + " has been soft released.");
+ }
+ renderSoftRef.close();
+
+ renderSoftRef = (RenderDataSourceSoftRef) RENDER_DATA_GARBAGE_COLLECTED_QUEUE.poll();
+ }
+ }
+ private static void removeExpiredDataSources()
+ {
+ // TODO merge these loops
+ FULL_DATA_SOFT_REFS.removeIf((fullDataSoftRef) ->
+ {
+ boolean remove = fullDataSoftRef.isDataSourceExpired() || (fullDataSoftRef.silentGet() == null);
+ if (remove)
+ {
+ fullDataSoftRef.clear();
+ fullDataSoftRef.close();
+
+ if (LOG_GARBAGE_COLLECTIONS)
+ {
+ LOGGER.info("Full Data at pos: " + fullDataSoftRef.metaFile.pos + " has expired and will be released at the next GC. ["+FULL_DATA_SOFT_REFS.size()+"] Full data sources remain.");
+ }
+ }
+
+ return remove;
+ });
+
+ // TODO merge these loops
+ RENDER_DATA_SOFT_REFS.removeIf((renderDataSoftRef) ->
+ {
+ boolean remove = renderDataSoftRef.isDataSourceExpired() || (renderDataSoftRef.silentGet() == null);
+ if (remove)
+ {
+ renderDataSoftRef.clear();
+ renderDataSoftRef.close();
+
+ if (LOG_GARBAGE_COLLECTIONS)
+ {
+ LOGGER.info("Render Data at pos: " + renderDataSoftRef.metaFile.pos + " has expired and will be released at the next GC. ["+RENDER_DATA_SOFT_REFS.size()+"] Render data sources remain.");
+ }
+ }
+
+ return remove;
+ });
+ }
+
+
+
+ //================//
+ // helper classes //
+ //================//
+
+ public static class FullDataSourceSoftRef extends AbstractDataSourceSoftTracker
+ {
+ public FullDataSourceSoftRef(FullDataMetaFile metaFile, IFullDataSource data)
+ {
+ super(metaFile, data, FULL_DATA_GARBAGE_COLLECTED_QUEUE);
+ FULL_DATA_SOFT_REFS.add(this);
+ }
+
+ @Override
+ public void close() { FULL_DATA_SOFT_REFS.remove(this); }
+ }
+ public static class RenderDataSourceSoftRef extends AbstractDataSourceSoftTracker
+ {
+ public RenderDataSourceSoftRef(RenderDataMetaFile metaFile, ColumnRenderSource data)
+ {
+ super(metaFile, data, RENDER_DATA_GARBAGE_COLLECTED_QUEUE);
+ RENDER_DATA_SOFT_REFS.add(this);
+ }
+
+ @Override
+ public void close() { RENDER_DATA_SOFT_REFS.remove(this); }
+ }
+
+ /** wrapper for a {@link SoftReference} so we can track and manually remove unused sources */
+ public static abstract class AbstractDataSourceSoftTracker extends SoftReference implements Closeable
+ {
+ public final TMetaFile metaFile;
+ public final long createdMsTime;
+
+ private long expirationMsTime;
+
+
+
+ public AbstractDataSourceSoftTracker(TMetaFile metaFile, TDataSource dataSource, ReferenceQueue referenceQueue)
+ {
+ super(dataSource, referenceQueue);
+ this.metaFile = metaFile;
+
+ this.createdMsTime = System.currentTimeMillis();
+ this.expirationMsTime = System.currentTimeMillis();
+ }
+
+
+
+ public void updateLastAccessedTime() { this.expirationMsTime = System.currentTimeMillis() + MS_TO_EXPIRE_DATA_SOURCE; }
+ public long getExpirationMsTime() { return this.expirationMsTime; }
+ public boolean isDataSourceExpired() { return this.expirationMsTime > System.currentTimeMillis(); }
+
+
+ @Override
+ public TDataSource get()
+ {
+ this.updateLastAccessedTime();
+ return super.get();
+ }
+
+ /**
+ * Gets the underlying datasource without updating the {@link AbstractDataSourceSoftTracker#expirationMsTime}
+ * Note: this still updates {@link SoftReference}'s timestamp variable which may prevent the JVM from
+ * marking this reference as valid for deletion.
+ */
+ public TDataSource silentGet() { return super.get(); }
+
+ }
+
+}
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataFileHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataFileHandler.java
index 9a19d41ce..34ca6d695 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataFileHandler.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataFileHandler.java
@@ -107,11 +107,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);
};
@@ -138,7 +138,7 @@ public class FullDataFileHandler implements IFullDataSourceProvider
@Override
public CompletableFuture 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)
{
@@ -192,7 +192,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;
}
@@ -227,7 +227,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);
@@ -244,22 +244,24 @@ public class FullDataFileHandler implements IFullDataSourceProvider
DhSectionPos effectivePos, DhSectionPos posAreaToGet,
ArrayList preexistingFiles, ArrayList missingFilePositions)
{
- byte sectionDetail = posAreaToGet.sectionDetailLevel;
+ byte sectionDetail = posAreaToGet.getDetailLevel();
boolean allEmpty = true;
+ final DhSectionPos.DhMutableSectionPos subPos = new DhSectionPos.DhMutableSectionPos((byte)0, 0, 0);
+
// get all existing files for this position
outerLoop:
while (--sectionDetail >= this.minDetailLevel)
{
- DhLodPos minPos = posAreaToGet.getCorner().getCornerLodPos(sectionDetail);
+ DhLodPos minPos = posAreaToGet.getMinCornerLodPos().getCornerLodPos(sectionDetail);
int count = posAreaToGet.getSectionBBoxPos().getWidthAtDetail(sectionDetail);
for (int xOffset = 0; xOffset < count; xOffset++)
{
for (int zOffset = 0; zOffset < count; zOffset++)
{
- DhSectionPos subPos = new DhSectionPos(sectionDetail, xOffset + minPos.x, zOffset + minPos.z);
- LodUtil.assertTrue(posAreaToGet.overlaps(effectivePos) && subPos.overlaps(posAreaToGet));
+ subPos.mutate(sectionDetail, xOffset + minPos.x, zOffset + minPos.z);
+ LodUtil.assertTrue(posAreaToGet.overlapsExactly(effectivePos) && subPos.overlapsExactly(posAreaToGet));
//TODO: The following check is temporary as we only sample corner points, which means
// on a very different level, we may not need the entire section at all.
@@ -311,7 +313,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);
@@ -337,11 +339,11 @@ public class FullDataFileHandler implements IFullDataSourceProvider
@Override
public void writeChunkDataToFile(DhSectionPos sectionPos, ChunkSizedFullDataAccessor chunkDataView)
{
- DhLodPos chunkPos = chunkDataView.getLodPos();
- LodUtil.assertTrue(chunkPos.overlapsExactly(sectionPos.getSectionBBoxPos()), "Chunk " + chunkPos + " does not overlap section " + sectionPos);
+ DhSectionPos chunkSectionPos = chunkDataView.getSectionPos();
+ LodUtil.assertTrue(chunkSectionPos.overlapsExactly(sectionPos), "Chunk " + chunkSectionPos + " does not overlap section " + sectionPos);
- chunkPos = chunkPos.convertToDetailLevel((byte) this.minDetailLevel);
- this.writeChunkDataToMetaFile(new DhSectionPos(chunkPos.detailLevel, chunkPos.x, chunkPos.z), chunkDataView);
+ chunkSectionPos = chunkSectionPos.convertNewToDetailLevel((byte) this.minDetailLevel);
+ this.writeChunkDataToMetaFile(chunkSectionPos, chunkDataView);
}
private void writeChunkDataToMetaFile(DhSectionPos sectionPos, ChunkSizedFullDataAccessor chunkData)
{
@@ -352,7 +354,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);
@@ -387,7 +389,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);
}
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataMetaFile.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataMetaFile.java
index 43fa3825a..858f084e5 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataMetaFile.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataMetaFile.java
@@ -33,6 +33,7 @@ import com.seibel.distanthorizons.core.dataObjects.fullData.sources.CompleteFull
import com.seibel.distanthorizons.core.dataObjects.fullData.accessor.ChunkSizedFullDataAccessor;
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.interfaces.IFullDataSource;
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.interfaces.IIncompleteFullDataSource;
+import com.seibel.distanthorizons.core.file.DataSourceReferenceTracker;
import com.seibel.distanthorizons.core.file.metaData.AbstractMetaDataContainerFile;
import com.seibel.distanthorizons.core.file.metaData.BaseMetaData;
import com.seibel.distanthorizons.core.level.IDhLevel;
@@ -84,7 +85,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I
* When clearing, don't set to null, instead create a SoftReference containing null.
* This makes null checks simpler.
*/
- private SoftReference cachedFullDataSourceRef = new SoftReference<>(null);
+ private DataSourceReferenceTracker.FullDataSourceSoftRef cachedFullDataSourceRef = new DataSourceReferenceTracker.FullDataSourceSoftRef(this,null);
private final AtomicReference> dataSourceLoadFutureRef = new AtomicReference<>(null);
// === Concurrent Write tracking ===
@@ -343,7 +344,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I
{
checkAndLogPhantomDataSourceLifeCycles();
- DhLodPos chunkLodPos = new DhLodPos(LodUtil.CHUNK_DETAIL_LEVEL, chunkAccessor.pos.x, chunkAccessor.pos.z);
+ DhLodPos chunkLodPos = new DhLodPos(LodUtil.CHUNK_DETAIL_LEVEL, chunkAccessor.chunkPos.x, chunkAccessor.chunkPos.z);
LodUtil.assertTrue(this.pos.getSectionBBoxPos().overlapsExactly(chunkLodPos), "Chunk pos " + chunkLodPos + " doesn't exactly overlap with section " + this.pos);
//LOGGER.info("Write Chunk {} to file {}", chunkPos, pos);
@@ -401,7 +402,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I
public static void checkAndLogPhantomDataSourceLifeCycles()
{
DataObjTracker phantomRef = (DataObjTracker) LIFE_CYCLE_DEBUG_QUEUE.poll();
- // wait for the tracker to be garbage collected(?)
+ // wait for the tracker to be garbage collected
while (phantomRef != null)
{
if (LOG_DATA_SOURCE_LIVES)
@@ -430,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;
}
@@ -554,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()),
@@ -563,7 +564,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I
// save the updated data source
- this.cachedFullDataSourceRef = new SoftReference<>(fullDataSource);
+ this.cachedFullDataSourceRef = new DataSourceReferenceTracker.FullDataSourceSoftRef(this, fullDataSource);
// the task is complete
completionFuture.complete(fullDataSource);
@@ -685,7 +686,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I
if (LOG_DATA_SOURCE_LIVES)
{
- LOGGER.info("Phantom created on {}! count: {}", data.getSectionPos(), LIFE_CYCLE_DEBUG_SET.size());
+ //LOGGER.info("Phantom created on "+data.getSectionPos()+"! count: "+LIFE_CYCLE_DEBUG_SET.size());
}
LIFE_CYCLE_DEBUG_SET.add(this);
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java
index 242e36217..e15369033 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java
@@ -355,7 +355,7 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler
return (chunkSizedFullDataSource) ->
{
- if (chunkSizedFullDataSource.getLodPos().overlapsExactly(this.loadedTargetFullDataSource.getSectionPos().getSectionBBoxPos()))
+ if (chunkSizedFullDataSource.getSectionPos().overlapsExactly(this.loadedTargetFullDataSource.getSectionPos()))
{
((DhLevel) level).saveWrites(chunkSizedFullDataSource);
//GeneratedFullDataFileHandler.this.write(this.loadedTargetFullDataSource.getSectionPos(), chunkSizedFullDataSource);
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/metaData/AbstractMetaDataContainerFile.java b/core/src/main/java/com/seibel/distanthorizons/core/file/metaData/AbstractMetaDataContainerFile.java
index 168bae813..846e1b71c 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/file/metaData/AbstractMetaDataContainerFile.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/file/metaData/AbstractMetaDataContainerFile.java
@@ -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
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/RenderMetaDataFile.java b/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/RenderDataMetaFile.java
similarity index 91%
rename from core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/RenderMetaDataFile.java
rename to core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/RenderDataMetaFile.java
index d5e739570..60991802a 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/RenderMetaDataFile.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/RenderDataMetaFile.java
@@ -23,14 +23,13 @@ import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dataObjects.fullData.accessor.ChunkSizedFullDataAccessor;
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.interfaces.IFullDataSource;
import com.seibel.distanthorizons.core.dataObjects.transformers.FullDataToRenderDataTransformer;
+import com.seibel.distanthorizons.core.file.DataSourceReferenceTracker;
import com.seibel.distanthorizons.core.file.fullDatafile.FullDataMetaFile;
import com.seibel.distanthorizons.core.file.fullDatafile.IFullDataSourceProvider;
import com.seibel.distanthorizons.core.file.metaData.AbstractMetaDataContainerFile;
import com.seibel.distanthorizons.core.file.metaData.BaseMetaData;
-import com.seibel.distanthorizons.core.level.IDhLevel;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
-import com.seibel.distanthorizons.core.pos.DhLodPos;
import com.seibel.distanthorizons.core.pos.DhSectionPos;
import com.seibel.distanthorizons.core.dataObjects.render.ColumnRenderLoader;
import com.seibel.distanthorizons.core.dataObjects.render.ColumnRenderSource;
@@ -47,13 +46,12 @@ import java.awt.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
-import java.lang.ref.SoftReference;
import java.util.Random;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicReference;
/** Represents a File that contains a {@link ColumnRenderSource}. */
-public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements IDebugRenderable
+public class RenderDataMetaFile extends AbstractMetaDataContainerFile implements IDebugRenderable
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
@@ -68,7 +66,7 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements
* When clearing, don't set to null, instead create a SoftReference containing null.
* This makes null checks simpler.
*/
- private SoftReference cachedRenderDataSource = new SoftReference<>(null);
+ private DataSourceReferenceTracker.RenderDataSourceSoftRef cachedRenderDataSource = new DataSourceReferenceTracker.RenderDataSourceSoftRef(this, null);
private final AtomicReference> renderSourceLoadFutureRef = new AtomicReference<>(null);
private final IDhClientLevel clientLevel;
@@ -82,10 +80,10 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements
//=============//
/**
- * Can be used instead of {@link RenderMetaDataFile#createFromExistingFile} or {@link RenderMetaDataFile#createNewFileForPos},
+ * Can be used instead of {@link RenderDataMetaFile#createFromExistingFile} or {@link RenderDataMetaFile#createNewFileForPos},
* if we are uncertain whether a file exists or not.
*/
- public static RenderMetaDataFile createFromExistingOrNewFile(IDhClientLevel clientLevel, IFullDataSourceProvider fullDataSourceProvider, DhSectionPos pos, File file) throws IOException
+ public static RenderDataMetaFile createFromExistingOrNewFile(IDhClientLevel clientLevel, IFullDataSourceProvider fullDataSourceProvider, DhSectionPos pos, File file) throws IOException
{
if (file.exists())
{
@@ -102,8 +100,8 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements
* NOTE: should only be used if there is NOT an existing file.
* @throws IOException if a file already exists for this position
*/
- public static RenderMetaDataFile createNewFileForPos(IFullDataSourceProvider fullDataSourceProvider, IDhClientLevel clientLevel, DhSectionPos pos, File file) throws IOException { return new RenderMetaDataFile(fullDataSourceProvider, clientLevel, pos, file); }
- private RenderMetaDataFile(IFullDataSourceProvider fullDataSourceProvider, IDhClientLevel clientLevel, DhSectionPos pos, File file) throws IOException
+ public static RenderDataMetaFile createNewFileForPos(IFullDataSourceProvider fullDataSourceProvider, IDhClientLevel clientLevel, DhSectionPos pos, File file) throws IOException { return new RenderDataMetaFile(fullDataSourceProvider, clientLevel, pos, file); }
+ private RenderDataMetaFile(IFullDataSourceProvider fullDataSourceProvider, IDhClientLevel clientLevel, DhSectionPos pos, File file) throws IOException
{
super(file, pos);
this.fullDataSourceProvider = fullDataSourceProvider;
@@ -118,8 +116,8 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements
* NOTE: should only be used if there IS an existing file.
* @throws IOException if no file exists for this position
*/
- public static RenderMetaDataFile createFromExistingFile(IFullDataSourceProvider fullDataSourceProvider, IDhClientLevel clientLevel, File file) throws IOException { return new RenderMetaDataFile(fullDataSourceProvider, clientLevel, file); }
- private RenderMetaDataFile(IFullDataSourceProvider fullDataSourceProvider, IDhClientLevel clientLevel, File file) throws IOException
+ public static RenderDataMetaFile createFromExistingFile(IFullDataSourceProvider fullDataSourceProvider, IDhClientLevel clientLevel, File file) throws IOException { return new RenderDataMetaFile(fullDataSourceProvider, clientLevel, file); }
+ private RenderDataMetaFile(IFullDataSourceProvider fullDataSourceProvider, IDhClientLevel clientLevel, File file) throws IOException
{
super(file);
this.fullDataSourceProvider = fullDataSourceProvider;
@@ -137,8 +135,8 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements
public void updateChunkIfSourceExistsAsync(ChunkSizedFullDataAccessor chunkDataView)
{
- DhLodPos chunkPos = chunkDataView.getLodPos();
- LodUtil.assertTrue(this.pos.getSectionBBoxPos().overlapsExactly(chunkPos), "Chunk pos " + chunkPos + " doesn't overlap with section " + this.pos);
+ DhSectionPos chunkSectionPos = chunkDataView.getSectionPos();
+ LodUtil.assertTrue(this.pos.overlapsExactly(chunkSectionPos), "Chunk pos " + chunkSectionPos + " doesn't overlap with section " + this.pos);
// update the render source if one exists
CompletableFuture renderSourceLoadFuture = this.getCachedDataSourceAsync(false);
@@ -157,7 +155,7 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements
Color debugColor = dataUpdated ? Color.blue : Color.red;
DebugRenderer.makeParticle(
new DebugRenderer.BoxParticle(
- new DebugRenderer.Box(chunkDataView.getLodPos(), 32f, 64f + offset, 0.07f, debugColor),
+ new DebugRenderer.Box(chunkDataView.getSectionPos(), 32f, 64f + offset, 0.07f, debugColor),
2.0, 16f
)
);
@@ -199,7 +197,7 @@ public class RenderMetaDataFile 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());
@@ -210,7 +208,7 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements
this.updateRenderCacheAsync(newColumnRenderSource).whenComplete((voidObj, ex) ->
{
- this.cachedRenderDataSource = new SoftReference<>(newColumnRenderSource);
+ this.cachedRenderDataSource = new DataSourceReferenceTracker.RenderDataSourceSoftRef(this, newColumnRenderSource);
this.renderSourceLoadFutureRef.set(null);
getSourceFuture.complete(newColumnRenderSource);
@@ -258,7 +256,7 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements
this.renderSourceLoadFutureRef.set(null);
- this.cachedRenderDataSource = new SoftReference<>(renderSource);
+ this.cachedRenderDataSource = new DataSourceReferenceTracker.RenderDataSourceSoftRef(this, renderSource);
getSourceFuture.complete(renderSource);
});
}
@@ -465,7 +463,7 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile implements
// helper methods //
//================//
- /** @return returns null if {@link RenderMetaDataFile#renderSourceLoadFutureRef} is empty and no cached {@link ColumnRenderSource} exists. */
+ /** @return returns null if {@link RenderDataMetaFile#renderSourceLoadFutureRef} is empty and no cached {@link ColumnRenderSource} exists. */
@Nullable
private CompletableFuture getCachedDataSourceAsync(boolean updateRenderSourceCache)
{
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/RenderSourceFileHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/RenderSourceFileHandler.java
index 40cb1eae8..9dc6a8bdc 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/RenderSourceFileHandler.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/RenderSourceFileHandler.java
@@ -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;
@@ -50,8 +49,8 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
private final F3Screen.NestedMessage threadPoolMsg;
private final ConcurrentHashMap unloadedFileBySectionPos = new ConcurrentHashMap<>();
- /** contains the loaded {@link RenderMetaDataFile}'s */
- private final ConcurrentHashMap metaFileBySectionPos = new ConcurrentHashMap<>();
+ /** contains the loaded {@link RenderDataMetaFile}'s */
+ private final ConcurrentHashMap metaFileBySectionPos = new ConcurrentHashMap<>();
private final IDhClientLevel clientLevel;
private final File saveDir;
@@ -93,21 +92,21 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
@Override
public void addScannedFiles(Collection detectedFiles)
{
- MetaFileScanUtil.ICreateMetadataFunc createMetadataFunc = (file) -> RenderMetaDataFile.createFromExistingFile(this.fullDataSourceProvider, this.clientLevel, file);
+ MetaFileScanUtil.ICreateMetadataFunc createMetadataFunc = (file) -> RenderDataMetaFile.createFromExistingFile(this.fullDataSourceProvider, this.clientLevel, file);
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.metaFileBySectionPos.put(pos, (RenderMetaDataFile) loadedMetaFile);
+ this.topDetailLevelRef.updateAndGet(oldDetailLevel -> Math.max(oldDetailLevel, pos.getDetailLevel()));
+ this.metaFileBySectionPos.put(pos, (RenderDataMetaFile) loadedMetaFile);
};
- MetaFileScanUtil.addScannedFiles(detectedFiles, USE_LAZY_LOADING, RenderMetaDataFile.FILE_SUFFIX,
+ MetaFileScanUtil.addScannedFiles(detectedFiles, USE_LAZY_LOADING, RenderDataMetaFile.FILE_SUFFIX,
createMetadataFunc,
addUnloadedFileFunc, addLoadedMetaFileFunc);
}
@@ -130,7 +129,7 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
- RenderMetaDataFile metaFile = this.getLoadOrMakeFile(pos);
+ RenderDataMetaFile metaFile = this.getLoadOrMakeFile(pos);
if (metaFile == null)
{
return CompletableFuture.completedFuture(ColumnRenderSource.createEmptyRenderSource(pos));
@@ -154,9 +153,9 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
return getDataSourceFuture;
}
/** @return null if there was an issue */
- private RenderMetaDataFile getLoadOrMakeFile(DhSectionPos pos)
+ private RenderDataMetaFile getLoadOrMakeFile(DhSectionPos pos)
{
- RenderMetaDataFile metaFile = this.metaFileBySectionPos.get(pos);
+ RenderDataMetaFile metaFile = this.metaFileBySectionPos.get(pos);
if (metaFile != null)
{
// return the loaded file
@@ -194,8 +193,8 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
// attempt to load the file
try
{
- metaFile = RenderMetaDataFile.createFromExistingFile(this.fullDataSourceProvider, this.clientLevel, fileToLoad);
- this.topDetailLevelRef.updateAndGet(currentTopDetailLevel -> Math.max(currentTopDetailLevel, pos.sectionDetailLevel));
+ metaFile = RenderDataMetaFile.createFromExistingFile(this.fullDataSourceProvider, this.clientLevel, fileToLoad);
+ this.topDetailLevelRef.updateAndGet(currentTopDetailLevel -> Math.max(currentTopDetailLevel, pos.getDetailLevel()));
this.metaFileBySectionPos.put(pos, metaFile);
return metaFile;
}
@@ -219,12 +218,12 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
{
// createFromExistingOrNewFile() is used instead of createFromExistingFile()
// due to a rare issue where the file may already exist but isn't in the file list
- metaFile = RenderMetaDataFile.createFromExistingOrNewFile(this.clientLevel, this.fullDataSourceProvider, pos, this.computeRenderFilePath(pos));
+ 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
- RenderMetaDataFile metaFileCas = this.metaFileBySectionPos.putIfAbsent(pos, metaFile);
+ RenderDataMetaFile metaFileCas = this.metaFileBySectionPos.putIfAbsent(pos, metaFile);
return (metaFileCas == null) ? metaFile : metaFileCas;
}
catch (IOException e)
@@ -253,16 +252,18 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
}
private void writeChunkDataToFileRecursively(ChunkSizedFullDataAccessor chunk, byte sectionDetailLevel)
{
- DhLodPos boundingPos = chunk.getLodPos();
- DhLodPos minSectionPos = boundingPos.convertToDetailLevel(sectionDetailLevel);
+ DhSectionPos boundingPos = chunk.getSectionPos();
+ DhSectionPos minSectionPos = boundingPos.convertNewToDetailLevel(sectionDetailLevel);
- int width = (sectionDetailLevel > boundingPos.detailLevel) ? 1 : boundingPos.getWidthAtDetail(sectionDetailLevel);
+ DhSectionPos.DhMutableSectionPos fileSectionPos = new DhSectionPos.DhMutableSectionPos((byte)0, 0, 0);
+
+ int width = (sectionDetailLevel > boundingPos.getDetailLevel()) ? 1 : boundingPos.getWidthCountForLowerDetailedSection(sectionDetailLevel);
for (int xOffset = 0; xOffset < width; xOffset++)
{
for (int zOffset = 0; zOffset < width; zOffset++)
{
- DhSectionPos sectionPos = new DhSectionPos(sectionDetailLevel, minSectionPos.x + xOffset, minSectionPos.z + zOffset);
- RenderMetaDataFile metaFile = this.metaFileBySectionPos.get(sectionPos); // bypass the getLoadOrMakeFile() since we only want cached files.
+ 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)
{
metaFile.updateChunkIfSourceExistsAsync(chunk);
@@ -284,7 +285,7 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
LOGGER.info("Shutting down " + RenderSourceFileHandler.class.getSimpleName() + "...");
ArrayList> futures = new ArrayList<>();
- for (RenderMetaDataFile metaFile : this.metaFileBySectionPos.values())
+ for (RenderDataMetaFile metaFile : this.metaFileBySectionPos.values())
{
futures.add(metaFile.flushAndSaveAsync());
}
@@ -378,7 +379,7 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
// helper methods //
//================//
- public File computeRenderFilePath(DhSectionPos pos) { return new File(this.saveDir, pos.serialize() + RenderMetaDataFile.FILE_SUFFIX); }
+ public File computeRenderFilePath(DhSectionPos pos) { return new File(this.saveDir, pos.serialize() + RenderDataMetaFile.FILE_SUFFIX); }
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java b/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java
index b32426a42..3cf6f863b 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java
@@ -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> 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 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);
}
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java b/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java
index ac3ec177c..a75d24755 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java
@@ -175,16 +175,16 @@ public class ClientLevelModule implements Closeable
//===============//
public void writeChunkDataToFile(ChunkSizedFullDataAccessor data)
{
- DhLodPos pos = data.getLodPos().convertToDetailLevel(CompleteFullDataSource.SECTION_SIZE_OFFSET);
+ DhSectionPos pos = data.getSectionPos().convertNewToDetailLevel(CompleteFullDataSource.SECTION_SIZE_OFFSET);
ClientRenderState ClientRenderState = this.ClientRenderStateRef.get();
if (ClientRenderState != null)
{
- ClientRenderState.renderSourceFileHandler.writeChunkDataToFile(new DhSectionPos(pos.detailLevel, pos.x, pos.z), data);
+ ClientRenderState.renderSourceFileHandler.writeChunkDataToFile(pos, data);
}
else
{
- this.parentClientLevel.getFileHandler().writeChunkDataToFile(new DhSectionPos(pos.detailLevel, pos.x, pos.z), data);
+ this.parentClientLevel.getFileHandler().writeChunkDataToFile(pos, data);
}
}
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java
index 202502855..36379395f 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java
@@ -279,8 +279,9 @@ public class DhServerLevel extends DhLevel implements IDhServerLevel
@Override
public void saveWrites(ChunkSizedFullDataAccessor data)
{
- DhLodPos pos = data.getLodPos().convertToDetailLevel(CompleteFullDataSource.SECTION_SIZE_OFFSET);
- getFileHandler().writeChunkDataToFile(new DhSectionPos(pos.detailLevel, pos.x, pos.z), data);
+ DhSectionPos pos = data.getSectionPos();
+ pos = pos.convertNewToDetailLevel(CompleteFullDataSource.SECTION_SIZE_OFFSET);
+ this.getFileHandler().writeChunkDataToFile(pos, data);
}
@Override
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhBlockPos2D.java b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhBlockPos2D.java
index 7ea8b68e6..c6f8c1906 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhBlockPos2D.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhBlockPos2D.java
@@ -26,6 +26,13 @@ public class DhBlockPos2D
public static final DhBlockPos2D ZERO = new DhBlockPos2D(0, 0);
public final int x;
public final int z;
+
+
+
+ //==============//
+ // constructors //
+ //==============//
+
public DhBlockPos2D(int x, int z)
{
this.x = x;
@@ -38,44 +45,42 @@ public class DhBlockPos2D
this.z = blockPos.z;
}
- public DhBlockPos2D add(DhBlockPos2D other)
- {
- return new DhBlockPos2D(x + other.x, z + other.z);
- }
+ public static DhBlockPos2D fromPos2D(Pos2D pos) { return new DhBlockPos2D(pos.x, pos.y); }
- public DhBlockPos2D add(int offsetX, int offsetZ)
- {
- return new DhBlockPos2D(x + offsetX, z + offsetZ);
- }
- public DhBlockPos2D subtract(DhBlockPos2D other)
- {
- return new DhBlockPos2D(x - other.x, z - other.z);
- }
- public double dist(DhBlockPos2D other)
- {
- return Math.sqrt(Math.pow(x - other.x, 2) + Math.pow(z - other.z, 2));
- }
- public long distSquared(DhBlockPos2D other)
- {
- return MathUtil.pow2((long) x - other.x) + MathUtil.pow2((long) z - other.z);
- }
- public Pos2D toPos2D()
- {
- return new Pos2D(x, z);
- }
+ //==========//
+ // mutators //
+ //==========//
- public static DhBlockPos2D fromPos2D(Pos2D pos)
- {
- return new DhBlockPos2D(pos.x, pos.y);
- }
+ public DhBlockPos2D add(DhBlockPos2D other) { return new DhBlockPos2D(this.x + other.x, this.z + other.z); }
+
+ public DhBlockPos2D add(int offsetX, int offsetZ) { return new DhBlockPos2D(this.x + offsetX, this.z + offsetZ); }
+
+ public DhBlockPos2D subtract(DhBlockPos2D other) { return new DhBlockPos2D(this.x - other.x, this.z - other.z); }
+
+ public Pos2D toPos2D() { return new Pos2D(this.x, this.z); }
+
+
+
+ //==============//
+ // calculations //
+ //==============//
+
+ public double dist(DhBlockPos2D other) { return this.dist(other.x, other.z); }
+ public double dist(int x, int z) { return Math.sqrt(Math.pow(this.x - x, 2) + Math.pow(this.z - z, 2)); }
+
+ public long distSquared(DhBlockPos2D other) { return this.distSquared(other.x, other.z); }
+ public long distSquared(int x, int z) { return MathUtil.pow2((long) this.x - x) + MathUtil.pow2((long) this.z - z); }
+
+
+
+ //===========//
+ // overrides //
+ //===========//
@Override
- public String toString()
- {
- return "(" + x + ", " + z + ")";
- }
+ public String toString() { return "(" + this.x + ", " + this.z + ")"; }
@Override
public boolean equals(Object obj)
@@ -83,15 +88,13 @@ public class DhBlockPos2D
if (obj instanceof DhBlockPos2D)
{
DhBlockPos2D other = (DhBlockPos2D) obj;
- return x == other.x && z == other.z;
+ return this.x == other.x && this.z == other.z;
}
+
return false;
}
@Override
- public int hashCode()
- {
- return Integer.hashCode(x) ^ Integer.hashCode(z);
- }
+ public int hashCode() { return Integer.hashCode(this.x) ^ Integer.hashCode(this.z); }
}
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhLodPos.java b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhLodPos.java
index f3aa7df76..21273d79a 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhLodPos.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhLodPos.java
@@ -47,8 +47,7 @@ public class DhLodPos implements Comparable
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()); }
@@ -193,11 +192,14 @@ public class DhLodPos implements Comparable
public boolean overlapsExactly(DhLodPos other)
{
if (this.equals(other))
+ {
return true;
- if (this.detailLevel == other.detailLevel)
+ }
+ else if (this.detailLevel == other.detailLevel)
+ {
return false;
-
- if (this.detailLevel > other.detailLevel)
+ }
+ else if (this.detailLevel > other.detailLevel)
{
return this.equals(other.convertToDetailLevel(this.detailLevel));
}
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java
index fc744673c..b453ec777 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java
@@ -24,7 +24,6 @@ import com.seibel.distanthorizons.core.network.protocol.INetworkObject;
import com.seibel.distanthorizons.coreapi.util.BitShiftUtil;
import com.seibel.distanthorizons.core.util.LodUtil;
import io.netty.buffer.ByteBuf;
-import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.Consumer;
@@ -44,7 +43,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 implements INetworkObject
{
@@ -59,116 +57,170 @@ public class DhSectionPos implements INetworkObject
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;
public static DhSectionPos zero() { return new DhSectionPos((byte) 0, 0, 0); };
-
+
//==============//
// 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) { this(new DhBlockPos2D(blockPos)); }
+ public DhSectionPos(DhBlockPos blockPos)
+ {
+ this(LodUtil.BLOCK_DETAIL_LEVEL, blockPos.x, blockPos.z);
+ this.convertSelfToDetailLevel(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL);
+ }
public DhSectionPos(DhBlockPos2D blockPos)
{
- DhLodPos lodPos = new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPos.x, blockPos.z);
- lodPos = lodPos.convertToDetailLevel(SECTION_BLOCK_DETAIL_LEVEL);
-
- this.sectionDetailLevel = SECTION_BLOCK_DETAIL_LEVEL;
- this.sectionX = lodPos.x;
- this.sectionZ = lodPos.z;
+ this(LodUtil.BLOCK_DETAIL_LEVEL, blockPos.x, blockPos.z);
+ this.convertSelfToDetailLevel(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL);
}
public DhSectionPos(DhChunkPos chunkPos)
{
- DhLodPos lodPos = new DhLodPos(LodUtil.CHUNK_DETAIL_LEVEL, chunkPos.x, chunkPos.z);
- lodPos = lodPos.convertToDetailLevel(SECTION_CHUNK_DETAIL_LEVEL);
-
- this.sectionDetailLevel = SECTION_CHUNK_DETAIL_LEVEL;
- this.sectionX = lodPos.x;
- this.sectionZ = lodPos.z;
+ this(LodUtil.CHUNK_DETAIL_LEVEL, chunkPos.x, chunkPos.z);
+ this.convertSelfToDetailLevel(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL);
}
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;
}
- /** Returns the center for the highest detail level (0) */
- public DhLodPos getCenter() { return this.getCenter((byte) 0); } // TODO why does this use detail level 0 instead of this object's detail level?
- public DhLodPos getCenter(byte returnDetailLevel)
- {
- LodUtil.assertTrue(returnDetailLevel <= this.sectionDetailLevel, "returnDetailLevel must be less than sectionDetail");
-
- if (returnDetailLevel == this.sectionDetailLevel)
- {
- return new DhLodPos(this.sectionDetailLevel, this.sectionX, this.sectionZ);
- }
-
- byte detailLevelOffset = (byte) (this.sectionDetailLevel - returnDetailLevel);
-
- // we can't get the center of the position at block level, only attempt to get the position offset for detail levels above 0 // TODO should this also apply to detail level 1 or is it fine?
- int positionOffset = 0;
- if (this.sectionDetailLevel != 1 || returnDetailLevel != 0)
- {
- positionOffset = BitShiftUtil.powerOfTwo(detailLevelOffset - 1);
- }
-
- return new DhLodPos(returnDetailLevel,
- (this.sectionX * BitShiftUtil.powerOfTwo(detailLevelOffset)) + positionOffset,
- (this.sectionZ * BitShiftUtil.powerOfTwo(detailLevelOffset)) + positionOffset);
- }
- /** @return the corner with the smallest X and Z coordinate */
- public DhLodPos getCorner() { return this.getCorner((byte) (this.sectionDetailLevel - 1)); }
- /** @return the corner with the smallest X and Z coordinate */
- public DhLodPos getCorner(byte returnDetailLevel)
- {
- LodUtil.assertTrue(returnDetailLevel <= this.sectionDetailLevel, "returnDetailLevel must be less than sectionDetail");
- byte offset = (byte) (this.sectionDetailLevel - returnDetailLevel);
- return new DhLodPos(returnDetailLevel,
- this.sectionX * BitShiftUtil.powerOfTwo(offset),
- this.sectionZ * BitShiftUtil.powerOfTwo(offset));
- }
-
- public DhLodUnit getWidth() { return this.getWidth(this.sectionDetailLevel); }
- public DhLodUnit getWidth(byte returnDetailLevel)
- {
- LodUtil.assertTrue(returnDetailLevel <= this.sectionDetailLevel, "returnDetailLevel must be less than sectionDetail");
- byte offset = (byte) (this.sectionDetailLevel - returnDetailLevel);
- return new DhLodUnit(this.sectionDetailLevel, BitShiftUtil.powerOfTwo(offset));
- }
+ //============//
+ // converters //
+ //============//
/**
- * uses the absolute detail level aka detail levels like {@link LodUtil#CHUNK_DETAIL_LEVEL} instead of the dhSectionPos detailLevels
+ * uses the absolute detail level aka detail levels like {@link LodUtil#CHUNK_DETAIL_LEVEL} instead of the dhSectionPos detailLevels.
*
* @return the new position closest to negative infinity with the new detail level
*/
- public DhSectionPos convertToDetailLevel(byte newSectionDetailLevel)
+ public DhSectionPos convertNewToDetailLevel(byte newSectionDetailLevel)
{
- DhLodPos lodPos = new DhLodPos(this.sectionDetailLevel, this.sectionX, this.sectionZ);
- lodPos = lodPos.convertToDetailLevel(newSectionDetailLevel);
+ DhSectionPos newPos = new DhSectionPos(this.detailLevel, this.x, this.z);
+ newPos.convertSelfToDetailLevel(newSectionDetailLevel);
- DhSectionPos newPos = new DhSectionPos(newSectionDetailLevel, lodPos);
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; }
+
+
+
+ //=========//
+ // getters //
+ //=========//
+
+ /** @return the corner with the smallest X and Z coordinate */
+ 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.detailLevel, "returnDetailLevel must be less than sectionDetail");
+
+ byte offset = (byte) (this.detailLevel - returnDetailLevel);
+ return new DhLodPos(returnDetailLevel,
+ this.x * BitShiftUtil.powerOfTwo(offset),
+ this.z * BitShiftUtil.powerOfTwo(offset));
+ }
+
+ /**
+ * A detail level of X lower than this section's detail level will return:
+ * 0 -> 1
+ * 1 -> 2
+ * 2 -> 4
+ * 3 -> 8
+ * etc.
+ *
+ * @return how many {@link DhSectionPos}'s at the given detail level it would take to span the width of this section.
+ */
+ public int getWidthCountForLowerDetailedSection(byte 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.detailLevel); }
+
+
+ public DhBlockPos2D getCenterBlockPos() { return new DhBlockPos2D(this.getCenterBlockPosX(), this.getCenterBlockPosZ()); }
+
+ public int getCenterBlockPosX() { return this.getCenterBlockPos(true); }
+ public int getCenterBlockPosZ() { return this.getCenterBlockPos(false); }
+ private int getCenterBlockPos(boolean returnX)
+ {
+ int centerBlockPos = returnX ? this.x : this.z;
+
+ if (this.detailLevel == 0)
+ {
+ // already at block detail level, no conversion necessary
+ return centerBlockPos;
+ }
+
+ // 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.detailLevel != 1)
+ {
+ positionOffset = BitShiftUtil.powerOfTwo(this.detailLevel - 1);
+ }
+
+ return (centerBlockPos * BitShiftUtil.powerOfTwo(this.detailLevel)) + positionOffset;
+ }
+
+
+
+ //==================//
+ // parent child pos //
+ //==================//
+
/**
* Returns the DhLodPos 1 detail level lower
*
@@ -183,16 +235,79 @@ public class DhSectionPos implements INetworkObject
public DhSectionPos getChildByIndex(int child0to3) throws IllegalArgumentException, IllegalStateException
{
if (child0to3 < 0 || child0to3 > 3)
+ {
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.detailLevel + 1), BitShiftUtil.half(this.x), BitShiftUtil.half(this.z)); }
+
+
+
+
+ public DhSectionPos getAdjacentPos(EDhDirection dir)
+ {
+ return new DhSectionPos(this.detailLevel,
+ this.x + dir.getNormal().x,
+ this.z + dir.getNormal().z);
+ }
+
+ public DhLodPos getSectionBBoxPos() { return new DhLodPos(this.detailLevel, this.x, this.z); }
+
+
+
+ //=============//
+ // comparisons //
+ //=============//
+
+ public boolean overlapsExactly(DhSectionPos other)
+ {
+ // original logic from DhLodPos
+ if (this.equals(other))
+ {
+ return true;
+ }
+ else if (this.detailLevel == other.detailLevel)
+ {
+ return false;
+ }
+ else if (this.detailLevel > other.detailLevel)
+ {
+ return this.equals(other.convertNewToDetailLevel(this.detailLevel));
+ }
+ else
+ {
+ return other.equals(this.convertNewToDetailLevel(other.detailLevel));
+ }
+ }
+
+ public boolean contains(DhSectionPos otherPos)
+ {
+ DhBlockPos2D thisMinBlockPos = this.getMinCornerLodPos(LodUtil.BLOCK_DETAIL_LEVEL).getCornerBlockPos();
+ DhBlockPos2D otherCornerBlockPos = otherPos.getMinCornerLodPos(LodUtil.BLOCK_DETAIL_LEVEL).getCornerBlockPos();
+
+ int thisBlockWidth = this.getBlockWidth() - 1; // minus 1 to account for zero based positional indexing
+ DhBlockPos2D thisMaxBlockPos = new DhBlockPos2D(thisMinBlockPos.x + thisBlockWidth, thisMinBlockPos.z + thisBlockWidth);
+
+ return thisMinBlockPos.x <= otherCornerBlockPos.x && otherCornerBlockPos.x <= thisMaxBlockPos.x &&
+ thisMinBlockPos.z <= otherCornerBlockPos.z && otherCornerBlockPos.z <= thisMaxBlockPos.z;
+ }
+
+
+
+ //===========//
+ // iterators //
+ //===========//
/** Applies the given consumer to all 4 of this position's children. */
public void forEachChild(Consumer callback)
@@ -206,46 +321,26 @@ public class DhSectionPos implements INetworkObject
/** Applies the given consumer to all children of the position at the given section detail level. */
public void forEachChildAtLevel(byte sectionDetailLevel, Consumer callback)
{
- if (sectionDetailLevel == this.sectionDetailLevel)
+ if (sectionDetailLevel == this.detailLevel)
{
callback.accept(this);
return;
}
+
for (int i = 0; i < 4; i++)
{
this.getChildByIndex(i).forEachChildAtLevel(sectionDetailLevel, callback);
}
}
- public DhSectionPos getParentPos() { return new DhSectionPos((byte) (this.sectionDetailLevel + 1), BitShiftUtil.half(this.sectionX), BitShiftUtil.half(this.sectionZ)); }
- public DhSectionPos getAdjacentPos(EDhDirection dir)
- {
- return new DhSectionPos(this.sectionDetailLevel,
- this.sectionX + dir.getNormal().x,
- this.sectionZ + dir.getNormal().z);
- }
- public DhLodPos getSectionBBoxPos() { return new DhLodPos(this.sectionDetailLevel, this.sectionX, this.sectionZ); }
-
- /** NOTE: This does not consider yOffset! */
- public boolean overlaps(DhSectionPos other) { return this.getSectionBBoxPos().overlapsExactly(other.getSectionBBoxPos()); }
-
- /** NOTE: This does not consider yOffset! */
- public boolean contains(DhSectionPos otherPos)
- {
- DhBlockPos2D thisMinBlockPos = this.getCorner(LodUtil.BLOCK_DETAIL_LEVEL).getCornerBlockPos();
- DhBlockPos2D otherCornerBlockPos = otherPos.getCorner(LodUtil.BLOCK_DETAIL_LEVEL).getCornerBlockPos();
-
- int thisBlockWidth = this.getWidth().toBlockWidth() - 1; // minus 1 to account for zero based positional indexing
- DhBlockPos2D thisMaxBlockPos = new DhBlockPos2D(thisMinBlockPos.x + thisBlockWidth, thisMinBlockPos.z + thisBlockWidth);
-
- return thisMinBlockPos.x <= otherCornerBlockPos.x && otherCornerBlockPos.x <= thisMaxBlockPos.x &&
- thisMinBlockPos.z <= otherCornerBlockPos.z && otherCornerBlockPos.z <= thisMaxBlockPos.z;
- }
+ //===============//
+ // serialization //
+ //===============//
/** 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)
@@ -257,42 +352,112 @@ public class DhSectionPos implements INetworkObject
}
+
+
+ //===========//
+ // overrides //
+ //===========//
+
@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)
{
if (this == obj)
+ {
return true;
- if (obj == null || this.getClass() != obj.getClass())
+ }
+ if (obj == null || obj.getClass() != DhSectionPos.class)
+ {
return false;
+ }
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.
+ * 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; }
+
+ }
+
@Override
public void encode(ByteBuf out) {
- out.writeByte(this.sectionDetailLevel);
- out.writeInt(this.sectionX);
- out.writeInt(this.sectionZ);
+ out.writeByte(this.detailLevel);
+ out.writeInt(this.x);
+ out.writeInt(this.z);
}
@Override
public void decode(ByteBuf in) {
- this.sectionDetailLevel = in.readByte();
- this.sectionX = in.readInt();
- this.sectionZ = in.readInt();
+ this.detailLevel = in.readByte();
+ this.x = in.readInt();
+ this.z = in.readInt();
}
}
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/LodQuadTree.java b/core/src/main/java/com/seibel/distanthorizons/core/render/LodQuadTree.java
index 0a81cc761..53dee52a2 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/render/LodQuadTree.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/render/LodQuadTree.java
@@ -143,7 +143,7 @@ public class LodQuadTree extends QuadTree 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 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 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
@@ -320,7 +320,7 @@ public class LodQuadTree extends QuadTree implements AutoClose
* @param sectionPos section position
* @return detail level of this section pos
*/
- public byte calculateExpectedDetailLevel(DhBlockPos2D playerPos, DhSectionPos sectionPos) { return this.getDetailLevelFromDistance(playerPos.dist(sectionPos.getCenter().getCenterBlockPos())); }
+ public byte calculateExpectedDetailLevel(DhBlockPos2D playerPos, DhSectionPos sectionPos) { return this.getDetailLevelFromDistance(playerPos.dist(sectionPos.getCenterBlockPosX(), sectionPos.getCenterBlockPosZ())); }
private byte getDetailLevelFromDistance(double distance)
{
// special case, never drop the quality
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java b/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java
index 18e06d240..eaa32502e 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java
@@ -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(
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java
index db50ae3fa..502537ce2 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java
@@ -118,13 +118,13 @@ public class RenderBufferHandler
}
}
- Pos2D cPos = lodQuadTree.getCenterBlockPos().toPos2D();
+ Pos2D cPos = this.lodQuadTree.getCenterBlockPos().toPos2D();
// Now that we have the axis directions, we can sort the render list
Comparator farToNearComparator = (loadedBufferA, loadedBufferB) ->
{
- Pos2D aPos = loadedBufferA.pos.getCenter().getCenterBlockPos().toPos2D();
- Pos2D bPos = loadedBufferB.pos.getCenter().getCenterBlockPos().toPos2D();
+ Pos2D aPos = loadedBufferA.pos.getCenterBlockPos().toPos2D();
+ Pos2D bPos = loadedBufferB.pos.getCenterBlockPos().toPos2D();
if (true)
{
int aManhattanDistance = aPos.manhattanDist(cPos);
@@ -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
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLProxy.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLProxy.java
index da4d5c7fe..2403a71a3 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLProxy.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLProxy.java
@@ -21,6 +21,7 @@ package com.seibel.distanthorizons.core.render.glObject;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.seibel.distanthorizons.api.enums.config.EGLErrorHandlingMode;
+import com.seibel.distanthorizons.api.enums.config.EGlProfileMode;
import com.seibel.distanthorizons.api.enums.config.EGpuUploadMethod;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
@@ -160,10 +161,27 @@ public class GLProxy
// DO NOT comment out the following 2 lines: they are needed for mac and creating forward compatible contexts
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 3);
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 2);
- GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_FORWARD_COMPAT, GLFW.GLFW_TRUE);
- GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_PROFILE, GLFW.GLFW_OPENGL_CORE_PROFILE);
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_DEBUG_CONTEXT, GLFW.GLFW_TRUE);
+ // TODO remove me
+ boolean useForwardCompatibility = Config.Client.Advanced.Debugging.glForwardCompatibilityMode.get();
+ GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_FORWARD_COMPAT, useForwardCompatibility ? GLFW.GLFW_TRUE : GLFW.GLFW_FALSE);
+
+ // TODO remove me
+ EGlProfileMode profileMode = Config.Client.Advanced.Debugging.glProfileMode.get();
+ if (profileMode == EGlProfileMode.CORE)
+ {
+ GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_PROFILE, GLFW.GLFW_OPENGL_CORE_PROFILE);
+ }
+ else if (profileMode == EGlProfileMode.ANY)
+ {
+ GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_PROFILE, GLFW.GLFW_OPENGL_ANY_PROFILE);
+ }
+ else
+ {
+ GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_PROFILE, GLFW.GLFW_OPENGL_COMPAT_PROFILE);
+ }
+
// create the Lod Builder context
lodBuilderGlContext = GLFW.glfwCreateWindow(64, 48, "LOD Builder Window", 0L, minecraftGlContext);
if (lodBuilderGlContext == 0)
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/MetaFileScanUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/MetaFileScanUtil.java
index 3b17c65f5..726c92d0a 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/util/MetaFileScanUtil.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/util/MetaFileScanUtil.java
@@ -25,7 +25,7 @@ import com.seibel.distanthorizons.core.file.fullDatafile.FullDataMetaFile;
import com.seibel.distanthorizons.core.file.fullDatafile.IFullDataSourceProvider;
import com.seibel.distanthorizons.core.file.metaData.AbstractMetaDataContainerFile;
import com.seibel.distanthorizons.core.file.renderfile.ILodRenderSourceProvider;
-import com.seibel.distanthorizons.core.file.renderfile.RenderMetaDataFile;
+import com.seibel.distanthorizons.core.file.renderfile.RenderDataMetaFile;
import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.pos.DhSectionPos;
@@ -81,7 +81,7 @@ public class MetaFileScanUtil
try (Stream pathStream = Files.walk(saveStructure.getRenderCacheFolder(levelWrapper).toPath(), MAX_SCAN_DEPTH))
{
List files = pathStream.filter(
- path -> path.toFile().getName().endsWith(RenderMetaDataFile.FILE_SUFFIX) && path.toFile().isFile()
+ path -> path.toFile().getName().endsWith(RenderDataMetaFile.FILE_SUFFIX) && path.toFile().isFile()
).map(Path::toFile).collect(Collectors.toList());
LOGGER.info("Found " + files.size() + " render cache files for " + levelWrapper + " in " + saveStructure);
renderSourceProvider.addScannedFiles(files);
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/QuadNode.java b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/QuadNode.java
index e2b585c40..a8794be82 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/QuadNode.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/QuadNode.java
@@ -179,21 +179,21 @@ public class QuadNode
if (!this.sectionPos.contains(inputSectionPos))
{
- LOGGER.error((replaceValue ? "set " : "get ") + inputSectionPos + " center block: " + inputSectionPos.getCenter().getCornerBlockPos() + ", this pos: " + this.sectionPos + " this center block: " + this.sectionPos.getCenter().getCornerBlockPos());
- throw new IllegalArgumentException("Input section pos " + inputSectionPos + " outside of this quadNode's pos: " + this.sectionPos + ", this node's blockPos: " + this.sectionPos.convertToDetailLevel(LodUtil.BLOCK_DETAIL_LEVEL) + " block width: " + this.sectionPos.getWidth().toBlockWidth() + " input detail level: " + inputSectionPos.convertToDetailLevel(LodUtil.BLOCK_DETAIL_LEVEL) + " width: " + inputSectionPos.getWidth().toBlockWidth());
+ LOGGER.error((replaceValue ? "set " : "get ") + inputSectionPos + " center block: " + inputSectionPos.getCenterBlockPos() + ", this pos: " + this.sectionPos + " this center block: " + this.sectionPos.getCenterBlockPos());
+ 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
// get/set logic
- if (inputSectionPos.sectionDetailLevel == this.sectionPos.sectionDetailLevel)
+ if (inputSectionPos.getDetailLevel() == this.sectionPos.getDetailLevel())
{
// this node is the requested position
if (replaceValue)
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/QuadTree.java b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/QuadTree.java
index 2014e4039..9dcaf72e7 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/QuadTree.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/QuadTree.java
@@ -119,51 +119,51 @@ public class QuadTree
/** @param runBoundaryChecks should only ever be set to true internally for removing out of bound nodes */
protected final QuadNode getOrSetNode(DhSectionPos pos, boolean setNewValue, T newValue, boolean runBoundaryChecks) throws IndexOutOfBoundsException
{
- if (!runBoundaryChecks || this.isSectionPosInBounds(pos))
- {
- DhSectionPos rootPos = pos.convertToDetailLevel(this.treeMinDetailLevel);
- int ringListPosX = rootPos.sectionX;
- int ringListPosZ = rootPos.sectionZ;
-
- QuadNode topQuadNode = this.topRingList.get(ringListPosX, ringListPosZ);
- if (topQuadNode == null)
- {
- if (!setNewValue)
- {
- return null;
- }
-
- topQuadNode = new QuadNode(rootPos, this.treeMaxDetailLevel);
- boolean successfullyAdded = this.topRingList.set(ringListPosX, ringListPosZ, topQuadNode);
- LodUtil.assertTrue(successfullyAdded, "Failed to add top quadTree node at position: " + rootPos);
- }
-
- if (!topQuadNode.sectionPos.contains(pos))
- {
- LodUtil.assertNotReach("failed to get a root node that contains the input position: " + pos + " root node pos: " + topQuadNode.sectionPos);
- }
-
-
- QuadNode returnNode = topQuadNode.getNode(pos);
- if (setNewValue)
- {
- topQuadNode.setValue(pos, newValue);
- }
- return returnNode;
- }
- else
+ if (runBoundaryChecks && !this.isSectionPosInBounds(pos))
{
int radius = this.diameterInBlocks() / 2;
DhBlockPos2D minPos = this.getCenterBlockPos().add(new DhBlockPos2D(-radius, -radius));
DhBlockPos2D maxPos = this.getCenterBlockPos().add(new DhBlockPos2D(radius, radius));
- throw new IndexOutOfBoundsException("QuadTree GetOrSet failed. Position out of bounds, min pos: " + minPos + ", max pos: " + maxPos + ", min detail level: " + this.treeMaxDetailLevel + ", max detail level: " + this.treeMinDetailLevel + ". Given Position: " + pos + " = block pos: " + pos.convertToDetailLevel(LodUtil.BLOCK_DETAIL_LEVEL));
+ throw new IndexOutOfBoundsException("QuadTree GetOrSet failed. Position out of bounds, min pos: " + minPos + ", max pos: " + maxPos + ", min detail level: " + this.treeMaxDetailLevel + ", max detail level: " + this.treeMinDetailLevel + ". Given Position: " + pos + " = block pos: " + pos.convertNewToDetailLevel(LodUtil.BLOCK_DETAIL_LEVEL));
}
+
+
+
+ DhSectionPos rootPos = pos.convertNewToDetailLevel(this.treeMinDetailLevel);
+ int ringListPosX = rootPos.getX();
+ int ringListPosZ = rootPos.getZ();
+
+ QuadNode topQuadNode = this.topRingList.get(ringListPosX, ringListPosZ);
+ if (topQuadNode == null)
+ {
+ if (!setNewValue)
+ {
+ return null;
+ }
+
+ topQuadNode = new QuadNode(rootPos, this.treeMaxDetailLevel);
+ boolean successfullyAdded = this.topRingList.set(ringListPosX, ringListPosZ, topQuadNode);
+ LodUtil.assertTrue(successfullyAdded, "Failed to add top quadTree node at position: " + rootPos);
+ }
+
+ if (!topQuadNode.sectionPos.contains(pos))
+ {
+ LodUtil.assertNotReach("failed to get a root node that contains the input position: " + pos + " root node pos: " + topQuadNode.sectionPos);
+ }
+
+
+ QuadNode returnNode = topQuadNode.getNode(pos);
+ if (setNewValue)
+ {
+ topQuadNode.setValue(pos, newValue);
+ }
+ return returnNode;
}
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;
@@ -174,9 +174,9 @@ public class QuadTree
DhBlockPos2D treeBlockCorner = this.centerBlockPos.add(new DhBlockPos2D(-this.widthInBlocks / 2, -this.widthInBlocks / 2));
DhLodPos treeCornerPos = new DhLodPos((byte) 0, treeBlockCorner.x, treeBlockCorner.z);
- DhSectionPos inputSectionCorner = testPos.convertToDetailLevel((byte) 0);
- DhLodPos inputCornerPos = new DhLodPos((byte) 0, inputSectionCorner.sectionX, inputSectionCorner.sectionZ);
- int inputBlockWidth = BitShiftUtil.powerOfTwo(testPos.sectionDetailLevel);
+ DhSectionPos inputSectionCorner = testPos.convertNewToDetailLevel((byte) 0);
+ DhLodPos inputCornerPos = new DhLodPos((byte) 0, inputSectionCorner.getX(), inputSectionCorner.getZ());
+ int inputBlockWidth = BitShiftUtil.powerOfTwo(testPos.getDetailLevel());
return DoSquaresOverlap(treeCornerPos, this.widthInBlocks, inputCornerPos, inputBlockWidth);
}
@@ -404,6 +404,7 @@ public class QuadTree
{
if (node != null || includeNullNodes)
{
+ // TODO can these DhSectionPos be pooled?
DhSectionPos rootPos = new DhSectionPos(QuadTree.this.treeMinDetailLevel, pos2D.x, pos2D.y);
if (QuadTree.this.isSectionPosInBounds(rootPos))
{
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/iterators/QuadNodeChildIndexIterator.java b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/iterators/QuadNodeChildIndexIterator.java
index 77dda14d1..639f8e40a 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/iterators/QuadNodeChildIndexIterator.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/iterators/QuadNodeChildIndexIterator.java
@@ -36,7 +36,7 @@ public class QuadNodeChildIndexIterator implements Iterator
public QuadNodeChildIndexIterator(QuadNode 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++)
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/iterators/QuadTreeNodeIterator.java b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/iterators/QuadTreeNodeIterator.java
index b36b4167f..13745870e 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/iterators/QuadTreeNodeIterator.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/iterators/QuadTreeNodeIterator.java
@@ -46,7 +46,7 @@ public class QuadTreeNodeIterator implements Iterator>
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)
diff --git a/core/src/main/resources/assets/distanthorizons/lang/en_us.json b/core/src/main/resources/assets/distanthorizons/lang/en_us.json
index e1c78d4ea..8d8f428a7 100644
--- a/core/src/main/resources/assets/distanthorizons/lang/en_us.json
+++ b/core/src/main/resources/assets/distanthorizons/lang/en_us.json
@@ -429,6 +429,14 @@
"OpenGL Error Handling Mode",
"distanthorizons.config.client.advanced.debugging.glErrorHandlingMode.@tooltip":
"Defines how OpenGL errors are handled. \nMay incorrectly catch OpenGL errors thrown by other mods.",
+ "distanthorizons.config.client.advanced.debugging.glProfileMode":
+ "OpenGL Profile Mode",
+ "distanthorizons.config.client.advanced.debugging.glProfileMode.@tooltip":
+ "Requires rebooting Minecraft to apply.",
+ "distanthorizons.config.client.advanced.debugging.glForwardCompatibilityMode":
+ "OpenGL Forward Compatibility Mode",
+ "distanthorizons.config.client.advanced.debugging.glForwardCompatibilityMode.@tooltip":
+ "Requires rebooting Minecraft to apply.",
"distanthorizons.config.client.advanced.buffers":
@@ -736,6 +744,13 @@
"distanthorizons.config.enum.EGLErrorHandlingMode.LOG_THROW":
"Log-Throw",
+ "distanthorizons.config.enum.EGlProfileMode.CORE":
+ "Core",
+ "distanthorizons.config.enum.EGlProfileMode.COMPAT":
+ "Compat",
+ "distanthorizons.config.enum.EGlProfileMode.ANY":
+ "Any",
+
"distanthorizons.config.enum.ELoggerMode.DISABLED":
"Disabled",
"distanthorizons.config.enum.ELoggerMode.LOG_ALL_TO_FILE":
diff --git a/core/src/test/java/tests/DhSectionPosTest.java b/core/src/test/java/tests/DhSectionPosTest.java
index 6728db56e..ff2419d1b 100644
--- a/core/src/test/java/tests/DhSectionPosTest.java
+++ b/core/src/test/java/tests/DhSectionPosTest.java
@@ -19,8 +19,7 @@
package tests;
-import com.seibel.distanthorizons.core.pos.DhLodPos;
-import com.seibel.distanthorizons.core.pos.DhSectionPos;
+import com.seibel.distanthorizons.core.pos.*;
import org.junit.Assert;
import org.junit.Test;
@@ -84,22 +83,22 @@ public class DhSectionPosTest
public void ParentPosTest()
{
DhSectionPos leaf = new DhSectionPos((byte) 0, 0, 0);
- DhSectionPos convert = leaf.convertToDetailLevel((byte) 1);
+ DhSectionPos convert = leaf.convertNewToDetailLevel((byte) 1);
DhSectionPos parent = leaf.getParentPos();
Assert.assertEquals("get parent at 0,0 fail", convert, parent);
leaf = new DhSectionPos((byte) 0, 1, 1);
- convert = leaf.convertToDetailLevel((byte) 1);
+ convert = leaf.convertNewToDetailLevel((byte) 1);
parent = leaf.getParentPos();
Assert.assertEquals("get parent at 1,1 fail", convert, parent);
leaf = new DhSectionPos((byte) 1, 2, 2);
- convert = leaf.convertToDetailLevel((byte) 2);
+ convert = leaf.convertNewToDetailLevel((byte) 2);
parent = leaf.getParentPos();
Assert.assertEquals("parent upscale fail", convert, parent);
- convert = leaf.convertToDetailLevel((byte) 0);
+ convert = leaf.convertNewToDetailLevel((byte) 0);
DhSectionPos childIndex = leaf.getChildByIndex(0);
Assert.assertEquals("child detail fail", convert, childIndex);
@@ -131,17 +130,17 @@ public class DhSectionPosTest
public void GetCenterTest()
{
DhSectionPos node = new DhSectionPos((byte) 1, 2303, 0);
- DhLodPos centerNode = node.getCenter();
- DhLodPos expectedCenterNode = new DhLodPos((byte) 0, 4606, 0);
- Assert.assertEquals("", expectedCenterNode, centerNode);
+ DhBlockPos2D centerBlockPos = node.getCenterBlockPos();
+ DhBlockPos2D expectedCenterNode = new DhBlockPos2D(4606, 0);
+ Assert.assertEquals("", expectedCenterNode, centerBlockPos);
node = new DhSectionPos((byte) 10, 0, 0); // 1024 blocks wide
- centerNode = node.getCenter();
- expectedCenterNode = new DhLodPos((byte) 0, 1024 / 2, 1024 / 2);
- Assert.assertEquals("", expectedCenterNode, centerNode);
-
+ centerBlockPos = node.getCenterBlockPos();
+ expectedCenterNode = new DhBlockPos2D(1024 / 2, 1024 / 2);
+ Assert.assertEquals("", expectedCenterNode, centerBlockPos);
+
}
@Test
@@ -151,12 +150,213 @@ public class DhSectionPosTest
DhSectionPos inputPos = new DhSectionPos((byte) 0, 4606, 0); // width 1 block
Assert.assertTrue(parentNode.contains(inputPos));
- DhLodPos parentCenter = parentNode.getCenter();
- DhLodPos inputCenter = inputPos.getCenter();
+ DhBlockPos2D parentCenter = parentNode.getCenterBlockPos();
+ DhBlockPos2D inputCenter = inputPos.getCenterBlockPos();
- Assert.assertEquals(new DhLodPos((byte) 0, 4606, 2), parentCenter);
- Assert.assertEquals(new DhLodPos((byte) 0, 4606, 0), inputCenter);
+ Assert.assertEquals(new DhBlockPos2D(4606, 2), parentCenter);
+ Assert.assertEquals(new DhBlockPos2D(4606, 0), inputCenter);
}
+ @Test
+ public void CreateFromBlockPos()
+ {
+ // origin pos //
+
+ DhBlockPos originBlockPos = new DhBlockPos(0, 0, 0);
+ DhSectionPos originSectionPos = new DhSectionPos(originBlockPos);
+ Assert.assertEquals(new DhSectionPos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originSectionPos);
+
+
+ // offset pos //
+
+ DhBlockPos offsetBlockPos = new DhBlockPos(1000, 0, 42000);
+ DhSectionPos offsetSectionPos = new DhSectionPos(offsetBlockPos);
+ Assert.assertEquals(new DhSectionPos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 15, 656), offsetSectionPos);
+
+ offsetBlockPos = new DhBlockPos(-987654, 0, 46);
+ offsetSectionPos = new DhSectionPos(offsetBlockPos);
+ Assert.assertEquals(new DhSectionPos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -15433, 0), offsetSectionPos);
+
+ }
+
+ @Test
+ public void CreateFromBlockPos2D()
+ {
+ // origin pos //
+
+ DhBlockPos2D originBlockPos = new DhBlockPos2D(0, 0);
+ DhSectionPos originSectionPos = new DhSectionPos(originBlockPos);
+ Assert.assertEquals(new DhSectionPos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originSectionPos);
+
+
+ // offset pos //
+
+ DhBlockPos2D offsetBlockPos = new DhBlockPos2D(1000, 42000);
+ DhSectionPos offsetSectionPos = new DhSectionPos(offsetBlockPos);
+ Assert.assertEquals(new DhSectionPos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 15, 656), offsetSectionPos);
+
+ offsetBlockPos = new DhBlockPos2D(-987654, 46);
+ offsetSectionPos = new DhSectionPos(offsetBlockPos);
+ Assert.assertEquals(new DhSectionPos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -15433, 0), offsetSectionPos);
+
+ }
+
+ @Test
+ public void CreateFromChunkPos()
+ {
+ // origin pos //
+
+ DhChunkPos originChunkPos = new DhChunkPos(0,0);
+ DhSectionPos originSectionPos = new DhSectionPos(originChunkPos);
+ Assert.assertEquals(new DhSectionPos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, 0, 0), originSectionPos);
+
+
+ // offset pos //
+
+ DhChunkPos offsetChunkPos = new DhChunkPos(1000, 42000);
+ DhSectionPos offsetSectionPos = new DhSectionPos(offsetChunkPos);
+ Assert.assertEquals(new DhSectionPos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, 15, 656), offsetSectionPos);
+
+ offsetChunkPos = new DhChunkPos(-987654, 46);
+ offsetSectionPos = new DhSectionPos(offsetChunkPos);
+ Assert.assertEquals(new DhSectionPos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, -15433, 0), offsetSectionPos);
+
+ }
+
+ @Test
+ public void ConvertToDetailLevel()
+ {
+ // origin pos //
+
+ DhSectionPos originSectionPos = new DhSectionPos((byte) 0,0,0);
+
+ originSectionPos = originSectionPos.convertNewToDetailLevel((byte) 1);
+ Assert.assertEquals(new DhSectionPos((byte) 1, 0, 0), originSectionPos);
+
+ originSectionPos = originSectionPos.convertNewToDetailLevel(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL);
+ Assert.assertEquals(new DhSectionPos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originSectionPos);
+
+ originSectionPos = originSectionPos.convertNewToDetailLevel(DhSectionPos.SECTION_REGION_DETAIL_LEVEL);
+ Assert.assertEquals(new DhSectionPos(DhSectionPos.SECTION_REGION_DETAIL_LEVEL, 0, 0), originSectionPos);
+
+
+ // offset pos //
+
+ DhSectionPos sectionPos = new DhSectionPos((byte) 0,-10000,5000);
+
+ sectionPos = sectionPos.convertNewToDetailLevel((byte) 1);
+ Assert.assertEquals(new DhSectionPos((byte) 1, -5000, 2500), sectionPos);
+
+ sectionPos = sectionPos.convertNewToDetailLevel(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL);
+ Assert.assertEquals(new DhSectionPos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -157, 78), sectionPos);
+
+ sectionPos = sectionPos.convertNewToDetailLevel(DhSectionPos.SECTION_REGION_DETAIL_LEVEL);
+ Assert.assertEquals(new DhSectionPos(DhSectionPos.SECTION_REGION_DETAIL_LEVEL, -1, 0), sectionPos);
+
+ }
+
+ @Test
+ public void GetOffsetWidth()
+ {
+ DhSectionPos originSectionPos = new DhSectionPos((byte) 0,0,0);
+ DhSectionPos sectionPos = new DhSectionPos((byte) 0,-10000,5000);
+
+
+
+ // 1 -> 0
+ byte returnDetailLevel = 0;
+ originSectionPos = originSectionPos.convertNewToDetailLevel((byte) 1);
+ Assert.assertEquals(2, originSectionPos.getWidthCountForLowerDetailedSection(returnDetailLevel));
+
+ sectionPos = sectionPos.convertNewToDetailLevel((byte) 1);
+ Assert.assertEquals(2, sectionPos.getWidthCountForLowerDetailedSection(returnDetailLevel));
+
+
+ // 2 -> 1
+ returnDetailLevel = 1;
+ originSectionPos = originSectionPos.convertNewToDetailLevel((byte) 2);
+ Assert.assertEquals(2, originSectionPos.getWidthCountForLowerDetailedSection(returnDetailLevel));
+
+ sectionPos = sectionPos.convertNewToDetailLevel((byte) 2);
+ Assert.assertEquals(2, sectionPos.getWidthCountForLowerDetailedSection(returnDetailLevel));
+
+
+ // Block -> 0
+ returnDetailLevel = 0;
+ originSectionPos = originSectionPos.convertNewToDetailLevel(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL);
+ Assert.assertEquals(64, originSectionPos.getWidthCountForLowerDetailedSection(returnDetailLevel));
+
+ sectionPos = sectionPos.convertNewToDetailLevel(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL);
+ Assert.assertEquals(64, sectionPos.getWidthCountForLowerDetailedSection(returnDetailLevel));
+
+
+ // Region -> 3
+ returnDetailLevel = 3;
+ originSectionPos = originSectionPos.convertNewToDetailLevel(DhSectionPos.SECTION_REGION_DETAIL_LEVEL);
+ Assert.assertEquals(4096, originSectionPos.getWidthCountForLowerDetailedSection(returnDetailLevel));
+
+ sectionPos = sectionPos.convertNewToDetailLevel(DhSectionPos.SECTION_REGION_DETAIL_LEVEL);
+ Assert.assertEquals(4096, sectionPos.getWidthCountForLowerDetailedSection(returnDetailLevel));
+
+ }
+
+ @Test
+ public void GetBlockWidth()
+ {
+ DhSectionPos originSectionPos = new DhSectionPos((byte) 0,0,0);
+ DhSectionPos sectionPos = new DhSectionPos((byte) 0,-10000,5000);
+
+
+ Assert.assertEquals(1, originSectionPos.getBlockWidth());
+ Assert.assertEquals(1, sectionPos.getBlockWidth());
+
+ originSectionPos = originSectionPos.convertNewToDetailLevel((byte) 1);
+ Assert.assertEquals(2, originSectionPos.getBlockWidth());
+ sectionPos = sectionPos.convertNewToDetailLevel((byte) 1);
+ Assert.assertEquals(2, sectionPos.getBlockWidth());
+
+ originSectionPos = originSectionPos.convertNewToDetailLevel(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL);
+ Assert.assertEquals(64, originSectionPos.getBlockWidth());
+ sectionPos = sectionPos.convertNewToDetailLevel(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL);
+ Assert.assertEquals(64, sectionPos.getBlockWidth());
+
+ originSectionPos = originSectionPos.convertNewToDetailLevel(DhSectionPos.SECTION_REGION_DETAIL_LEVEL);
+ Assert.assertEquals(32768, originSectionPos.getBlockWidth());
+ sectionPos = sectionPos.convertNewToDetailLevel(DhSectionPos.SECTION_REGION_DETAIL_LEVEL);
+ Assert.assertEquals(32768, sectionPos.getBlockWidth());
+
+ }
+
+ @Test
+ public void GetCenterBlockPos()
+ {
+ DhSectionPos originSectionPos = new DhSectionPos((byte) 0,0,0);
+ DhSectionPos sectionPos = new DhSectionPos((byte) 0,-10000,5000);
+
+
+ Assert.assertEquals(new DhBlockPos2D(0, 0), originSectionPos.getCenterBlockPos());
+ Assert.assertEquals(new DhBlockPos2D(-10000, 5000), sectionPos.getCenterBlockPos());
+
+
+ originSectionPos = originSectionPos.convertNewToDetailLevel((byte) 1);
+ Assert.assertEquals(new DhBlockPos2D(0, 0), originSectionPos.getCenterBlockPos());
+ sectionPos = sectionPos.convertNewToDetailLevel((byte) 1);
+ Assert.assertEquals(new DhBlockPos2D(-10000, 5000), sectionPos.getCenterBlockPos());
+
+
+ originSectionPos = originSectionPos.convertNewToDetailLevel(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL);
+ Assert.assertEquals(new DhBlockPos2D(32, 32), originSectionPos.getCenterBlockPos());
+ sectionPos = sectionPos.convertNewToDetailLevel(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL);
+ Assert.assertEquals(new DhBlockPos2D(-10016, 5024), sectionPos.getCenterBlockPos());
+
+
+ originSectionPos = originSectionPos.convertNewToDetailLevel(DhSectionPos.SECTION_REGION_DETAIL_LEVEL);
+ Assert.assertEquals(new DhBlockPos2D(16384, 16384), originSectionPos.getCenterBlockPos());
+ sectionPos = sectionPos.convertNewToDetailLevel(DhSectionPos.SECTION_REGION_DETAIL_LEVEL);
+ Assert.assertEquals(new DhBlockPos2D(-16384, 16384), sectionPos.getCenterBlockPos());
+
+ }
+
+
}
diff --git a/core/src/test/java/tests/QuadTreeTest.java b/core/src/test/java/tests/QuadTreeTest.java
index ea79698af..722dfbaec 100644
--- a/core/src/test/java/tests/QuadTreeTest.java
+++ b/core/src/test/java/tests/QuadTreeTest.java
@@ -649,7 +649,7 @@ public class QuadTreeTest
DhSectionPos sectionPos = directChildIterator.next();
QuadNode 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);
}
}