diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java index 5d8ea494a..d08989ad8 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java @@ -31,7 +31,7 @@ import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSour import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.pos.DhLodPos; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.util.FullDataPointUtil; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.RayCastUtil; @@ -202,10 +202,10 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo // get the detail levels for this request byte requestedDetailLevel = requestedColumnPos.detailLevel; - byte sectionDetailLevel = (byte) (requestedDetailLevel + OldDhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL); + byte sectionDetailLevel = (byte) (requestedDetailLevel + DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL); // get the positions for this request - OldDhSectionPos sectionPos = requestedColumnPos.getSectionPosWithSectionDetailLevel(sectionDetailLevel); + long sectionPos = requestedColumnPos.getSectionPosWithSectionDetailLevel(sectionDetailLevel); DhLodPos relativePos = requestedColumnPos.getDhSectionRelativePositionForDetailLevel(); @@ -215,7 +215,7 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo FullDataSourceV2 dataSource = level.getFullDataProvider().getAsync(sectionPos).get(); if (dataSource == null) { - return DhApiResult.createFail("Unable to find/generate any data at the " + OldDhSectionPos.class.getSimpleName() + " [" + sectionPos + "]."); + return DhApiResult.createFail("Unable to find/generate any data at the " + DhSectionPos.class.getSimpleName() + " [" + DhSectionPos.toString(sectionPos) + "]."); } else { 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 739482c8b..341cb9f3f 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 @@ -30,7 +30,7 @@ import com.seibel.distanthorizons.core.config.types.*; import com.seibel.distanthorizons.core.config.types.enums.*; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper; import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.coreapi.util.StringUtil; @@ -1208,7 +1208,7 @@ public class Config .addListener(DebugColumnConfigEventHandler.INSTANCE) .build(); public static ConfigEntry columnBuilderDebugDetailLevel = new ConfigEntry.Builder() - .set((int) OldDhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL) + .set((int) DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL) .setAppearance(EConfigEntryAppearance.ONLY_IN_GUI) .addListener(DebugColumnConfigEventHandler.INSTANCE) .build(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/FullDataPointIdMap.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/FullDataPointIdMap.java index 7eb637b05..4307b3fa2 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/FullDataPointIdMap.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/FullDataPointIdMap.java @@ -20,7 +20,7 @@ package com.seibel.distanthorizons.core.dataObjects.fullData; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.objects.DataCorruptedException; import com.seibel.distanthorizons.core.util.objects.dataStreams.DhDataInputStream; @@ -67,7 +67,7 @@ public class FullDataPointIdMap private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); /** should only be used for debugging */ - private OldDhSectionPos pos; + private long pos; /** The index should be the same as the Entry's ID */ private final ArrayList entryList = new ArrayList<>(); @@ -79,7 +79,7 @@ public class FullDataPointIdMap // constructor // //=============// - public FullDataPointIdMap(OldDhSectionPos pos) { this.pos = pos; } + public FullDataPointIdMap(long pos) { this.pos = pos; } @@ -123,7 +123,7 @@ public class FullDataPointIdMap public boolean isEmpty() { return this.entryList.isEmpty(); } - public OldDhSectionPos getPos() { return this.pos; } + public long getPos() { return this.pos; } @@ -270,7 +270,7 @@ public class FullDataPointIdMap } /** Should only be used if this map is going to be reused, otherwise bad things will happen. */ - public void clear(OldDhSectionPos pos) + public void clear(long pos) { this.pos = pos; this.entryList.clear(); @@ -321,7 +321,7 @@ public class FullDataPointIdMap } /** Creates a new IdBiomeBlockStateMap from the given UTF formatted stream */ - public static FullDataPointIdMap deserialize(DhDataInputStream inputStream, OldDhSectionPos pos, ILevelWrapper levelWrapper) throws IOException, InterruptedException, DataCorruptedException + public static FullDataPointIdMap deserialize(DhDataInputStream inputStream, long pos, ILevelWrapper levelWrapper) throws IOException, InterruptedException, DataCorruptedException { int entityCount = inputStream.readInt(); if (entityCount < 0) @@ -361,12 +361,10 @@ public class FullDataPointIdMap } } - //LOGGER.trace("deserialized " + pos + " " + newMap.entryList.size() + "-" + entityCount); - if (newMap.size() != entityCount) { // if the mappings are out of sync then the LODs will render incorrectly due to IDs being wrong - LodUtil.assertNotReach("ID maps failed to deserialize for pos: "+pos+", incorrect entity count. Expected count ["+entityCount+"], actual count ["+newMap.size()+"]"); + LodUtil.assertNotReach("ID maps failed to deserialize for pos: ["+DhSectionPos.toString(pos)+"], incorrect entity count. Expected count ["+entityCount+"], actual count ["+newMap.size()+"]"); } return newMap; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/FullDataSourceV1.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/FullDataSourceV1.java index 53625d118..bc82aa94a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/FullDataSourceV1.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/FullDataSourceV1.java @@ -23,7 +23,7 @@ import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiWorldGeneratio import com.seibel.distanthorizons.core.file.IDataSource; import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.sql.dto.FullDataSourceV1DTO; import com.seibel.distanthorizons.core.util.FullDataPointUtil; import com.seibel.distanthorizons.core.util.LodUtil; @@ -51,7 +51,7 @@ public class FullDataSourceV1 implements IDataSource { private static final Logger LOGGER = DhLoggerBuilder.getLogger(); - public static final byte SECTION_SIZE_OFFSET = OldDhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL; + public static final byte SECTION_SIZE_OFFSET = DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL; /** measured in dataPoints */ public static final int WIDTH = BitShiftUtil.powerOfTwo(SECTION_SIZE_OFFSET); @@ -75,7 +75,7 @@ public class FullDataSourceV1 implements IDataSource /** A flattened 2D array (for the X and Z directions) containing an array for the Y direction. */ private final long[][] dataArrays; - private OldDhSectionPos sectionPos; + private long sectionPos; private boolean isEmpty = true; @@ -85,8 +85,8 @@ public class FullDataSourceV1 implements IDataSource // constructors // //==============// - public static FullDataSourceV1 createEmpty(OldDhSectionPos pos) { return new FullDataSourceV1(pos); } - private FullDataSourceV1(OldDhSectionPos sectionPos) + public static FullDataSourceV1 createEmpty(long pos) { return new FullDataSourceV1(pos); } + private FullDataSourceV1(long sectionPos) { this.dataArrays = new long[WIDTH * WIDTH][0]; this.mapping = new FullDataPointIdMap(sectionPos); @@ -111,19 +111,19 @@ public class FullDataSourceV1 implements IDataSource //=====================// @Override - public OldDhSectionPos getKey() { return this.sectionPos; } + public Long getKey() { return this.sectionPos; } @Override - public OldDhSectionPos getPos() { return this.sectionPos; } + public Long getPos() { return this.sectionPos; } - public void resizeDataStructuresForRepopulation(OldDhSectionPos pos) + public void resizeDataStructuresForRepopulation(long pos) { // no data structures need to be changed, only the source's position this.sectionPos = pos; } @Override - public byte getDataDetailLevel() { return (byte) (this.sectionPos.getDetailLevel() - SECTION_SIZE_OFFSET); } + public byte getDataDetailLevel() { return (byte) (DhSectionPos.getDetailLevel(this.sectionPos) - SECTION_SIZE_OFFSET); } public boolean isEmpty() { return this.isEmpty; } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/FullDataSourceV2.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/FullDataSourceV2.java index c61887add..6828629a1 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/FullDataSourceV2.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/FullDataSourceV2.java @@ -28,7 +28,7 @@ import com.seibel.distanthorizons.core.file.DataSourcePool; import com.seibel.distanthorizons.core.file.IDataSource; import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.util.FullDataPointUtil; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.RenderDataPointUtil; @@ -43,7 +43,7 @@ import javax.annotation.Nullable; import java.util.Arrays; /** - * This data source contains every datapoint over its given {@link OldDhSectionPos}.

+ * This data source contains every datapoint over its given {@link DhSectionPos}.

* * @see FullDataPointUtil * @see FullDataSourceV1 @@ -71,9 +71,9 @@ public class FullDataSourceV2 implements IDataSource private int cachedHashCode = 0; - private OldDhSectionPos pos; + private long pos; @Override - public OldDhSectionPos getKey() { return this.pos; } + public Long getKey() { return this.pos; } public final FullDataPointIdMap mapping; @@ -112,8 +112,8 @@ public class FullDataSourceV2 implements IDataSource // constructors // //==============// - public static FullDataSourceV2 createEmpty(OldDhSectionPos pos) { return new FullDataSourceV2(pos); } - private FullDataSourceV2(OldDhSectionPos pos) + public static FullDataSourceV2 createEmpty(long pos) { return new FullDataSourceV2(pos); } + private FullDataSourceV2(long pos) { this.pos = pos; this.dataPoints = new LongArrayList[WIDTH * WIDTH]; @@ -126,8 +126,8 @@ public class FullDataSourceV2 implements IDataSource this.columnWorldCompressionMode = new byte[WIDTH * WIDTH]; } - public static FullDataSourceV2 createWithData(OldDhSectionPos pos, FullDataPointIdMap mapping, LongArrayList[] data, byte[] columnGenerationStep, byte[] columnWorldCompressionMode) { return new FullDataSourceV2(pos, mapping, data, columnGenerationStep, columnWorldCompressionMode); } - private FullDataSourceV2(OldDhSectionPos pos, FullDataPointIdMap mapping, LongArrayList[] data, byte[] columnGenerationSteps, byte[] columnWorldCompressionMode) + public static FullDataSourceV2 createWithData(long pos, FullDataPointIdMap mapping, LongArrayList[] data, byte[] columnGenerationStep, byte[] columnWorldCompressionMode) { return new FullDataSourceV2(pos, mapping, data, columnGenerationStep, columnWorldCompressionMode); } + private FullDataSourceV2(long pos, FullDataPointIdMap mapping, LongArrayList[] data, byte[] columnGenerationSteps, byte[] columnWorldCompressionMode) { LodUtil.assertTrue(data.length == WIDTH * WIDTH); @@ -230,8 +230,8 @@ public class FullDataSourceV2 implements IDataSource } - byte thisDetailLevel = this.pos.getDetailLevel(); - byte inputDetailLevel = inputDataSource.pos.getDetailLevel(); + byte thisDetailLevel = DhSectionPos.getDetailLevel(this.pos); + byte inputDetailLevel = DhSectionPos.getDetailLevel(inputDataSource.pos); // determine the mapping changes necessary for the input to map onto this datasource @@ -256,7 +256,7 @@ public class FullDataSourceV2 implements IDataSource } // determine if this data source should be applied to its parent - this.applyToParent = (dataChanged && this.pos.getDetailLevel() < AbstractDataSourceHandler.TOP_SECTION_DETAIL_LEVEL); + this.applyToParent = (dataChanged && DhSectionPos.getDetailLevel(this.pos) < AbstractDataSourceHandler.TOP_SECTION_DETAIL_LEVEL); if (dataChanged) { @@ -269,9 +269,9 @@ public class FullDataSourceV2 implements IDataSource public boolean updateFromSameDetailLevel(FullDataSourceV2 inputDataSource, int[] remappedIds) { // both data sources should have the same detail level - if (inputDataSource.pos.getDetailLevel() != this.pos.getDetailLevel()) + if (DhSectionPos.getDetailLevel(inputDataSource.pos) != DhSectionPos.getDetailLevel(this.pos)) { - throw new IllegalArgumentException("Both data sources must have the same detail level. Expected ["+this.pos.getDetailLevel()+"], received ["+inputDataSource.pos.getDetailLevel()+"]."); + throw new IllegalArgumentException("Both data sources must have the same detail level. Expected ["+DhSectionPos.getDetailLevel(this.pos)+"], received ["+DhSectionPos.getDetailLevel(inputDataSource.pos)+"]."); } // copy over everything from the input data source into this one @@ -351,9 +351,9 @@ public class FullDataSourceV2 implements IDataSource } public boolean updateFromOneBelowDetailLevel(FullDataSourceV2 inputDataSource, int[] remappedIds) { - if (inputDataSource.pos.getDetailLevel() + 1 != this.pos.getDetailLevel()) + if (DhSectionPos.getDetailLevel(inputDataSource.pos) + 1 != DhSectionPos.getDetailLevel(this.pos)) { - throw new IllegalArgumentException("Input data source must be exactly 1 detail level below this data source. Expected [" + (this.pos.getDetailLevel() - 1) + "], received [" + inputDataSource.pos.getDetailLevel() + "]."); + throw new IllegalArgumentException("Input data source must be exactly 1 detail level below this data source. Expected [" + (DhSectionPos.getDetailLevel(this.pos) - 1) + "], received [" + DhSectionPos.getDetailLevel(inputDataSource.pos) + "]."); } // input is one detail level lower (higher detail) @@ -362,10 +362,10 @@ public class FullDataSourceV2 implements IDataSource // determine where in the input data source should be written to // since the input is one detail level below it will be one of this position's 4 children - int minChildXPos = this.pos.getChildByIndex(0).getX(); - int recipientOffsetX = (inputDataSource.pos.getX() == minChildXPos) ? 0 : (WIDTH / 2); - int minChildZPos = this.pos.getChildByIndex(0).getZ(); - int recipientOffsetZ = (inputDataSource.pos.getZ() == minChildZPos) ? 0 : (WIDTH / 2); + int minChildXPos = DhSectionPos.getX(DhSectionPos.getChildByIndex(0, this.pos)); + int recipientOffsetX = (DhSectionPos.getX(inputDataSource.pos) == minChildXPos) ? 0 : (WIDTH / 2); + int minChildZPos = DhSectionPos.getZ(DhSectionPos.getChildByIndex(0, this.pos)); + int recipientOffsetZ = (DhSectionPos.getZ(inputDataSource.pos) == minChildZPos) ? 0 : (WIDTH / 2); @@ -783,7 +783,7 @@ public class FullDataSourceV2 implements IDataSource * * @see FullDataSourceV2#dataPoints */ - public static void throwIfDataColumnInWrongOrder(OldDhSectionPos pos, LongArrayList dataArray) throws IllegalStateException + public static void throwIfDataColumnInWrongOrder(long pos, LongArrayList dataArray) throws IllegalStateException { long firstDataPoint = dataArray.getLong(0); int firstBottomY = FullDataPointUtil.getBottomY(firstDataPoint); @@ -793,7 +793,7 @@ public class FullDataSourceV2 implements IDataSource if (firstBottomY < lastBottomY) { - throw new IllegalStateException("Incorrect data point order at pos: "+pos+", first datapoint bottom Y ["+firstBottomY+"], last datapoint bottom Y ["+lastBottomY+"]."); + throw new IllegalStateException("Incorrect data point order at pos: ["+DhSectionPos.toString(pos)+"], first datapoint bottom Y ["+firstBottomY+"], last datapoint bottom Y ["+lastBottomY+"]."); } } @@ -829,7 +829,7 @@ public class FullDataSourceV2 implements IDataSource // pooling // //=========// - private static void prepPooledDataSource(OldDhSectionPos pos, boolean clearData, FullDataSourceV2 dataSource) + private static void prepPooledDataSource(long pos, boolean clearData, FullDataSourceV2 dataSource) { dataSource.pos = pos; @@ -857,10 +857,10 @@ public class FullDataSourceV2 implements IDataSource //=====================// @Override - public OldDhSectionPos getPos() { return this.pos; } + public Long getPos() { return this.pos; } @Override - public byte getDataDetailLevel() { return (byte) (this.pos.getDetailLevel() - OldDhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL); } + public byte getDataDetailLevel() { return (byte) (DhSectionPos.getDetailLevel(this.pos) - DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL); } public EDhApiWorldGenerationStep getWorldGenStepAtRelativePos(int relX, int relZ) { @@ -899,7 +899,7 @@ public class FullDataSourceV2 implements IDataSource //================// @Override - public String toString() { return this.pos.toString(); } + public String toString() { return DhSectionPos.toString(this.pos); } @Override public int hashCode() @@ -912,7 +912,7 @@ public class FullDataSourceV2 implements IDataSource } private void generateHashCode() { - int result = this.pos.hashCode(); + int result = DhSectionPos.hashCode(this.pos); result = 31 * result + Arrays.deepHashCode(this.dataPoints); result = 17 * result + Arrays.hashCode(this.columnGenerationSteps); result = 43 * result + Arrays.hashCode(this.columnWorldCompressionMode); @@ -929,7 +929,7 @@ public class FullDataSourceV2 implements IDataSource } FullDataSourceV2 other = (FullDataSourceV2) obj; - if (!other.pos.equals(this.pos)) + if (other.pos != this.pos) { return false; } 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 b1fed9355..92626cbdb 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 @@ -26,7 +26,7 @@ import com.seibel.distanthorizons.core.file.DataSourcePool; import com.seibel.distanthorizons.core.file.IDataSource; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos2D; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.core.dataObjects.render.columnViews.ColumnArrayView; import com.seibel.distanthorizons.core.dataObjects.render.columnViews.ColumnQuadView; @@ -50,7 +50,7 @@ public class ColumnRenderSource implements IDataSource private static final Logger LOGGER = DhLoggerBuilder.getLogger(); public static final boolean DO_SAFETY_CHECKS = ModInfo.IS_DEV_BUILD; - public static final byte SECTION_SIZE_OFFSET = OldDhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL; + public static final byte SECTION_SIZE_OFFSET = DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL; public static final int SECTION_SIZE = BitShiftUtil.powerOfTwo(SECTION_SIZE_OFFSET); public static final DataSourcePool DATA_SOURCE_POOL = new DataSourcePool<>(ColumnRenderSource::createEmptyRenderSource, null /* data source prep/cleanup needs to be done outside the pool since it requires additional inputs */); @@ -59,7 +59,7 @@ public class ColumnRenderSource implements IDataSource /** will be zero if an empty data source was created */ public int verticalDataCount; - public OldDhSectionPos pos; + public long pos; public int yOffset; public LongArrayList renderDataContainer; @@ -77,11 +77,11 @@ public class ColumnRenderSource implements IDataSource //==============// /** - * This is separate from {@link DataSourcePool#getPooledSource(OldDhSectionPos, boolean)} + * This is separate from {@link DataSourcePool#getPooledSource(long, boolean)} * because we need to pass in a couple extra values, * specifically maxVerticalSize and yOffset. */ - public static ColumnRenderSource getPooledRenderSource(OldDhSectionPos pos, int maxVerticalSize, int yOffset, boolean clearData) + public static ColumnRenderSource getPooledRenderSource(long pos, int maxVerticalSize, int yOffset, boolean clearData) { ColumnRenderSource renderSource = DATA_SOURCE_POOL.getPooledSource(pos); @@ -109,14 +109,14 @@ public class ColumnRenderSource implements IDataSource } - private static ColumnRenderSource createEmptyRenderSource(OldDhSectionPos sectionPos) { return new ColumnRenderSource(sectionPos, 0, 0); } + private static ColumnRenderSource createEmptyRenderSource(long sectionPos) { return new ColumnRenderSource(sectionPos, 0, 0); } /** * Creates an empty ColumnRenderSource. * * @param pos the relative position of the container * @param maxVerticalSize the maximum vertical size of the container */ - private ColumnRenderSource(OldDhSectionPos pos, int maxVerticalSize, int yOffset) + private ColumnRenderSource(long pos, int maxVerticalSize, int yOffset) { this.verticalDataCount = maxVerticalSize; this.renderDataContainer = new LongArrayList(new long[SECTION_SIZE * SECTION_SIZE * this.verticalDataCount]); @@ -155,7 +155,7 @@ public class ColumnRenderSource implements IDataSource final String errorMessagePrefix = "Unable to complete update for RenderSource pos: [" + this.pos + "] and pos: [" + inputFullDataSource.getPos() + "]. Error:"; boolean dataChanged = false; - if (inputFullDataSource.getPos().getDetailLevel() == this.pos.getDetailLevel()) + if (DhSectionPos.getDetailLevel(inputFullDataSource.getPos()) == DhSectionPos.getDetailLevel(this.pos)) { try { @@ -167,8 +167,8 @@ public class ColumnRenderSource implements IDataSource - DhBlockPos2D centerBlockPos = inputFullDataSource.getPos().getCenterBlockPos(); - int halfBlockWidth = inputFullDataSource.getPos().getBlockWidth() / 2; + DhBlockPos2D centerBlockPos = DhSectionPos.getCenterBlockPos(inputFullDataSource.getPos()); + int halfBlockWidth = DhSectionPos.getBlockWidth(inputFullDataSource.getPos()) / 2; DhBlockPos2D minBlockPos = new DhBlockPos2D(centerBlockPos.x - halfBlockWidth, centerBlockPos.z - halfBlockWidth); for (int x = 0; x < FullDataSourceV2.WIDTH; x++) @@ -215,11 +215,11 @@ public class ColumnRenderSource implements IDataSource // data helper methods // //=====================// - public OldDhSectionPos getPos() { return this.pos; } + public Long getPos() { return this.pos; } @Override - public OldDhSectionPos getKey() { return this.pos; } + public Long getKey() { return this.pos; } - public byte getDataDetailLevel() { return (byte) (this.pos.getDetailLevel() - SECTION_SIZE_OFFSET); } + public byte getDataDetailLevel() { return (byte) (DhSectionPos.getDetailLevel(this.pos) - SECTION_SIZE_OFFSET); } public boolean isEmpty() { return this.isEmpty; } public void markNotEmpty() { this.isEmpty = false; } 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 3c0e9f681..02c064408 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 @@ -27,7 +27,7 @@ import com.seibel.distanthorizons.core.level.IDhClientLevel; import com.seibel.distanthorizons.core.logging.ConfigBasedLogger; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.render.glObject.GLProxy; import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer; import com.seibel.distanthorizons.core.util.LodUtil; @@ -98,7 +98,7 @@ public class ColumnRenderBufferBuilder && !clientLevel.getLevelWrapper().getDimensionType().isTheEnd() // FIXME temporary fix // Cave culling is currently broken for any detail level above 0 - && renderSource.pos.getDetailLevel() == OldDhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL + && DhSectionPos.getDetailLevel(renderSource.pos) == DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL ); int skyLightCullingBelow = Config.Client.Advanced.Graphics.AdvancedGraphics.caveCullingHeight.get(); @@ -131,7 +131,7 @@ public class ColumnRenderBufferBuilder { try { - ColumnRenderBuffer buffer = new ColumnRenderBuffer(new DhBlockPos(renderSource.pos.getMinCornerLodPos().getCornerBlockPos(), clientLevel.getMinY())); + ColumnRenderBuffer buffer = new ColumnRenderBuffer(new DhBlockPos(DhSectionPos.getMinCornerBlockX(renderSource.pos), clientLevel.getMinY(), DhSectionPos.getMinCornerBlockZ(renderSource.pos))); try { buffer.uploadBuffer(quadBuilder, GLProxy.getInstance().getGpuUploadMethod()); @@ -174,9 +174,9 @@ public class ColumnRenderBufferBuilder boolean enableColumnBufferLimit = Config.Client.Advanced.Debugging.columnBuilderDebugEnable.get(); if (enableColumnBufferLimit) { - if (renderSource.pos.getDetailLevel() == Config.Client.Advanced.Debugging.columnBuilderDebugDetailLevel.get() - && renderSource.pos.getX() == Config.Client.Advanced.Debugging.columnBuilderDebugXPos.get() - && renderSource.pos.getZ() == Config.Client.Advanced.Debugging.columnBuilderDebugZPos.get()) + if (DhSectionPos.getDetailLevel(renderSource.pos) == Config.Client.Advanced.Debugging.columnBuilderDebugDetailLevel.get() + && DhSectionPos.getX(renderSource.pos) == Config.Client.Advanced.Debugging.columnBuilderDebugXPos.get() + && DhSectionPos.getZ(renderSource.pos) == Config.Client.Advanced.Debugging.columnBuilderDebugZPos.get()) { int test = 0; } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/columnViews/IColumnDataView.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/columnViews/IColumnDataView.java index 825824162..2d97e9426 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/columnViews/IColumnDataView.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/columnViews/IColumnDataView.java @@ -19,6 +19,8 @@ package com.seibel.distanthorizons.core.dataObjects.render.columnViews; +import it.unimi.dsi.fastutil.longs.LongIterator; + import java.util.Iterator; public interface IColumnDataView @@ -28,18 +30,18 @@ public interface IColumnDataView // FIXME probably horizontal size in blocks? int size(); - default Iterator iterator() + default LongIterator iterator() { - return new Iterator() + return new LongIterator() { private int index = 0; - private final int size = size(); + private final int size = IColumnDataView.this.size(); @Override public boolean hasNext() { return this.index < this.size; } @Override - public Long next() { return get(this.index++); } + public long nextLong() { return IColumnDataView.this.get(this.index++); } }; } 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 2d498d681..30d4d5a4c 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 @@ -29,7 +29,7 @@ import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.level.IDhClientLevel; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.util.ColorUtil; import com.seibel.distanthorizons.core.util.FullDataPointUtil; import com.seibel.distanthorizons.core.util.RenderDataPointUtil; @@ -38,6 +38,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrappe import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper; import it.unimi.dsi.fastutil.longs.LongArrayList; +import it.unimi.dsi.fastutil.longs.LongOpenHashSet; import org.apache.logging.log4j.Logger; import java.util.HashSet; @@ -52,7 +53,7 @@ public class FullDataToRenderDataTransformer private static final IWrapperFactory WRAPPER_FACTORY = SingletonInjector.INSTANCE.get(IWrapperFactory.class); private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); - private static final HashSet brokenPos = new HashSet<>(); + private static final LongOpenHashSet brokenPos = new LongOpenHashSet(); @@ -98,7 +99,7 @@ public class FullDataToRenderDataTransformer */ private static ColumnRenderSource transformCompleteFullDataToColumnData(IDhClientLevel level, FullDataSourceV2 fullDataSource) throws InterruptedException { - final OldDhSectionPos pos = fullDataSource.getPos(); + final long pos = fullDataSource.getPos(); final byte dataDetail = fullDataSource.getDataDetailLevel(); final int vertSize = Config.Client.Advanced.Graphics.Quality.verticalQuality.get().calculateMaxVerticalData(fullDataSource.getDataDetailLevel()); final ColumnRenderSource columnSource = ColumnRenderSource.getPooledRenderSource(pos, vertSize, level.getMinY(), true); @@ -111,12 +112,12 @@ public class FullDataToRenderDataTransformer if (dataDetail == columnSource.getDataDetailLevel()) { - int baseX = pos.getMinCornerLodPos().getCornerBlockPos().x; - int baseZ = pos.getMinCornerLodPos().getCornerBlockPos().z; + int baseX = DhSectionPos.getMinCornerBlockX(pos); + int baseZ = DhSectionPos.getMinCornerBlockZ(pos); - for (int x = 0; x < pos.getWidthCountForLowerDetailedSection(dataDetail); x++) + for (int x = 0; x < DhSectionPos.getWidthCountForLowerDetailedSection(dataDetail, pos); x++) { - for (int z = 0; z < pos.getWidthCountForLowerDetailedSection(dataDetail); z++) + for (int z = 0; z < DhSectionPos.getWidthCountForLowerDetailedSection(dataDetail, pos); z++) { throwIfThreadInterrupted(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java index d73f7d860..5f3001621 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java @@ -32,7 +32,7 @@ import com.seibel.distanthorizons.core.enums.EDhDirection; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhChunkPos; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.util.FullDataPointUtil; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.objects.DataCorruptedException; @@ -73,7 +73,7 @@ public class LodDataBuilder sectionPosX = (sectionPosX < 0) ? ((sectionPosX + 1) / NUMB_OF_CHUNKS_WIDE) - 1 : (sectionPosX / NUMB_OF_CHUNKS_WIDE); int sectionPosZ = chunkWrapper.getChunkPos().z; sectionPosZ = (sectionPosZ < 0) ? ((sectionPosZ + 1) / NUMB_OF_CHUNKS_WIDE) - 1 : (sectionPosZ / NUMB_OF_CHUNKS_WIDE); - OldDhSectionPos pos = new OldDhSectionPos(OldDhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ); + long pos = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ); FullDataSourceV2 dataSource = FullDataSourceV2.createEmpty(pos); dataSource.isEmpty = false; @@ -303,7 +303,7 @@ public class LodDataBuilder /** @throws ClassCastException if an API user returns the wrong object type(s) */ public static FullDataSourceV2 createFromApiChunkData(DhApiChunk dataPoints) throws ClassCastException, DataCorruptedException { - FullDataSourceV2 accessor = FullDataSourceV2.createEmpty(new OldDhSectionPos(new DhChunkPos(dataPoints.chunkPosX, dataPoints.chunkPosZ))); + FullDataSourceV2 accessor = FullDataSourceV2.createEmpty(DhSectionPos.encode(new DhChunkPos(dataPoints.chunkPosX, dataPoints.chunkPosZ))); for (int relZ = 0; relZ < LodUtil.CHUNK_WIDTH; relZ++) { for (int relX = 0; relX < LodUtil.CHUNK_WIDTH; relX++) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/AbstractDataSourceHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/file/AbstractDataSourceHandler.java index f26434a91..ab54b191e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/AbstractDataSourceHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/AbstractDataSourceHandler.java @@ -4,7 +4,7 @@ import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSour import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure; import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.sql.repo.AbstractDhRepo; import com.seibel.distanthorizons.core.sql.dto.IBaseDTO; import com.seibel.distanthorizons.core.util.LodUtil; @@ -26,8 +26,8 @@ import java.util.concurrent.locks.ReentrantLock; // We shouldn't need multiple data source handlers public abstract class AbstractDataSourceHandler , - TDTO extends IBaseDTO, - TRepo extends AbstractDhRepo, + TDTO extends IBaseDTO, + TRepo extends AbstractDhRepo, TDhLevel extends IDhLevel> implements AutoCloseable { @@ -41,13 +41,13 @@ public abstract class AbstractDataSourceHandler * * @see AbstractDataSourceHandler#MIN_SECTION_DETAIL_LEVEL */ - public static final byte TOP_SECTION_DETAIL_LEVEL = OldDhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL + LodUtil.REGION_DETAIL_LEVEL; + public static final byte TOP_SECTION_DETAIL_LEVEL = DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL + LodUtil.REGION_DETAIL_LEVEL; /** * The lowest numerical detail level possible. * * @see AbstractDataSourceHandler#TOP_SECTION_DETAIL_LEVEL * */ - public static final byte MIN_SECTION_DETAIL_LEVEL = OldDhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL; + public static final byte MIN_SECTION_DETAIL_LEVEL = DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL; protected final PositionalLockProvider updateLockProvider = new PositionalLockProvider(); @@ -55,8 +55,8 @@ public abstract class AbstractDataSourceHandler * generally just used for debugging, * keeps track of which positions are currently locked. */ - public final Set lockedPosSet = ConcurrentHashMap.newKeySet(); - public final ConcurrentHashMap queuedUpdateCountsByPos = new ConcurrentHashMap<>(); + public final Set lockedPosSet = ConcurrentHashMap.newKeySet(); + public final ConcurrentHashMap queuedUpdateCountsByPos = new ConcurrentHashMap<>(); protected final ReentrantLock closeLock = new ReentrantLock(); @@ -101,7 +101,7 @@ public abstract class AbstractDataSourceHandler protected abstract TDataSource createDataSourceFromDto(TDTO dto) throws InterruptedException, IOException, DataCorruptedException; protected abstract TDTO createDtoFromDataSource(TDataSource dataSource); - protected abstract TDataSource makeEmptyDataSource(OldDhSectionPos pos); + protected abstract TDataSource makeEmptyDataSource(long pos); @@ -115,7 +115,7 @@ public abstract class AbstractDataSourceHandler * * This call is concurrent. I.e. it supports being called by multiple threads at the same time. */ - public CompletableFuture getAsync(OldDhSectionPos pos) + public CompletableFuture getAsync(long pos) { ThreadPoolExecutor executor = ThreadPoolUtil.getFileHandlerExecutor(); if (executor == null || executor.isTerminated()) @@ -137,10 +137,10 @@ public abstract class AbstractDataSourceHandler /** * Should only be used in internal file handler methods where we are already running on a file handler thread. * Can return null if the repo is in the process of being shut down - * @see AbstractDataSourceHandler#getAsync(OldDhSectionPos) + * @see AbstractDataSourceHandler#getAsync(long) */ @Nullable - public TDataSource get(OldDhSectionPos pos) + public TDataSource get(long pos) { TDataSource dataSource = null; try @@ -160,7 +160,7 @@ public abstract class AbstractDataSourceHandler // if the user is migrating from a nightly build and used ZStd. if (CORRUPT_DATA_ERRORS_LOGGED.add(e.getMessage())) { - LOGGER.warn("Corrupted data found at pos " + pos + ". Data at position will be deleted so it can be re-generated to prevent issues. Future errors with this same message won't be logged. Error: " + e.getMessage(), e); + LOGGER.warn("Corrupted data found at pos [" + DhSectionPos.toString(pos) + "]. Data at position will be deleted so it can be re-generated to prevent issues. Future errors with this same message won't be logged. Error: " + e.getMessage(), e); } this.repo.deleteWithKey(pos); @@ -177,7 +177,7 @@ public abstract class AbstractDataSourceHandler catch (InterruptedException ignore) { } catch (IOException e) { - LOGGER.warn("File read Error for pos ["+pos+"], error: "+e.getMessage(), e); + LOGGER.warn("File read Error for pos ["+DhSectionPos.toString(pos)+"], error: "+e.getMessage(), e); } return dataSource; @@ -230,7 +230,7 @@ public abstract class AbstractDataSourceHandler * After this method returns the inputData will be written to file. * @param updatePos the position to update */ - protected void updateDataSourceAtPos(OldDhSectionPos updatePos, @NotNull FullDataSourceV2 inputData, boolean lockOnUpdatePos) + protected void updateDataSourceAtPos(long updatePos, @NotNull FullDataSourceV2 inputData, boolean lockOnUpdatePos) { boolean methodLocked = false; // a lock is necessary to prevent two threads from writing to the same position at once, @@ -292,7 +292,7 @@ public abstract class AbstractDataSourceHandler //================// /** used for debugging to track which positions are queued for updating */ - private void markUpdateStart(OldDhSectionPos dataSourcePos) + private void markUpdateStart(long dataSourcePos) { this.queuedUpdateCountsByPos.compute(dataSourcePos, (pos, atomicCount) -> { @@ -305,7 +305,7 @@ public abstract class AbstractDataSourceHandler }); } /** used for debugging to track which positions are queued for updating */ - private void markUpdateEnd(OldDhSectionPos dataSourcePos) + private void markUpdateEnd(long dataSourcePos) { this.queuedUpdateCountsByPos.compute(dataSourcePos, (pos, atomicCount) -> { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/DataSourcePool.java b/core/src/main/java/com/seibel/distanthorizons/core/file/DataSourcePool.java index 0c5b35dc6..226006a2d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/DataSourcePool.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/DataSourcePool.java @@ -1,7 +1,7 @@ package com.seibel.distanthorizons.core.file; import com.seibel.distanthorizons.core.level.IDhLevel; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; @@ -26,7 +26,7 @@ public class DataSourcePool, TDhLevel private final ArrayList pooledDataSources = new ArrayList<>(); private final ReentrantLock poolLock = new ReentrantLock(); - private final Function createEmptyDatasourceFunc; + private final Function createEmptyDatasourceFunc; @Nullable private final IPrepPooledDataSourceFunc prepDatasourceFunc; @@ -36,7 +36,7 @@ public class DataSourcePool, TDhLevel // constructor // //=============// - public DataSourcePool(Function createEmptyDatasourceFunc, @Nullable IPrepPooledDataSourceFunc prepDatasourceFunc) + public DataSourcePool(Function createEmptyDatasourceFunc, @Nullable IPrepPooledDataSourceFunc prepDatasourceFunc) { this.createEmptyDatasourceFunc = createEmptyDatasourceFunc; this.prepDatasourceFunc = prepDatasourceFunc; @@ -50,12 +50,12 @@ public class DataSourcePool, TDhLevel /** * Returns a cleared data source. - * @see DataSourcePool#getPooledSource(OldDhSectionPos, boolean) + * @see DataSourcePool#getPooledSource(long, boolean) */ - public TDataSource getPooledSource(OldDhSectionPos pos) { return this.getPooledSource(pos, true);} + public TDataSource getPooledSource(long pos) { return this.getPooledSource(pos, true);} /** @return an empty data source if non are cached */ - public TDataSource getPooledSource(OldDhSectionPos pos, boolean clearData) + public TDataSource getPooledSource(long pos, boolean clearData) { try { @@ -132,7 +132,7 @@ public class DataSourcePool, TDhLevel public interface IPrepPooledDataSourceFunc, TDhLevel extends IDhLevel> { /** @param clearData will be false if the data will be immediately overwritten anyway */ - void prepDataSource(OldDhSectionPos pos, boolean clearData, TDataSource dataSource); + void prepDataSource(long pos, boolean clearData, TDataSource dataSource); } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/IDataSource.java b/core/src/main/java/com/seibel/distanthorizons/core/file/IDataSource.java index 0abb28372..e662c79a8 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/IDataSource.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/IDataSource.java @@ -3,7 +3,7 @@ package com.seibel.distanthorizons.core.file; import com.seibel.distanthorizons.api.enums.EDhApiDetailLevel; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; import com.seibel.distanthorizons.core.level.IDhLevel; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.sql.dto.IBaseDTO; /** @@ -13,9 +13,9 @@ import com.seibel.distanthorizons.core.sql.dto.IBaseDTO; * * @param there are times when we need specifically a client level vs a more generic level */ -public interface IDataSource extends IBaseDTO, AutoCloseable +public interface IDataSource extends IBaseDTO, AutoCloseable { - OldDhSectionPos getPos(); + Long getPos(); /** @return true if the data was changed */ boolean update(FullDataSourceV2 chunkData, TDhLevel level); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/DelayedFullDataSourceSaveCache.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/DelayedFullDataSourceSaveCache.java index 193ed399e..bf6a71b67 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/DelayedFullDataSourceSaveCache.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/DelayedFullDataSourceSaveCache.java @@ -2,7 +2,7 @@ package com.seibel.distanthorizons.core.file.fullDatafile; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.util.TimerUtil; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.NotNull; @@ -22,8 +22,8 @@ public class DelayedFullDataSourceSaveCache private static final Timer DELAY_UPDATE_TIMER = TimerUtil.CreateTimer("Delayed Full Datasource Save Timer"); - public final ConcurrentHashMap dataSourceByPosition = new ConcurrentHashMap<>(); - private final ConcurrentHashMap saveTimerTasksBySectionPos = new ConcurrentHashMap<>(); + public final ConcurrentHashMap dataSourceByPosition = new ConcurrentHashMap<>(); + private final ConcurrentHashMap saveTimerTasksBySectionPos = new ConcurrentHashMap<>(); private final ISaveDataSourceFunc onSaveTimeoutFunc; private final int saveDelayInMs; @@ -48,7 +48,7 @@ public class DelayedFullDataSourceSaveCache public void queueDataSourceForUpdateAndSave(FullDataSourceV2 inputDataSource) { - OldDhSectionPos dataSourcePos = inputDataSource.getPos(); + long dataSourcePos = inputDataSource.getPos(); this.dataSourceByPosition.compute(dataSourcePos, (inputPos, temporaryDataSource) -> { if (temporaryDataSource == null) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataSourceProviderV1.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataSourceProviderV1.java index 2a82f73af..86b95ac2b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataSourceProviderV1.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataSourceProviderV1.java @@ -4,11 +4,12 @@ import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSour import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure; import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.sql.dto.FullDataSourceV1DTO; import com.seibel.distanthorizons.core.sql.repo.FullDataSourceV1Repo; import com.seibel.distanthorizons.core.util.objects.DataCorruptedException; import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil; +import it.unimi.dsi.fastutil.longs.LongArrayList; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.Nullable; @@ -92,7 +93,7 @@ public class FullDataSourceProviderV1 * * This call is concurrent. I.e. it supports being called by multiple threads at the same time. */ - public CompletableFuture getAsync(OldDhSectionPos pos) + public CompletableFuture getAsync(long pos) { ThreadPoolExecutor executor = ThreadPoolUtil.getFileHandlerExecutor(); if (executor == null || executor.isTerminated()) @@ -113,10 +114,10 @@ public class FullDataSourceProviderV1 /** * Should only be used in internal file handler methods where we are already running on a file handler thread. * Can return null. - * @see FullDataSourceProviderV1#getAsync(OldDhSectionPos) + * @see FullDataSourceProviderV1#getAsync(long) */ @Nullable - public FullDataSourceV1 get(OldDhSectionPos pos) + public FullDataSourceV1 get(Long pos) { FullDataSourceV1 dataSource = null; try @@ -133,12 +134,12 @@ public class FullDataSourceProviderV1 { // stack trace not included since a lot of corrupt data would cause the log to get quite messy, // and it should be fairly easy to see what the problem was from the message - LOGGER.warn("Corrupted data found at pos "+pos+". Data at position will be deleted so it can be re-generated and to prevent future issues. Error: "+e.getMessage()); + LOGGER.warn("Corrupted data found at pos ["+DhSectionPos.toString(pos)+"]. Data at position will be deleted so it can be re-generated and to prevent future issues. Error: "+e.getMessage()); this.repo.deleteWithKey(pos); } catch (IOException e) { - LOGGER.warn("File read Error for pos ["+pos+"], error: "+e.getMessage(), e); + LOGGER.warn("File read Error for pos ["+DhSectionPos.toString(pos)+"], error: "+e.getMessage(), e); } return dataSource; @@ -156,10 +157,10 @@ public class FullDataSourceProviderV1 { ArrayList dataSourceList = new ArrayList<>(); - ArrayList migrationPosList = this.repo.getPositionsToMigrate(limit); + LongArrayList migrationPosList = this.repo.getPositionsToMigrate(limit); for (int i = 0; i < migrationPosList.size(); i++) { - OldDhSectionPos pos = migrationPosList.get(i); + Long pos = migrationPosList.getLong(i); FullDataSourceV1 dataSource = this.get(pos); if (dataSource != null) { @@ -170,7 +171,7 @@ public class FullDataSourceProviderV1 return dataSourceList; } - public void markMigrationFailed(OldDhSectionPos pos) { ((FullDataSourceV1Repo) this.repo).markMigrationFailed(pos); } + public void markMigrationFailed(long pos) { ((FullDataSourceV1Repo) this.repo).markMigrationFailed(pos); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataSourceProviderV2.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataSourceProviderV2.java index acb80535c..32d529e88 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataSourceProviderV2.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataSourceProviderV2.java @@ -29,7 +29,7 @@ import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure; import com.seibel.distanthorizons.core.file.AbstractDataSourceHandler; import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.render.renderer.DebugRenderer; import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable; import com.seibel.distanthorizons.core.sql.dto.FullDataSourceV2DTO; @@ -38,6 +38,7 @@ import com.seibel.distanthorizons.core.util.ThreadUtil; import com.seibel.distanthorizons.core.util.objects.DataCorruptedException; import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; +import it.unimi.dsi.fastutil.longs.LongArrayList; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.Nullable; @@ -97,7 +98,7 @@ public class FullDataSourceProviderV2 * Tracks which positions are currently being updated * to prevent duplicate concurrent updates. */ - public final Set parentUpdatingPosSet = ConcurrentHashMap.newKeySet(); + public final Set parentUpdatingPosSet = ConcurrentHashMap.newKeySet(); // TODO only run thread if modifications happened recently /** @@ -172,7 +173,7 @@ public class FullDataSourceProviderV2 { return dto.createPooledDataSource(this.level.getLevelWrapper()); } @Override - protected FullDataSourceV2 makeEmptyDataSource(OldDhSectionPos pos) { return FullDataSourceV2.DATA_SOURCE_POOL.getPooledSource(pos, true); } + protected FullDataSourceV2 makeEmptyDataSource(long pos) { return FullDataSourceV2.DATA_SOURCE_POOL.getPooledSource(pos, true); } @@ -201,13 +202,13 @@ public class FullDataSourceProviderV2 && this.parentUpdatingPosSet.size() < MAX_UPDATE_TASK_COUNT) { // get the positions that need to be applied to their parents - ArrayList parentUpdatePosList = this.repo.getPositionsToUpdate(MAX_UPDATE_TASK_COUNT); + LongArrayList parentUpdatePosList = this.repo.getPositionsToUpdate(MAX_UPDATE_TASK_COUNT); // combine updates together based on their parent - HashMap> updatePosByParentPos = new HashMap<>(); - for (OldDhSectionPos pos : parentUpdatePosList) + HashMap> updatePosByParentPos = new HashMap<>(); + for (Long pos : parentUpdatePosList) { - updatePosByParentPos.compute(pos.getParentPos(), (parentPos, updatePosSet) -> + updatePosByParentPos.compute(DhSectionPos.getParentPos(pos), (parentPos, updatePosSet) -> { if (updatePosSet == null) { @@ -219,7 +220,7 @@ public class FullDataSourceProviderV2 } // queue the updates - for (OldDhSectionPos parentUpdatePos : updatePosByParentPos.keySet()) + for (Long parentUpdatePos : updatePosByParentPos.keySet()) { // stop if there are already a bunch of updates queued if (this.parentUpdatingPosSet.size() > MAX_UPDATE_TASK_COUNT @@ -246,7 +247,7 @@ public class FullDataSourceProviderV2 this.lockedPosSet.add(parentUpdatePos); // apply each child pos to the parent - for (OldDhSectionPos childPos : updatePosByParentPos.get(parentUpdatePos)) + for (Long childPos : updatePosByParentPos.get(parentUpdatePos)) { ReentrantLock childReadLock = this.updateLockProvider.getLock(childPos); try @@ -423,7 +424,7 @@ public class FullDataSourceProviderV2 } catch (Exception e) { - OldDhSectionPos migrationPos = legacyDataSource.getPos(); + Long migrationPos = legacyDataSource.getPos(); LOGGER.warn("Unexpected issue migrating data source at pos " + migrationPos + ". Error: " + e.getMessage(), e); this.legacyFileHandler.markMigrationFailed(migrationPos); } @@ -555,18 +556,18 @@ public class FullDataSourceProviderV2 * an empty array if all positions were generated */ @Nullable - public ArrayList getPositionsToRetrieve(OldDhSectionPos pos) { return null; } + public LongArrayList getPositionsToRetrieve(Long pos) { return null; } /** * Returns how many positions could potentially be generated for this position assuming the position is empty. * Used when estimating the total number of retrieval requests. */ - public int getMaxPossibleRetrievalPositionCountForPos(OldDhSectionPos pos) { return -1; } + public int getMaxPossibleRetrievalPositionCountForPos(Long pos) { return -1; } /** @return true if the position was queued, false if not */ - public boolean queuePositionForRetrieval(OldDhSectionPos genPos) { return false; } + public boolean queuePositionForRetrieval(Long genPos) { return false; } /** does nothing if the given position isn't present in the queue */ - public void removeRetrievalRequestIf(Function removeIf) { } + public void removeRetrievalRequestIf(DhSectionPos.ICancelablePrimitiveLongConsumer removeIf) { } public void clearRetrievalQueue() { } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataSourceProvider.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataSourceProvider.java index c7dfba6a2..371f68b39 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataSourceProvider.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataSourceProvider.java @@ -28,12 +28,13 @@ import com.seibel.distanthorizons.core.generation.tasks.IWorldGenTaskTracker; import com.seibel.distanthorizons.core.generation.tasks.WorldGenResult; import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.render.renderer.DebugRenderer; import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil; import com.seibel.distanthorizons.coreapi.util.BitShiftUtil; +import it.unimi.dsi.fastutil.longs.LongArrayList; import org.apache.logging.log4j.Logger; import java.awt.*; @@ -116,7 +117,7 @@ public class GeneratedFullDataSourceProvider extends FullDataSourceProviderV2 im } // TODO only fire after the section has finished generated or once every X seconds - private void fireOnGenPosSuccessListeners(OldDhSectionPos pos) + private void fireOnGenPosSuccessListeners(long pos) { // fire the event listeners for (IOnWorldGenCompleteListener listener : this.onWorldGenTaskCompleteListeners) @@ -205,7 +206,7 @@ public class GeneratedFullDataSourceProvider extends FullDataSourceProviderV2 im } @Override - public boolean queuePositionForRetrieval(OldDhSectionPos genPos) + public boolean queuePositionForRetrieval(Long genPos) { IFullDataSourceRetrievalQueue worldGenQueue = this.worldGenQueueRef.get(); if (worldGenQueue == null) @@ -214,14 +215,14 @@ public class GeneratedFullDataSourceProvider extends FullDataSourceProviderV2 im } GenTask genTask = new GenTask(genPos); - CompletableFuture worldGenFuture = worldGenQueue.submitGenTask(genPos, (byte) (genPos.getDetailLevel() - OldDhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL), genTask); + CompletableFuture worldGenFuture = worldGenQueue.submitGenTask(genPos, (byte) (DhSectionPos.getDetailLevel(genPos) - DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL), genTask); worldGenFuture.whenComplete((genTaskResult, ex) -> this.onWorldGenTaskComplete(genTaskResult, ex)); return true; } @Override - public void removeRetrievalRequestIf(Function removeIf) + public void removeRetrievalRequestIf(DhSectionPos.ICancelablePrimitiveLongConsumer removeIf) { IFullDataSourceRetrievalQueue worldGenQueue = this.worldGenQueueRef.get(); if (worldGenQueue != null) @@ -238,7 +239,7 @@ public class GeneratedFullDataSourceProvider extends FullDataSourceProviderV2 im @Override - public ArrayList getPositionsToRetrieve(OldDhSectionPos pos) + public LongArrayList getPositionsToRetrieve(Long pos) { IFullDataSourceRetrievalQueue worldGenQueue = this.worldGenQueueRef.get(); if (worldGenQueue == null) @@ -268,7 +269,7 @@ public class GeneratedFullDataSourceProvider extends FullDataSourceProviderV2 im if (positionFullyGenerated) { - return new ArrayList<>(); + return new LongArrayList(); } } } @@ -277,9 +278,9 @@ public class GeneratedFullDataSourceProvider extends FullDataSourceProviderV2 im // this section is missing one or more columns, queue the missing ones for generation. // TODO speed up this logic by only checking ungenerated columns - ArrayList generationList = new ArrayList<>(); - byte minGeneratorSectionDetailLevel = (byte) (worldGenQueue.highestDataDetail() + OldDhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL); - pos.forEachChildAtDetailLevel(minGeneratorSectionDetailLevel, (genPos) -> + LongArrayList generationList = new LongArrayList(); + byte minGeneratorSectionDetailLevel = (byte) (worldGenQueue.highestDataDetail() + DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL); + DhSectionPos.forEachChildAtDetailLevel(minGeneratorSectionDetailLevel, (genPos) -> { if (!this.repo.existsWithKey(genPos)) { @@ -330,13 +331,13 @@ public class GeneratedFullDataSourceProvider extends FullDataSourceProviderV2 im generationList.add(genPos); } - }); + }, pos); return generationList; } @Override - public int getMaxPossibleRetrievalPositionCountForPos(OldDhSectionPos pos) + public int getMaxPossibleRetrievalPositionCountForPos(Long pos) { IFullDataSourceRetrievalQueue worldGenQueue = this.worldGenQueueRef.get(); if (worldGenQueue == null) @@ -344,8 +345,8 @@ public class GeneratedFullDataSourceProvider extends FullDataSourceProviderV2 im return -1; } - int minGeneratorSectionDetailLevel = worldGenQueue.highestDataDetail() + OldDhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL; - int detailLevelDiff = pos.getDetailLevel() - minGeneratorSectionDetailLevel; + int minGeneratorSectionDetailLevel = worldGenQueue.highestDataDetail() + DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL; + int detailLevelDiff = DhSectionPos.getDetailLevel(pos) - minGeneratorSectionDetailLevel; return BitShiftUtil.powerOfTwo(detailLevelDiff); } @@ -375,12 +376,9 @@ public class GeneratedFullDataSourceProvider extends FullDataSourceProviderV2 im // TODO may not be needed private class GenTask implements IWorldGenTaskTracker { - private final OldDhSectionPos pos; + private final long pos; - public GenTask(OldDhSectionPos pos) - { - this.pos = pos; - } + public GenTask(long pos) { this.pos = pos; } @@ -406,7 +404,7 @@ public class GeneratedFullDataSourceProvider extends FullDataSourceProviderV2 im public interface IOnWorldGenCompleteListener { /** Fired whenever a section has completed generating */ - void onWorldGenTaskComplete(OldDhSectionPos pos); + void onWorldGenTaskComplete(long pos); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionLevelMatcher.java b/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionLevelMatcher.java index 60dbbe45e..6a30b948c 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionLevelMatcher.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionLevelMatcher.java @@ -29,7 +29,7 @@ import com.seibel.distanthorizons.core.level.DhClientLevel; import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.logging.ConfigBasedLogger; import com.seibel.distanthorizons.core.pos.DhChunkPos; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.dataObjects.transformers.LodDataBuilder; import com.seibel.distanthorizons.core.util.FullDataPointUtil; import com.seibel.distanthorizons.core.util.LodUtil; @@ -190,7 +190,7 @@ public class SubDimensionLevelMatcher implements AutoCloseable } FullDataSourceV2 newChunkSizedFullDataView = FullDataSourceV2.createFromChunk(newlyLoadedChunk); // convert to a data source for easier comparing - FullDataSourceV2 newDataSource = FullDataSourceV2.createEmpty(new OldDhSectionPos(this.playerData.playerBlockPos)); + FullDataSourceV2 newDataSource = FullDataSourceV2.createEmpty(DhSectionPos.encode(this.playerData.playerBlockPos)); newDataSource.update(newChunkSizedFullDataView); @@ -215,7 +215,7 @@ public class SubDimensionLevelMatcher implements AutoCloseable // get the data source to compare against try (IDhLevel tempLevel = new DhClientLevel(new ClientOnlySaveStructure(), this.currentClientLevel, testLevelFolder, false)) { - testFullDataSource = tempLevel.getFullDataProvider().getAsync(new OldDhSectionPos(this.playerData.playerBlockPos)).join(); + testFullDataSource = tempLevel.getFullDataProvider().getAsync(DhSectionPos.encode(this.playerData.playerBlockPos)).join(); if (testFullDataSource == null) { continue; @@ -224,9 +224,9 @@ public class SubDimensionLevelMatcher implements AutoCloseable // confirm both data sources have the same section pos - OldDhSectionPos newSectionChunkPos = newDataSource.getPos().convertNewToDetailLevel(OldDhSectionPos.SECTION_CHUNK_DETAIL_LEVEL); - OldDhSectionPos testSectionChunkPos = testFullDataSource.getPos().convertNewToDetailLevel(OldDhSectionPos.SECTION_CHUNK_DETAIL_LEVEL); - LodUtil.assertTrue(newSectionChunkPos.equals(testSectionChunkPos), "data source positions don't match"); + long newSectionChunkPos = DhSectionPos.convertToDetailLevel(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, newDataSource.getPos()); + long testSectionChunkPos = DhSectionPos.convertToDetailLevel(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, testFullDataSource.getPos()); + LodUtil.assertTrue(newSectionChunkPos == testSectionChunkPos, "data source positions don't match"); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/generation/IFullDataSourceRetrievalQueue.java b/core/src/main/java/com/seibel/distanthorizons/core/generation/IFullDataSourceRetrievalQueue.java index 9a36f8e75..d3ebde39d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/generation/IFullDataSourceRetrievalQueue.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/generation/IFullDataSourceRetrievalQueue.java @@ -22,7 +22,7 @@ package com.seibel.distanthorizons.core.generation; import com.seibel.distanthorizons.core.generation.tasks.IWorldGenTaskTracker; import com.seibel.distanthorizons.core.generation.tasks.WorldGenResult; import com.seibel.distanthorizons.core.pos.DhBlockPos2D; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.render.LodQuadTree; import java.io.Closeable; @@ -80,9 +80,9 @@ public interface IFullDataSourceRetrievalQueue extends Closeable * Generally the retrieval queue should be fairly small, so its faster to iterate over the existing list * and check if each one is valid vs dumbly attempting to remove every position that just went out of range. */ - void removeRetrievalRequestIf(Function removeIf); + void removeRetrievalRequestIf(DhSectionPos.ICancelablePrimitiveLongConsumer removeIf); - CompletableFuture submitGenTask(OldDhSectionPos pos, byte requiredDataDetail, IWorldGenTaskTracker tracker); + CompletableFuture submitGenTask(long pos, byte requiredDataDetail, IWorldGenTaskTracker tracker); 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 6036f7a4f..738e19858 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 @@ -29,7 +29,7 @@ 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.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.dataObjects.transformers.LodDataBuilder; import com.seibel.distanthorizons.core.render.renderer.DebugRenderer; @@ -42,6 +42,7 @@ import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; +import it.unimi.dsi.fastutil.longs.LongArrayFIFOQueue; import org.apache.logging.log4j.Logger; import java.awt.*; @@ -58,9 +59,9 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb private final IDhApiWorldGenerator generator; /** contains the positions that need to be generated */ - private final ConcurrentHashMap waitingTasks = new ConcurrentHashMap<>(); + private final ConcurrentHashMap waitingTasks = new ConcurrentHashMap<>(); - private final ConcurrentHashMap inProgressGenTasksByLodPos = new ConcurrentHashMap<>(); + private final ConcurrentHashMap inProgressGenTasksByLodPos = new ConcurrentHashMap<>(); // granularity is the detail level for batching world generator requests together public final byte maxGranularity; @@ -89,8 +90,8 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb // debug variables to test for duplicate world generator requests // /** limits how many of the previous world gen requests we should track */ private static final int MAX_ALREADY_GENERATED_COUNT = 100; - private final HashMap alreadyGeneratedPosHashSet = new HashMap<>(MAX_ALREADY_GENERATED_COUNT); - private final Queue alreadyGeneratedPosQueue = new LinkedList<>(); + private final HashMap alreadyGeneratedPosHashSet = new HashMap<>(MAX_ALREADY_GENERATED_COUNT); + private final LongArrayFIFOQueue alreadyGeneratedPosQueue = new LongArrayFIFOQueue(); /** just used for rendering to the F3 menu */ private int estimatedTotalTaskCount = 0; @@ -131,7 +132,7 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb //=================// @Override - public CompletableFuture submitGenTask(OldDhSectionPos pos, byte requiredDataDetail, IWorldGenTaskTracker tracker) + public CompletableFuture submitGenTask(long pos, byte requiredDataDetail, IWorldGenTaskTracker tracker) { // the generator is shutting down, don't add new tasks if (this.generatorClosingFuture != null) @@ -151,7 +152,7 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb } // Assert that the data at least can fill in 1 single ChunkSizedFullDataAccessor - LodUtil.assertTrue(pos.getDetailLevel() > requiredDataDetail + LodUtil.CHUNK_DETAIL_LEVEL); + LodUtil.assertTrue(DhSectionPos.getDetailLevel(pos) > requiredDataDetail + LodUtil.CHUNK_DETAIL_LEVEL); CompletableFuture future = new CompletableFuture<>(); @@ -160,11 +161,11 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb } @Override - public void removeRetrievalRequestIf(Function removeIf) + public void removeRetrievalRequestIf(DhSectionPos.ICancelablePrimitiveLongConsumer removeIf) { this.waitingTasks.forEachKey(100, (genPos) -> { - if (removeIf.apply(genPos)) + if (removeIf.accept(genPos)) { this.waitingTasks.remove(genPos); } @@ -254,7 +255,7 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb Mapper closestTaskMap = this.waitingTasks.reduceEntries(1024, - entry -> new Mapper(entry.getValue(), entry.getValue().pos.getSectionBBoxPos().getCenterBlockPos().toPos2D().chebyshevDist(targetPos.toPos2D())), + entry -> new Mapper(entry.getValue(), DhSectionPos.getSectionBBoxPos(entry.getValue().pos).getCenterBlockPos().toPos2D().chebyshevDist(targetPos.toPos2D())), (aMapper, bMapper) -> aMapper.dist < bMapper.dist ? aMapper : bMapper); if (closestTaskMap == null) @@ -307,16 +308,16 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb // split up the task and add each one to the tree LinkedList> childFutures = new LinkedList<>(); - OldDhSectionPos sectionPos = new OldDhSectionPos(closestTask.pos.getDetailLevel(), closestTask.pos.getX(), closestTask.pos.getZ()); + long sectionPos = closestTask.pos; WorldGenTask finalClosestTask = closestTask; - sectionPos.forEachChild((childDhSectionPos) -> + DhSectionPos.forEachChild((childDhSectionPos) -> { CompletableFuture newFuture = new CompletableFuture<>(); childFutures.add(newFuture); - WorldGenTask newGenTask = new WorldGenTask(childDhSectionPos, childDhSectionPos.getDetailLevel(), finalClosestTask.taskTracker, newFuture); + WorldGenTask newGenTask = new WorldGenTask(childDhSectionPos, DhSectionPos.getDetailLevel(childDhSectionPos), finalClosestTask.taskTracker, newFuture); this.waitingTasks.put(newGenTask.pos, newGenTask); - }); + }, sectionPos); // send the child futures to the future recipient, to notify them of the new tasks closestTask.future.complete(WorldGenResult.CreateSplit(childFutures)); @@ -329,12 +330,12 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb private boolean tryStartingWorldGenTaskGroup(InProgressWorldGenTaskGroup newTaskGroup) { byte taskDetailLevel = newTaskGroup.group.dataDetail; - OldDhSectionPos taskPos = newTaskGroup.group.pos; - byte granularity = (byte) (taskPos.getDetailLevel() - taskDetailLevel); + long taskPos = newTaskGroup.group.pos; + byte granularity = (byte) (DhSectionPos.getDetailLevel(taskPos) - taskDetailLevel); LodUtil.assertTrue(granularity >= this.minGranularity && granularity <= this.maxGranularity); LodUtil.assertTrue(taskDetailLevel >= this.highestDataDetail && taskDetailLevel <= this.lowestDataDetail); - DhChunkPos chunkPosMin = new DhChunkPos(taskPos.getSectionBBoxPos().getCornerBlockPos()); + DhChunkPos chunkPosMin = new DhChunkPos(DhSectionPos.getSectionBBoxPos(taskPos).getCornerBlockPos()); // check if this is a duplicate generation task if (this.alreadyGeneratedPosHashSet.containsKey(newTaskGroup.group.pos)) @@ -343,16 +344,16 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb //LOGGER.trace("Duplicate generation section " + taskPos + " with granularity [" + granularity + "] at " + chunkPosMin + ". Skipping..."); // sending a success result is necessary to make sure the render sections are reloaded correctly - newTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(new OldDhSectionPos(granularity, taskPos.getX(), taskPos.getZ())))); + newTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(DhSectionPos.encode(granularity, DhSectionPos.getX(taskPos), DhSectionPos.getZ(taskPos))))); return false; } this.alreadyGeneratedPosHashSet.put(newTaskGroup.group.pos, Thread.currentThread().getStackTrace()); - this.alreadyGeneratedPosQueue.add(newTaskGroup.group.pos); + this.alreadyGeneratedPosQueue.enqueue(newTaskGroup.group.pos); // remove extra tracked duplicate positions while (this.alreadyGeneratedPosQueue.size() > MAX_ALREADY_GENERATED_COUNT) { - OldDhSectionPos posToRemove = this.alreadyGeneratedPosQueue.poll(); + long posToRemove = this.alreadyGeneratedPosQueue.dequeueLong(); this.alreadyGeneratedPosHashSet.remove(posToRemove); } @@ -380,8 +381,7 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb } else { - //LOGGER.info("Section generation at "+pos+" completed"); - newTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(new OldDhSectionPos(granularity, taskPos.getX(), taskPos.getZ())))); + newTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(DhSectionPos.encode(granularity, DhSectionPos.getX(taskPos), DhSectionPos.getZ(taskPos))))); } boolean worked = this.inProgressGenTasksByLodPos.remove(taskPos, newTaskGroup); LodUtil.assertTrue(worked); @@ -624,9 +624,9 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb // helper methods // //================// - private boolean canGeneratePos(byte worldGenTaskGroupDetailLevel /*when in doubt use 0*/ , OldDhSectionPos taskPos) + private boolean canGeneratePos(byte worldGenTaskGroupDetailLevel /*when in doubt use 0*/ , long taskPos) { - byte granularity = (byte) (taskPos.getDetailLevel() - worldGenTaskGroupDetailLevel); + byte granularity = (byte) (DhSectionPos.getDetailLevel(taskPos) - worldGenTaskGroupDetailLevel); return (granularity >= this.minGranularity && granularity <= this.maxGranularity); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenResult.java b/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenResult.java index b5b994e73..f5f1ed38c 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenResult.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenResult.java @@ -19,7 +19,7 @@ package com.seibel.distanthorizons.core.generation.tasks; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import java.util.Collection; import java.util.LinkedList; @@ -30,15 +30,15 @@ public class WorldGenResult /** true if terrain was generated */ public final boolean success; /** the position that was generated, will be null if nothing was generated */ - public final OldDhSectionPos pos; + public final long pos; /** if a position is too high detail for world generator to handle it, these futures are for its 4 children positions after being split up. */ public final LinkedList> childFutures = new LinkedList<>(); - public static WorldGenResult CreateSplit(Collection> siblingFutures) { return new WorldGenResult(false, null, siblingFutures); } - public static WorldGenResult CreateFail() { return new WorldGenResult(false, null, null); } - public static WorldGenResult CreateSuccess(OldDhSectionPos pos) { return new WorldGenResult(true, pos, null); } - private WorldGenResult(boolean success, OldDhSectionPos pos, Collection> childFutures) + public static WorldGenResult CreateSplit(Collection> siblingFutures) { return new WorldGenResult(false, 0, siblingFutures); } + public static WorldGenResult CreateFail() { return new WorldGenResult(false, 0, null); } + public static WorldGenResult CreateSuccess(long pos) { return new WorldGenResult(true, pos, null); } + private WorldGenResult(boolean success, long pos, Collection> childFutures) { this.success = success; this.pos = pos; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenTask.java b/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenTask.java index ad85df4c6..69f70a32b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenTask.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenTask.java @@ -19,7 +19,7 @@ package com.seibel.distanthorizons.core.generation.tasks; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import java.util.concurrent.CompletableFuture; @@ -29,14 +29,14 @@ import java.util.concurrent.CompletableFuture; */ public final class WorldGenTask { - public final OldDhSectionPos pos; + public final long pos; public final byte dataDetailLevel; public final IWorldGenTaskTracker taskTracker; public final CompletableFuture future; - public WorldGenTask(OldDhSectionPos pos, byte dataDetail, IWorldGenTaskTracker taskTracker, CompletableFuture future) + public WorldGenTask(long pos, byte dataDetail, IWorldGenTaskTracker taskTracker, CompletableFuture future) { this.dataDetailLevel = dataDetail; this.pos = pos; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenTaskGroup.java b/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenTaskGroup.java index 413512a8e..aa7178deb 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenTaskGroup.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenTaskGroup.java @@ -20,7 +20,7 @@ package com.seibel.distanthorizons.core.generation.tasks; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import java.util.Iterator; import java.util.LinkedList; @@ -33,14 +33,14 @@ import java.util.function.Consumer; @Deprecated // TODO look into how these are used and if they should continue to be used public final class WorldGenTaskGroup { - public final OldDhSectionPos pos; + public final long pos; public byte dataDetail; /** Only accessed by the generator polling thread */ public final LinkedList worldGenTasks = new LinkedList<>(); - public WorldGenTaskGroup(OldDhSectionPos pos, byte dataDetail) + public WorldGenTaskGroup(long pos, byte dataDetail) { this.pos = pos; this.dataDetail = dataDetail; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java index 7b197e509..080130820 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java @@ -24,7 +24,7 @@ import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSour import com.seibel.distanthorizons.core.dataObjects.transformers.ChunkToLodBuilder; import com.seibel.distanthorizons.core.file.fullDatafile.DelayedFullDataSourceSaveCache; import com.seibel.distanthorizons.core.pos.DhChunkPos; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector; @@ -36,8 +36,8 @@ public abstract class AbstractDhLevel implements IDhLevel public final ChunkToLodBuilder chunkToLodBuilder; protected final DelayedFullDataSourceSaveCache delayedFullDataSourceSaveCache = new DelayedFullDataSourceSaveCache(this::onDataSourceSave, 2_000); - /** contains the {@link DhChunkPos} for each {@link OldDhSectionPos} that are queued to save via {@link AbstractDhLevel#delayedFullDataSourceSaveCache} */ - protected final ConcurrentHashMap> updatedChunkPosSetBySectionPos = new ConcurrentHashMap<>(); + /** contains the {@link DhChunkPos} for each {@link DhSectionPos} that are queued to save via {@link AbstractDhLevel#delayedFullDataSourceSaveCache} */ + protected final ConcurrentHashMap> updatedChunkPosSetBySectionPos = new ConcurrentHashMap<>(); 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 c4fab8db3..d9fd01de1 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 @@ -29,7 +29,7 @@ import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.f3.F3Screen; import com.seibel.distanthorizons.core.pos.DhBlockPos2D; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.render.LodQuadTree; import com.seibel.distanthorizons.core.render.RenderBufferHandler; import com.seibel.distanthorizons.core.render.renderer.LodRenderer; @@ -313,7 +313,7 @@ public class ClientLevelModule implements Closeable, AbstractDataSourceHandler.I } } - public void reloadPos(OldDhSectionPos pos) + public void reloadPos(long pos) { ClientRenderState clientRenderState = this.ClientRenderStateRef.get(); if (clientRenderState != null && clientRenderState.quadtree != null) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java index 26eec2a53..6ec5e6713 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java @@ -28,7 +28,7 @@ import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhBlockPos2D; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; @@ -199,7 +199,7 @@ public class DhClientServerLevel extends AbstractDhLevel implements IDhClientLev } @Override - public void onWorldGenTaskComplete(OldDhSectionPos pos) + public void onWorldGenTaskComplete(long pos) { DebugRenderer.makeParticle( new DebugRenderer.BoxParticle( 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 b7e8599c1..ef40c5e89 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 @@ -23,7 +23,7 @@ import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSour import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2; import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure; import com.seibel.distanthorizons.core.pos.DhBlockPos2D; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper; @@ -105,7 +105,7 @@ public class DhServerLevel extends AbstractDhLevel implements IDhServerLevel public boolean hasSkyLight() { return this.serverLevelWrapper.hasSkyLight(); } @Override - public void onWorldGenTaskComplete(OldDhSectionPos pos) + public void onWorldGenTaskComplete(long pos) { //TODO: Send packet to client } 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 62a27e9c1..7678ec3e8 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 @@ -53,7 +53,7 @@ public class DhLodPos implements Comparable this.x = x; this.z = z; } - public DhLodPos(OldDhSectionPos sectionPos) { this(sectionPos.getDetailLevel(), sectionPos.getX(), sectionPos.getZ()); } + public DhLodPos(long sectionPos) { this(DhSectionPos.getDetailLevel(sectionPos), DhSectionPos.getX(sectionPos), DhSectionPos.getZ(sectionPos)); } @@ -162,10 +162,10 @@ public class DhLodPos implements Comparable } /** - * @param sectionDetailLevel This is different from the normal LOD Detail level, see {@link OldDhSectionPos} for more information + * @param sectionDetailLevel This is different from the normal LOD Detail level, see {@link DhSectionPos} for more information * @throws IllegalArgumentException if this position's detail level is lower than the output detail level */ - public OldDhSectionPos getSectionPosWithSectionDetailLevel(byte sectionDetailLevel) throws IllegalArgumentException + public long getSectionPosWithSectionDetailLevel(byte sectionDetailLevel) throws IllegalArgumentException { if (sectionDetailLevel < this.detailLevel) { @@ -174,7 +174,7 @@ public class DhLodPos implements Comparable DhLodPos lodPos = new DhLodPos(this.detailLevel, this.x, this.z); lodPos = lodPos.convertToDetailLevel(sectionDetailLevel); - return new OldDhSectionPos(lodPos.detailLevel, lodPos.x, lodPos.z); + return DhSectionPos.encode(lodPos.detailLevel, lodPos.x, lodPos.z); } 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 0c269ae4b..ea3044bae 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 @@ -23,6 +23,8 @@ import com.seibel.distanthorizons.core.enums.EDhDirection; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.coreapi.util.BitShiftUtil; +import java.util.function.LongConsumer; + /** * The position object used to define LOD objects in the quad trees.

* @@ -175,13 +177,15 @@ public class DhSectionPos /** @return the block X pos that represents the smallest X coordinate of this section */ public static int getMinCornerBlockX(long pos) { - int halfBlockWidth = DhSectionPos.getBlockWidth(pos) / 2; + // detail level 1 (2x2 blocks) is a special case, + // if this isn't done it will return (1,1) instead of (0,0) + int halfBlockWidth = (getDetailLevel(pos) != 1) ? (DhSectionPos.getBlockWidth(pos) / 2) : 0; return DhSectionPos.getCenterBlockPosX(pos) - halfBlockWidth; } /** @return the block Z pos that represents the smallest Z coordinate of this section */ public static int getMinCornerBlockZ(long pos) { - int halfBlockWidth = DhSectionPos.getBlockWidth(pos) / 2; + int halfBlockWidth = (getDetailLevel(pos) != 1) ? (DhSectionPos.getBlockWidth(pos) / 2) : 0; return DhSectionPos.getCenterBlockPosZ(pos) - halfBlockWidth; } @@ -298,7 +302,8 @@ public class DhSectionPos getZ(pos) + dir.getNormal().z); } - //public DhLodPos getSectionBBoxPos() { return new DhLodPos(this.detailLevel, this.x, this.z); } + @Deprecated + public static DhLodPos getSectionBBoxPos(long pos) { return new DhLodPos(getDetailLevel(pos), getX(pos), getZ(pos)); } @@ -329,7 +334,7 @@ public class DhSectionPos //===========// /** Applies the given consumer to all 4 of this position's children. */ - public static void forEachChild(IPrimitiveLongConsumer callback, long pos) throws IllegalArgumentException, IllegalStateException + public static void forEachChild(LongConsumer callback, long pos) throws IllegalArgumentException, IllegalStateException { for (int i = 0; i < 4; i++) { @@ -353,7 +358,7 @@ public class DhSectionPos } /** Applies the given consumer to all children of the position at the given section detail level. */ - public static void forEachChildAtDetailLevel(byte sectionDetailLevel, IPrimitiveLongConsumer callback, long pos) throws IllegalArgumentException, IllegalStateException + public static void forEachChildAtDetailLevel(byte sectionDetailLevel, LongConsumer callback, long pos) throws IllegalArgumentException, IllegalStateException { if (sectionDetailLevel == getDetailLevel(pos)) { @@ -368,7 +373,7 @@ public class DhSectionPos } /** Applies the given consumer to all children of the position at the given section detail level. */ - public static void forEachPosUpToDetailLevel(byte maxSectionDetailLevel, IPrimitiveLongConsumer callback, long pos) + public static void forEachPosUpToDetailLevel(byte maxSectionDetailLevel, LongConsumer callback, long pos) { callback.accept(pos); if (maxSectionDetailLevel == getDetailLevel(pos)) @@ -386,6 +391,7 @@ public class DhSectionPos //==============// public static String toString(long pos) { return getDetailLevel(pos) + "*" + getX(pos) + "," + getZ(pos); } + public static int hashCode(long pos) { return Long.hashCode(pos); } @@ -393,13 +399,6 @@ public class DhSectionPos // helper methods // //================// - /** Used instead of {@link java.util.function.Consumer} to prevent unnecessary (un)wrapping. */ - @FunctionalInterface - public interface IPrimitiveLongConsumer - { - void accept(long value); - } - /** Used instead of {@link java.util.function.Function} to prevent unnecessary (un)wrapping. */ @FunctionalInterface public interface ICancelablePrimitiveLongConsumer diff --git a/core/src/main/java/com/seibel/distanthorizons/core/pos/OldDhSectionPos.java b/core/src/main/java/com/seibel/distanthorizons/core/pos/OldDhSectionPos.java deleted file mode 100644 index 2c2aaadde..000000000 --- a/core/src/main/java/com/seibel/distanthorizons/core/pos/OldDhSectionPos.java +++ /dev/null @@ -1,448 +0,0 @@ -/* - * 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.pos; - -import com.seibel.distanthorizons.core.enums.EDhDirection; -import com.seibel.distanthorizons.coreapi.util.BitShiftUtil; -import com.seibel.distanthorizons.core.util.LodUtil; -import org.jetbrains.annotations.Nullable; - -import java.util.function.Consumer; -import java.util.function.Function; - -/** - * The position object used to define LOD objects in the quad trees.

- * - * A section contains 64 x 64 LOD columns at a given quality. - * The Section detail level is different from the LOD detail level. - * For the specifics of how they compare can be viewed in the constants {@link #SECTION_BLOCK_DETAIL_LEVEL}, - * {@link #SECTION_CHUNK_DETAIL_LEVEL}, and {@link #SECTION_REGION_DETAIL_LEVEL}).

- * - * Why does the smallest render section represent 2x2 MC chunks (section detail level 6)?
- * A section defines what unit the quad tree works in, because of that we don't want that unit to be too big or too small.
- * Too small, and we'll have 1,000s of sections running around, all needing individual files and render buffers.
- * Too big, and the LOD dropoff will be very noticeable.
- * With those thoughts in mind we decided on a smallest section size of 32 data points square (IE 2x2 chunks). - * - * @author Leetom - */ -public class OldDhSectionPos -{ - /** - * The lowest detail level a Section position can hold. - * This section DetailLevel holds 64 x 64 Block level (detail level 0) LODs. - */ - public final static byte SECTION_MINIMUM_DETAIL_LEVEL = 6; - - public final static byte SECTION_BLOCK_DETAIL_LEVEL = SECTION_MINIMUM_DETAIL_LEVEL + LodUtil.BLOCK_DETAIL_LEVEL; - public final static byte SECTION_CHUNK_DETAIL_LEVEL = SECTION_MINIMUM_DETAIL_LEVEL + LodUtil.CHUNK_DETAIL_LEVEL; - public final static byte SECTION_REGION_DETAIL_LEVEL = SECTION_MINIMUM_DETAIL_LEVEL + LodUtil.REGION_DETAIL_LEVEL; - - - protected byte detailLevel; - - /** in a sectionDetailLevel grid */ - protected int x; - /** in a sectionDetailLevel grid */ - protected int z; - - - - //==============// - // constructors // - //==============// - - public OldDhSectionPos(byte detailLevel, int x, int z) - { - this.detailLevel = detailLevel; - this.x = x; - this.z = z; - } - - public OldDhSectionPos(DhBlockPos blockPos) - { - this(LodUtil.BLOCK_DETAIL_LEVEL, blockPos.x, blockPos.z); - this.convertSelfToDetailLevel(OldDhSectionPos.SECTION_BLOCK_DETAIL_LEVEL); - } - public OldDhSectionPos(DhBlockPos2D blockPos) - { - this(LodUtil.BLOCK_DETAIL_LEVEL, blockPos.x, blockPos.z); - this.convertSelfToDetailLevel(OldDhSectionPos.SECTION_BLOCK_DETAIL_LEVEL); - } - - public OldDhSectionPos(DhChunkPos chunkPos) - { - this(LodUtil.CHUNK_DETAIL_LEVEL, chunkPos.x, chunkPos.z); - this.convertSelfToDetailLevel(OldDhSectionPos.SECTION_CHUNK_DETAIL_LEVEL); - } - - public OldDhSectionPos(byte detailLevel, DhLodPos dhLodPos) - { - this.detailLevel = detailLevel; - this.x = dhLodPos.x; - this.z = dhLodPos.z; - } - - - - //============// - // converters // - //============// - - /** - * 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 OldDhSectionPos convertNewToDetailLevel(byte newSectionDetailLevel) - { - OldDhSectionPos newPos = new OldDhSectionPos(this.detailLevel, this.x, this.z); - newPos.convertSelfToDetailLevel(newSectionDetailLevel); - - return newPos; - } - - /** uses the absolute detail level aka detail levels like {@link LodUtil#CHUNK_DETAIL_LEVEL} instead of the dhSectionPos detailLevels. */ - protected void convertSelfToDetailLevel(byte newDetailLevel) - { - // logic originally taken from DhLodPos - if (newDetailLevel >= this.detailLevel) - { - this.x = Math.floorDiv(this.x, BitShiftUtil.powerOfTwo(newDetailLevel - this.detailLevel)); - this.z = Math.floorDiv(this.z, BitShiftUtil.powerOfTwo(newDetailLevel - this.detailLevel)); - } - else - { - this.x = this.x * BitShiftUtil.powerOfTwo(this.detailLevel - newDetailLevel); - this.z = this.z * BitShiftUtil.powerOfTwo(this.detailLevel - newDetailLevel); - } - - this.detailLevel = newDetailLevel; - } - - - - //==================// - // property getters // - //==================// - - public byte getDetailLevel() { return this.detailLevel; } - - public int getX() { return this.x; } - public int getZ() { return this.z; } - - - - //=========// - // getters // - //=========// - - /** - * @deprecated use DhSectionPos instead - * @return the corner with the smallest X and Z coordinate - */ - @Deprecated - public DhLodPos getMinCornerLodPos() { return this.getMinCornerLodPos((byte) (this.detailLevel - 1)); } - /** - * @deprecated use DhSectionPos instead - * @return the corner with the smallest X and Z coordinate - */ - @Deprecated - 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 OldDhSectionPos}'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; - } - - public int getManhattanBlockDistance(DhBlockPos2D blockPos) - { - return Math.abs(this.getCenterBlockPosX() - blockPos.x) - + Math.abs(this.getCenterBlockPosZ() - blockPos.z); - } - - - - //==================// - // parent child pos // - //==================// - - /** - * Returns the DhLodPos 1 detail level lower

- * - * Relative child positions returned for each index:
- * 0 = (0,0) - North West
- * 1 = (1,0) - South West
- * 2 = (0,1) - North East
- * 3 = (1,1) - South East
- * - * @param child0to3 must be an int between 0 and 3 - */ - public OldDhSectionPos getChildByIndex(int child0to3) throws IllegalArgumentException, IllegalStateException - { - if (child0to3 < 0 || child0to3 > 3) - { - throw new IllegalArgumentException("child0to3 must be between 0 and 3"); - } - if (this.detailLevel <= 0) - { - throw new IllegalStateException("section detail must be greater than 0"); - } - - return new OldDhSectionPos((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.x & 1) + BitShiftUtil.square(this.z & 1); } - - public OldDhSectionPos getParentPos() { return new OldDhSectionPos((byte) (this.detailLevel + 1), BitShiftUtil.half(this.x), BitShiftUtil.half(this.z)); } - - - - - public OldDhSectionPos getAdjacentPos(EDhDirection dir) - { - return new OldDhSectionPos(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 contains(OldDhSectionPos 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) - { - for (int i = 0; i < 4; i++) - { - callback.accept(this.getChildByIndex(i)); - } - } - - /** Applies the given consumer to all children of the position at the given section detail level. */ - public void forEachChildDownToDetailLevel(byte minSectionDetailLevel, Function callback) - { - boolean stop = callback.apply(this); - if (stop || minSectionDetailLevel == this.detailLevel) - { - return; - } - - for (int i = 0; i < 4; i++) - { - this.getChildByIndex(i).forEachChildDownToDetailLevel(minSectionDetailLevel, callback); - } - } - - /** Applies the given consumer to all children of the position at the given section detail level. */ - public void forEachChildAtDetailLevel(byte sectionDetailLevel, Consumer callback) - { - if (sectionDetailLevel == this.detailLevel) - { - callback.accept(this); - return; - } - - for (int i = 0; i < 4; i++) - { - this.getChildByIndex(i).forEachChildAtDetailLevel(sectionDetailLevel, callback); - } - } - - /** Applies the given consumer to all children of the position at the given section detail level. */ - public void forEachPosUpToDetailLevel(byte maxSectionDetailLevel, Consumer callback) - { - callback.accept(this); - if (maxSectionDetailLevel == this.detailLevel) - { - return; - } - - this.getParentPos().forEachPosUpToDetailLevel(maxSectionDetailLevel, callback); - } - - - - //===========// - // overrides // - //===========// - - @Override - public String toString() { return "{" + this.detailLevel + "*" + this.x + "," + this.z + "}"; } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - if (obj == null || obj.getClass() != OldDhSectionPos.class) - { - return false; - } - - OldDhSectionPos that = (OldDhSectionPos) obj; - return this.detailLevel == that.detailLevel && - this.x == that.x && - this.z == that.z; - } - - @Override - public int hashCode() - { - return Integer.hashCode(this.detailLevel) ^ // XOR - Integer.hashCode(this.x) ^ // XOR - Integer.hashCode(this.z); - } - - - - //=============// - // sub classes // - //=============// - - /** - * Identical to {@link OldDhSectionPos} except it is mutable. - * See {@link OldDhSectionPos} for full documentation. - * - * @see OldDhSectionPos - */ - public static class DhMutableSectionPos extends OldDhSectionPos - { - - //==============// - // 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; } - - } - -} 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 2441fadfe..2da0f1168 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 @@ -28,7 +28,7 @@ import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV import com.seibel.distanthorizons.core.level.IDhClientLevel; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos2D; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.render.renderer.DebugRenderer; import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable; import com.seibel.distanthorizons.core.util.LodUtil; @@ -36,6 +36,7 @@ import com.seibel.distanthorizons.core.util.ThreadUtil; import com.seibel.distanthorizons.core.util.objects.quadTree.QuadNode; import com.seibel.distanthorizons.core.util.objects.quadTree.QuadTree; import com.seibel.distanthorizons.coreapi.util.MathUtil; +import it.unimi.dsi.fastutil.longs.LongIterator; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.NotNull; @@ -68,10 +69,10 @@ public class LodQuadTree extends QuadTree implements IDebugRen private final FullDataSourceProviderV2 fullDataSourceProvider; /** - * This holds every {@link OldDhSectionPos} that should be reloaded next tick.
+ * This holds every {@link DhSectionPos} that should be reloaded next tick.
* This is a {@link ConcurrentLinkedQueue} because new sections can be added to this list via the world generator threads. */ - private final ConcurrentLinkedQueue sectionsToReload = new ConcurrentLinkedQueue<>(); + private final ConcurrentLinkedQueue sectionsToReload = new ConcurrentLinkedQueue<>(); private final IDhClientLevel level; //FIXME: Proper hierarchy to remove this reference! private final ConfigChangeListener horizontalScaleChangeListener; private final ReentrantLock treeReadWriteLock = new ReentrantLock(); @@ -181,12 +182,12 @@ public class LodQuadTree extends QuadTree implements IDebugRen // reload any sections that need it - OldDhSectionPos pos; + Long pos; while ((pos = this.sectionsToReload.poll()) != null) { // 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.getDetailLevel() <= this.treeMinDetailLevel) + while (DhSectionPos.getDetailLevel(pos) <= this.treeMinDetailLevel) { try { @@ -199,7 +200,7 @@ public class LodQuadTree extends QuadTree implements IDebugRen catch (IndexOutOfBoundsException e) { /* the section is now out of bounds, it doesn't need to be reloaded */ } - pos = pos.getParentPos(); + pos = DhSectionPos.getParentPos(pos); } } @@ -207,11 +208,11 @@ public class LodQuadTree extends QuadTree implements IDebugRen // walk through each root node ArrayList nodesNeedingRetrieval = new ArrayList<>(); ArrayList nodesNeedingLoading = new ArrayList<>(); - Iterator rootPosIterator = this.rootNodePosIterator(); + LongIterator rootPosIterator = this.rootNodePosIterator(); while (rootPosIterator.hasNext()) { // make sure all root nodes have been created - OldDhSectionPos rootPos = rootPosIterator.next(); + long rootPos = rootPosIterator.nextLong(); if (this.getNode(rootPos) == null) { this.setValue(rootPos, new LodRenderSection(rootPos, this, this.level, this.fullDataSourceProvider)); @@ -232,8 +233,8 @@ public class LodQuadTree extends QuadTree implements IDebugRen nodesNeedingLoading.sort((a, b) -> { - int aDist = a.pos.getManhattanBlockDistance(playerPos); - int bDist = b.pos.getManhattanBlockDistance(playerPos); + int aDist = DhSectionPos.getManhattanBlockDistance(playerPos, a.pos); + int bDist = DhSectionPos.getManhattanBlockDistance(playerPos, b.pos); return Integer.compare(aDist, bDist); }); @@ -250,7 +251,7 @@ public class LodQuadTree extends QuadTree implements IDebugRen /** @return whether the current position is able to render (note: not if it IS rendering, just if it is ABLE to.) */ private boolean recursivelyUpdateRenderSectionNode( DhBlockPos2D playerPos, - QuadNode rootNode, QuadNode quadNode, OldDhSectionPos sectionPos, + QuadNode rootNode, QuadNode quadNode, long sectionPos, boolean parentSectionIsRendering, ArrayList nodesNeedingRetrieval, ArrayList nodesNeedingLoading) @@ -292,20 +293,20 @@ public class LodQuadTree extends QuadTree implements IDebugRen //byte expectedDetailLevel = DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL + 3; // can be used instead of the following logic for testing byte expectedDetailLevel = this.calculateExpectedDetailLevel(playerPos, sectionPos); expectedDetailLevel = (byte) Math.min(expectedDetailLevel, this.minRenderDetailLevel); - expectedDetailLevel += OldDhSectionPos.SECTION_BLOCK_DETAIL_LEVEL; + expectedDetailLevel += DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL; - if (sectionPos.getDetailLevel() > expectedDetailLevel) + if (DhSectionPos.getDetailLevel(sectionPos) > expectedDetailLevel) { // section detail level too high // boolean thisPosIsRendering = renderSection.renderingEnabled; boolean allChildrenSectionsAreLoaded = true; // recursively update all child render sections - Iterator childPosIterator = quadNode.getChildPosIterator(); + LongIterator childPosIterator = quadNode.getChildPosIterator(); while (childPosIterator.hasNext()) { - OldDhSectionPos childPos = childPosIterator.next(); + long childPos = childPosIterator.nextLong(); QuadNode childNode = rootNode.getNode(childPos); boolean childSectionLoaded = this.recursivelyUpdateRenderSectionNode(playerPos, rootNode, childNode, childPos, thisPosIsRendering || parentSectionIsRendering, nodesNeedingRetrieval, nodesNeedingLoading); @@ -338,7 +339,7 @@ public class LodQuadTree extends QuadTree implements IDebugRen childPosIterator = quadNode.getChildPosIterator(); while (childPosIterator.hasNext()) { - OldDhSectionPos childPos = childPosIterator.next(); + long childPos = childPosIterator.nextLong(); QuadNode childNode = rootNode.getNode(childPos); boolean childSectionLoaded = this.recursivelyUpdateRenderSectionNode(playerPos, rootNode, childNode, childPos, parentSectionIsRendering, nodesNeedingRetrieval, nodesNeedingLoading); @@ -348,7 +349,7 @@ public class LodQuadTree extends QuadTree implements IDebugRen { // FIXME having world generation enabled in a pre-generated world that doesn't have any DH data can cause this to happen // surprisingly reloadPos() doesn't appear to be the culprit, maybe there is an issue with reloading/changing the full data source? - //LOGGER.warn("Potential QuadTree concurrency issue. All child sections should be enabled and ready to render for pos: "+sectionPos); + //LOGGER.warn("Potential QuadTree concurrency issue. All child sections should be enabled and ready to render for pos: "+DhSectionPos.toString(sectionPos)); } // this section is now being rendered via its children @@ -356,7 +357,7 @@ public class LodQuadTree extends QuadTree implements IDebugRen } } // 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.getDetailLevel() == expectedDetailLevel || sectionPos.getDetailLevel() == expectedDetailLevel - 1) + else if (DhSectionPos.getDetailLevel(sectionPos) == expectedDetailLevel || DhSectionPos.getDetailLevel(sectionPos) == expectedDetailLevel - 1) { // this is the detail level we want to render // @@ -445,7 +446,7 @@ public class LodQuadTree extends QuadTree implements IDebugRen * @param sectionPos section position * @return detail level of this section pos */ - public byte calculateExpectedDetailLevel(DhBlockPos2D playerPos, OldDhSectionPos sectionPos) { return this.getDetailLevelFromDistance(playerPos.dist(sectionPos.getCenterBlockPosX(), sectionPos.getCenterBlockPosZ())); } + public byte calculateExpectedDetailLevel(DhBlockPos2D playerPos, long sectionPos) { return this.getDetailLevelFromDistance(playerPos.dist(DhSectionPos.getCenterBlockPosX(sectionPos), DhSectionPos.getCenterBlockPosZ(sectionPos))); } private byte getDetailLevelFromDistance(double distance) { double maxDetailDistance = this.getDrawDistanceFromDetail(Byte.MAX_VALUE - 1); @@ -537,16 +538,8 @@ public class LodQuadTree extends QuadTree implements IDebugRen * Can be called whenever a render section's data needs to be refreshed.
* This should be called whenever a world generation task is completed or if the connected server has new data to show. */ - public void reloadPos(@NotNull OldDhSectionPos pos) + public void reloadPos(long pos) { - if (pos == null) - { - // shouldn't happen, but James saw it happen once, so this is here just in case - LOGGER.warn("reloadPos given a null pos."); - return; - } - - this.sectionsToReload.add(pos); // the adjacent locations also need to be updated to make sure lighting @@ -554,7 +547,7 @@ public class LodQuadTree extends QuadTree implements IDebugRen // and lights may not show up over LOD borders for (EDhDirection direction : EDhDirection.ADJ_DIRECTIONS) { - this.sectionsToReload.add(pos.getAdjacentPos(direction)); + this.sectionsToReload.add(DhSectionPos.getAdjacentPos(direction, pos)); } } @@ -574,8 +567,8 @@ public class LodQuadTree extends QuadTree implements IDebugRen // sort the nodes from nearest to farthest nodesNeedingRetrieval.sort((a, b) -> { - int aDist = a.pos.getManhattanBlockDistance(playerPos); - int bDist = b.pos.getManhattanBlockDistance(playerPos); + int aDist = DhSectionPos.getManhattanBlockDistance(playerPos, a.pos); + int bDist = DhSectionPos.getManhattanBlockDistance(playerPos, b.pos); return Integer.compare(aDist, bDist); }); 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 f27b503a6..a95de0e83 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 @@ -28,12 +28,13 @@ import com.seibel.distanthorizons.core.enums.EDhDirection; import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2; import com.seibel.distanthorizons.core.level.IDhClientLevel; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.render.glObject.GLProxy; import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable; import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.ColumnRenderBuffer; import com.seibel.distanthorizons.core.render.renderer.DebugRenderer; import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil; +import it.unimi.dsi.fastutil.longs.LongArrayList; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.Nullable; @@ -56,7 +57,7 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable - public final OldDhSectionPos pos; + public final long pos; private final IDhClientLevel level; @WillNotClose @@ -85,7 +86,7 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable private boolean missingPositionsCalculated = false; /** should be an empty array if no positions need to be generated */ - private ArrayList missingGenerationPos = null; + private LongArrayList missingGenerationPos = null; @@ -93,7 +94,7 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable // constructor // //=============// - public LodRenderSection(OldDhSectionPos pos, LodQuadTree quadTree, IDhClientLevel level, FullDataSourceProviderV2 fullDataSourceProvider) + public LodRenderSection(long pos, LodQuadTree quadTree, IDhClientLevel level, FullDataSourceProviderV2 fullDataSourceProvider) { this.pos = pos; this.quadTree = quadTree; @@ -236,7 +237,7 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable EDhDirection direction = EDhDirection.ADJ_DIRECTIONS[i]; int arrayIndex = direction.ordinal() - 2; - OldDhSectionPos adjPos = this.pos.getAdjacentPos(direction); + long adjPos = DhSectionPos.getAdjacentPos(direction, this.pos); try { LodRenderSection adjRenderSection = this.quadTree.getValue(adjPos); @@ -350,7 +351,7 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable break; } - OldDhSectionPos pos = this.missingGenerationPos.remove(i); + long pos = this.missingGenerationPos.removeLong(i); boolean positionQueued = this.fullDataSourceProvider.queuePositionForRetrieval(pos); if (!positionQueued) { @@ -443,7 +444,7 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable try { - executor.execute(() -> this.fullDataSourceProvider.removeRetrievalRequestIf((genPos) -> this.pos.contains(genPos))); + executor.execute(() -> this.fullDataSourceProvider.removeRetrievalRequestIf((genPos) -> DhSectionPos.contains(this.pos, genPos))); } catch (RejectedExecutionException ignore) { /* If this happens that means everything is already shut down and no additional cleanup will be necessary */ } 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 b727ed8a0..3c151d7d9 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 @@ -31,7 +31,7 @@ import com.seibel.distanthorizons.core.enums.EDhDirection; 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.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.pos.Pos2D; import com.seibel.distanthorizons.core.render.renderer.LodRenderer; import com.seibel.distanthorizons.core.util.LodUtil; @@ -205,8 +205,8 @@ public class RenderBufferHandler implements AutoCloseable // Now that we have the axis directions, we can sort the render list Comparator farToNearComparator = (loadedBufferA, loadedBufferB) -> { - Pos2D aPos = loadedBufferA.pos.getCenterBlockPos().toPos2D(); - Pos2D bPos = loadedBufferB.pos.getCenterBlockPos().toPos2D(); + Pos2D aPos = DhSectionPos.getCenterBlockPos(loadedBufferA.pos).toPos2D(); + Pos2D bPos = DhSectionPos.getCenterBlockPos(loadedBufferB.pos).toPos2D(); if (true) { int aManhattanDistance = aPos.manhattanDist(cPos); @@ -243,7 +243,7 @@ public class RenderBufferHandler implements AutoCloseable return abPosDifference; } - return loadedBufferA.pos.getDetailLevel() - loadedBufferB.pos.getDetailLevel(); // If all else fails, sort by detail + return DhSectionPos.getDetailLevel(loadedBufferA.pos) - DhSectionPos.getDetailLevel(loadedBufferB.pos); // If all else fails, sort by detail }; this.loadedNearToFarBuffers = new SortedArraySet<>((a, b) -> -farToNearComparator.compare(a, b)); // TODO is the comparator named wrong? @@ -309,7 +309,7 @@ public class RenderBufferHandler implements AutoCloseable { QuadNode node = nodeIterator.next(); - OldDhSectionPos sectionPos = node.sectionPos; + long sectionPos = node.sectionPos; LodRenderSection renderSection = node.value; if (renderSection == null) { @@ -320,7 +320,7 @@ public class RenderBufferHandler implements AutoCloseable { if (enableFrustumCulling) { - DhLodPos lodBounds = renderSection.pos.getSectionBBoxPos(); + DhLodPos lodBounds = DhSectionPos.getSectionBBoxPos(renderSection.pos); int blockMinX = lodBounds.getMinX().toBlockWidth(); int blockMinZ = lodBounds.getMinZ().toBlockWidth(); int lodBlockWidth = lodBounds.getBlockWidth(); @@ -425,9 +425,9 @@ public class RenderBufferHandler implements AutoCloseable private static class LoadedRenderBuffer { public final ColumnRenderBuffer buffer; - public final OldDhSectionPos pos; + public final long pos; - LoadedRenderBuffer(ColumnRenderBuffer buffer, OldDhSectionPos pos) + LoadedRenderBuffer(ColumnRenderBuffer buffer, long pos) { this.buffer = buffer; this.pos = pos; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java index 938014339..42d893b9d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java @@ -28,7 +28,7 @@ import com.seibel.distanthorizons.core.logging.ConfigBasedLogger; import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger; import com.seibel.distanthorizons.core.pos.DhBlockPos2D; import com.seibel.distanthorizons.core.pos.DhLodPos; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.render.glObject.GLState; import com.seibel.distanthorizons.core.render.glObject.buffer.GLElementBuffer; import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer; @@ -247,6 +247,8 @@ public class DebugRenderer public Vec3f b; public Color color; + + public Box(Vec3f a, Vec3f b, Color color) { this.a = a; @@ -288,14 +290,14 @@ public class DebugRenderer this.color = color; } - public Box(OldDhSectionPos pos, float minY, float maxY, float marginPercent, Color color) + public Box(long pos, float minY, float maxY, float marginPercent, Color color) { - this(pos.getSectionBBoxPos(), minY, maxY, marginPercent, color); + this(DhSectionPos.getSectionBBoxPos(pos), minY, maxY, marginPercent, color); } - public Box(OldDhSectionPos pos, float y, float yDiff, Object hash, float marginPercent, Color color) + public Box(long pos, float y, float yDiff, Object hash, float marginPercent, Color color) { - this(pos.getSectionBBoxPos(), y, yDiff, hash, marginPercent, color); + this(DhSectionPos.getSectionBBoxPos(pos), y, yDiff, hash, marginPercent, color); } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/sql/dto/FullDataSourceV1DTO.java b/core/src/main/java/com/seibel/distanthorizons/core/sql/dto/FullDataSourceV1DTO.java index af9263a07..9a8f4f37f 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/sql/dto/FullDataSourceV1DTO.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/sql/dto/FullDataSourceV1DTO.java @@ -22,7 +22,7 @@ package com.seibel.distanthorizons.core.sql.dto; import com.seibel.distanthorizons.api.enums.config.EDhApiDataCompressionMode; import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiWorldGenerationStep; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV1; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.util.objects.dataStreams.DhDataInputStream; import java.io.ByteArrayInputStream; @@ -32,9 +32,9 @@ import java.io.InputStream; /** * Handles storing{@link FullDataSourceV1}'s in the database. */ -public class FullDataSourceV1DTO implements IBaseDTO +public class FullDataSourceV1DTO implements IBaseDTO { - public OldDhSectionPos pos; + public long pos; public int checksum; public byte dataDetailLevel; public EDhApiWorldGenerationStep worldGenStep; @@ -52,7 +52,7 @@ public class FullDataSourceV1DTO implements IBaseDTO // constructor // //=============// - public FullDataSourceV1DTO(OldDhSectionPos pos, int checksum, byte dataDetailLevel, EDhApiWorldGenerationStep worldGenStep, String dataType, byte binaryDataFormatVersion, byte[] dataArray) + public FullDataSourceV1DTO(long pos, int checksum, byte dataDetailLevel, EDhApiWorldGenerationStep worldGenStep, String dataType, byte binaryDataFormatVersion, byte[] dataArray) { this.pos = pos; this.checksum = checksum; @@ -81,7 +81,7 @@ public class FullDataSourceV1DTO implements IBaseDTO //===========// @Override - public OldDhSectionPos getKey() { return this.pos; } + public Long getKey() { return this.pos; } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/sql/dto/FullDataSourceV2DTO.java b/core/src/main/java/com/seibel/distanthorizons/core/sql/dto/FullDataSourceV2DTO.java index 55eef4062..1d8813d1f 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/sql/dto/FullDataSourceV2DTO.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/sql/dto/FullDataSourceV2DTO.java @@ -24,7 +24,7 @@ import com.seibel.distanthorizons.api.enums.config.EDhApiWorldCompressionMode; import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiWorldGenerationStep; import com.seibel.distanthorizons.core.dataObjects.fullData.FullDataPointIdMap; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.util.FullDataPointUtil; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.objects.DataCorruptedException; @@ -39,12 +39,12 @@ import java.util.zip.Adler32; import java.util.zip.CheckedOutputStream; /** handles storing {@link FullDataSourceV2}'s in the database. */ -public class FullDataSourceV2DTO implements IBaseDTO +public class FullDataSourceV2DTO implements IBaseDTO { public static final boolean VALIDATE_INPUT_DATAPOINTS = true; - public OldDhSectionPos pos; + public long pos; public int levelMinY; @@ -91,7 +91,7 @@ public class FullDataSourceV2DTO implements IBaseDTO } public FullDataSourceV2DTO( - OldDhSectionPos pos, + long pos, int dataChecksum, byte[] compressedColumnGenStepByteArray, byte[] compressedWorldCompressionModeByteArray, byte dataFormatVersion, byte compressionModeValue, byte[] compressedDataByteArray, long lastModifiedUnixDateTime, long createdUnixDateTime, byte[] compressedMappingByteArray, boolean applyToParent, @@ -342,7 +342,7 @@ public class FullDataSourceV2DTO implements IBaseDTO return byteArrayOutputStream.toByteArray(); } - private static FullDataPointIdMap readBlobToDataMapping(byte[] compressedMappingByteArray, OldDhSectionPos pos, @NotNull ILevelWrapper levelWrapper, EDhApiDataCompressionMode compressionModeEnum) throws IOException, InterruptedException, DataCorruptedException + private static FullDataPointIdMap readBlobToDataMapping(byte[] compressedMappingByteArray, long pos, @NotNull ILevelWrapper levelWrapper, EDhApiDataCompressionMode compressionModeEnum) throws IOException, InterruptedException, DataCorruptedException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(compressedMappingByteArray); DhDataInputStream compressedIn = new DhDataInputStream(byteArrayInputStream, compressionModeEnum); @@ -358,7 +358,7 @@ public class FullDataSourceV2DTO implements IBaseDTO //===========// @Override - public OldDhSectionPos getKey() { return this.pos; } + public Long getKey() { return this.pos; } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/FullDataSourceV1Repo.java b/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/FullDataSourceV1Repo.java index 062dec00d..d02cc9a39 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/FullDataSourceV1Repo.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/FullDataSourceV1Repo.java @@ -21,9 +21,10 @@ package com.seibel.distanthorizons.core.sql.repo; import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiWorldGenerationStep; import com.seibel.distanthorizons.core.pos.DhSectionPos; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.sql.dto.FullDataSourceV1DTO; import com.seibel.distanthorizons.coreapi.util.StringUtil; +import it.unimi.dsi.fastutil.longs.LongArrayList; import org.jetbrains.annotations.Nullable; import java.sql.PreparedStatement; @@ -32,7 +33,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -public class FullDataSourceV1Repo extends AbstractDhRepo +public class FullDataSourceV1Repo extends AbstractDhRepo { public static final String TABLE_NAME = "Legacy_FullData_V1"; @@ -57,7 +58,7 @@ public class FullDataSourceV1Repo extends AbstractDhRepo objectMap) throws ClassCastException { String posString = (String) objectMap.get("DhSectionPos"); - OldDhSectionPos pos = deserializeSectionPos(posString); + Long pos = deserializeSectionPos(posString); // meta data int checksum = (Integer) objectMap.get("Checksum"); @@ -164,7 +165,7 @@ public class FullDataSourceV1Repo extends AbstractDhRepo - * Returns {@link OldDhSectionPos#SECTION_MINIMUM_DETAIL_LEVEL} if no data is present. + * Returns {@link DhSectionPos#SECTION_MINIMUM_DETAIL_LEVEL} if no data is present. */ public int getMaxSectionDetailLevel() { @@ -179,7 +180,7 @@ public class FullDataSourceV1Repo extends AbstractDhRepo getPositionsToMigrate(int returnCount) + public LongArrayList getPositionsToMigrate(int returnCount) { - ArrayList list = new ArrayList<>(); + LongArrayList list = new LongArrayList(); List> resultMapList = this.queryDictionary( "select DhSectionPos " + @@ -220,14 +221,14 @@ public class FullDataSourceV1Repo extends AbstractDhRepo resultMap : resultMapList) { // returned in the format [sectionDetailLevel,x,z] IE [6,0,0] - OldDhSectionPos sectionPos = deserializeSectionPos((String) resultMap.get("DhSectionPos")); + long sectionPos = deserializeSectionPos((String) resultMap.get("DhSectionPos")); list.add(sectionPos); } return list; } - public void markMigrationFailed(OldDhSectionPos pos) + public void markMigrationFailed(long pos) { String sql = "UPDATE "+this.getTableName()+" \n" + @@ -262,7 +263,7 @@ public class FullDataSourceV1Repo extends AbstractDhRepo getUnusedDataSourcePositionStringList(int deleteCount) { List> deletePosResultMapList = this.queryDictionary( @@ -291,17 +292,24 @@ public class FullDataSourceV1Repo extends AbstractDhRepo +public class FullDataSourceV2Repo extends AbstractDhRepo { private static final Logger LOGGER = DhLoggerBuilder.getLogger(); @@ -60,10 +61,10 @@ public class FullDataSourceV2Repo extends AbstractDhRepo objectMap) throws ClassCastException { byte detailLevel = (Byte) objectMap.get("DetailLevel"); - byte sectionDetailLevel = (byte) (detailLevel + OldDhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL); + byte sectionDetailLevel = (byte) (detailLevel + DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL); int posX = (Integer) objectMap.get("PosX"); int posZ = (Integer) objectMap.get("PosZ"); - OldDhSectionPos pos = new OldDhSectionPos(sectionDetailLevel, posX, posZ); + long pos = DhSectionPos.encode(sectionDetailLevel, posX, posZ); int minY = (Integer) objectMap.get("MinY"); int dataChecksum = (Integer) objectMap.get("DataChecksum"); @@ -127,9 +128,9 @@ public class FullDataSourceV2Repo extends AbstractDhRepo resultMap : resultMapList) { byte detailLevel = (Byte) resultMap.get("DetailLevel"); - byte sectionDetailLevel = (byte) (detailLevel + OldDhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL); + byte sectionDetailLevel = (byte) (detailLevel + DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL); int posX = (Integer) resultMap.get("PosX"); int posZ = (Integer) resultMap.get("PosZ"); - OldDhSectionPos pos = new OldDhSectionPos(sectionDetailLevel, posX, posZ); + long pos = DhSectionPos.encode(sectionDetailLevel, posX, posZ); list.add(pos); } @@ -237,14 +238,14 @@ public class FullDataSourceV2Repo extends AbstractDhRepo resultMap = this.queryDictionaryFirst( "select ColumnGenerationStep, CompressionMode " + "from "+this.getTableName()+" " + - "WHERE DetailLevel = "+detailLevel+" AND PosX = "+pos.getX()+" AND PosZ = "+pos.getZ()); + "WHERE DetailLevel = "+detailLevel+" AND PosX = "+DhSectionPos.getX(pos)+" AND PosZ = "+DhSectionPos.getZ(pos)); if (resultMap != null) { @@ -266,7 +267,7 @@ public class FullDataSourceV2Repo extends AbstractDhRepo getAllPositions() + public LongArrayList getAllPositions() { - ArrayList list = new ArrayList<>(); + LongArrayList list = new LongArrayList(); List> resultMapList = this.queryDictionary( "select DetailLevel, PosX, PosZ " + @@ -294,11 +295,11 @@ public class FullDataSourceV2Repo extends AbstractDhRepo resultMap : resultMapList) { byte detailLevel = (Byte) resultMap.get("DetailLevel"); - byte sectionDetailLevel = (byte) (detailLevel + OldDhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL); + byte sectionDetailLevel = (byte) (detailLevel + DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL); int posX = (Integer) resultMap.get("PosX"); int posZ = (Integer) resultMap.get("PosZ"); - OldDhSectionPos pos = new OldDhSectionPos(sectionDetailLevel, posX, posZ); + long pos = DhSectionPos.encode(sectionDetailLevel, posX, posZ); list.add(pos); } @@ -309,14 +310,14 @@ public class FullDataSourceV2Repo extends AbstractDhRepo resultMap = this.queryDictionaryFirst( "select LENGTH(Data) as dataSize " + "from "+this.getTableName()+" " + - "WHERE DetailLevel = "+detailLevel+" AND PosX = "+pos.getX()+" AND PosZ = "+pos.getZ()); + "WHERE DetailLevel = "+detailLevel+" AND PosX = "+DhSectionPos.getX(pos)+" AND PosZ = "+DhSectionPos.getZ(pos)); if (resultMap != null && resultMap.get("dataSize") != null) { 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 7754b3dbb..bb9ed2648 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 @@ -20,11 +20,12 @@ package com.seibel.distanthorizons.core.util.objects.quadTree; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.objects.quadTree.iterators.QuadNodeDirectChildIterator; import com.seibel.distanthorizons.core.util.objects.quadTree.iterators.QuadNodeDirectChildPosIterator; import com.seibel.distanthorizons.core.util.objects.quadTree.iterators.QuadTreeNodeIterator; +import it.unimi.dsi.fastutil.longs.LongIterator; import org.apache.logging.log4j.Logger; import java.util.Iterator; @@ -35,7 +36,7 @@ public class QuadNode private static final Logger LOGGER = DhLoggerBuilder.getLogger(); - public final OldDhSectionPos sectionPos; + public final long sectionPos; public final byte minimumDetailLevel; public T value; @@ -67,7 +68,7 @@ public class QuadNode - public QuadNode(OldDhSectionPos sectionPos, byte minimumDetailLevel) + public QuadNode(long sectionPos, byte minimumDetailLevel) { this.sectionPos = sectionPos; this.minimumDetailLevel = minimumDetailLevel; @@ -145,14 +146,14 @@ public class QuadNode * @return the node at the given position * @throws IllegalArgumentException if childSectionPos has the wrong detail level or is outside the bounds of this node */ - public QuadNode getNode(OldDhSectionPos sectionPos) throws IllegalArgumentException { return this.getOrSetValue(sectionPos, false, null); } + public QuadNode getNode(long sectionPos) throws IllegalArgumentException { return this.getOrSetValue(sectionPos, false, null); } /** * @param sectionPos must be 1 detail level lower than this node's detail level * @return the value at the given position before the new value was set * @throws IllegalArgumentException if childSectionPos has the wrong detail level or is outside the bounds of this node */ - public T setValue(OldDhSectionPos sectionPos, T newValue) throws IllegalArgumentException + public T setValue(long sectionPos, T newValue) throws IllegalArgumentException { QuadNode previousNode = this.getNode(sectionPos); if (previousNode != null) @@ -173,27 +174,27 @@ public class QuadNode * @return the node at the given position before the new node was set (if the new node should be set) * @throws IllegalArgumentException if childSectionPos has the wrong detail level or is outside the bounds of this */ - private QuadNode getOrSetValue(OldDhSectionPos inputSectionPos, boolean replaceValue, T newValue) throws IllegalArgumentException + private QuadNode getOrSetValue(long inputSectionPos, boolean replaceValue, T newValue) throws IllegalArgumentException { // debug validation - if (!this.sectionPos.contains(inputSectionPos)) + if (!DhSectionPos.contains(this.sectionPos, inputSectionPos)) { - 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()); + LOGGER.error((replaceValue ? "set " : "get ") + inputSectionPos + " center block: " + DhSectionPos.getCenterBlockPos(inputSectionPos) + ", this pos: " + this.sectionPos + " this center block: " + DhSectionPos.getCenterBlockPos(this.sectionPos)); + throw new IllegalArgumentException("Input section pos " + inputSectionPos + " outside of this quadNode's pos: " + this.sectionPos + ", this node's blockPos: " + DhSectionPos.convertToDetailLevel(LodUtil.BLOCK_DETAIL_LEVEL, this.sectionPos) + " block width: " + DhSectionPos.getBlockWidth(this.sectionPos) + " input detail level: " + DhSectionPos.convertToDetailLevel(LodUtil.BLOCK_DETAIL_LEVEL, inputSectionPos) + " width: " + DhSectionPos.getBlockWidth(inputSectionPos)); } - if (inputSectionPos.getDetailLevel() > this.sectionPos.getDetailLevel()) + if (DhSectionPos.getDetailLevel(inputSectionPos) > DhSectionPos.getDetailLevel(this.sectionPos)) { - throw new IllegalArgumentException("detail level higher than this node. Node Detail level: " + this.sectionPos.getDetailLevel() + " input detail level: " + inputSectionPos.getDetailLevel()); + throw new IllegalArgumentException("detail level higher than this node. Node Detail level: " + DhSectionPos.getDetailLevel(this.sectionPos) + " input detail level: " + DhSectionPos.getDetailLevel(inputSectionPos)); } - if (inputSectionPos.getDetailLevel() == this.sectionPos.getDetailLevel() && !inputSectionPos.equals(this.sectionPos)) + if (DhSectionPos.getDetailLevel(inputSectionPos) == DhSectionPos.getDetailLevel(this.sectionPos) && inputSectionPos != 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.getDetailLevel() < this.minimumDetailLevel) + if (DhSectionPos.getDetailLevel(inputSectionPos) < 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 +202,7 @@ public class QuadNode // get/set logic - if (inputSectionPos.getDetailLevel() == this.sectionPos.getDetailLevel()) + if (DhSectionPos.getDetailLevel(inputSectionPos) == DhSectionPos.getDetailLevel(this.sectionPos)) { // this node is the requested position if (replaceValue) @@ -217,14 +218,14 @@ public class QuadNode // LOGGER.info((replaceValue ? "set " : "get ")+inputSectionPos+" center block: "+inputSectionPos.getCenter().getCornerBlockPos()+", this pos: "+this.sectionPos+" this center block: "+this.sectionPos.getCenter().getCornerBlockPos()); - OldDhSectionPos nwPos = this.sectionPos.getChildByIndex(0); - OldDhSectionPos swPos = this.sectionPos.getChildByIndex(1); - OldDhSectionPos nePos = this.sectionPos.getChildByIndex(2); - OldDhSectionPos sePos = this.sectionPos.getChildByIndex(3); + long nwPos = DhSectionPos.getChildByIndex(0, this.sectionPos); + long swPos = DhSectionPos.getChildByIndex(1, this.sectionPos); + long nePos = DhSectionPos.getChildByIndex(2, this.sectionPos); + long sePos = DhSectionPos.getChildByIndex(3, this.sectionPos); // look for the child that contains the input position (there may be a faster way to do this, but this works for now) QuadNode childNode; - if (nwPos.contains(inputSectionPos)) + if (DhSectionPos.contains(nwPos, inputSectionPos)) { // TODO merge duplicate code if (replaceValue && this.nwChild == null) @@ -237,7 +238,7 @@ public class QuadNode // childNode should only be null when replaceValue = false and the end of a node chain has been reached return (childNode != null) ? childNode.getOrSetValue(inputSectionPos, replaceValue, newValue) : null; } - else if (swPos.contains(inputSectionPos)) + else if (DhSectionPos.contains(swPos, inputSectionPos)) { // TODO merge duplicate code if (replaceValue && this.swChild == null) @@ -250,7 +251,7 @@ public class QuadNode // childNode should only be null when replaceValue = false and the end of a node chain has been reached return (childNode != null) ? childNode.getOrSetValue(inputSectionPos, replaceValue, newValue) : null; } - else if (nePos.contains(inputSectionPos)) + else if (DhSectionPos.contains(nePos, inputSectionPos)) { // TODO merge duplicate code if (replaceValue && this.neChild == null) @@ -263,7 +264,7 @@ public class QuadNode // childNode should only be null when replaceValue = false and the end of a node chain has been reached return (childNode != null) ? childNode.getOrSetValue(inputSectionPos, replaceValue, newValue) : null; } - else if (sePos.contains(inputSectionPos)) + else if (DhSectionPos.contains(sePos, inputSectionPos)) { // TODO merge duplicate code if (replaceValue && this.seChild == null) @@ -293,7 +294,7 @@ public class QuadNode public Iterator> getLeafNodeIterator() { return new QuadTreeNodeIterator<>(this, true); } /** positions can point to null children */ - public Iterator getChildPosIterator() { return new QuadNodeDirectChildPosIterator<>(this); } + public LongIterator getChildPosIterator() { return new QuadNodeDirectChildPosIterator<>(this); } public Iterator> getChildNodeIterator() { return new QuadNodeDirectChildIterator<>(this); } 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 51d730410..da4723362 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 @@ -22,16 +22,19 @@ package com.seibel.distanthorizons.core.util.objects.quadTree; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos2D; import com.seibel.distanthorizons.core.pos.DhLodPos; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.pos.Pos2D; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.coreapi.util.BitShiftUtil; import com.seibel.distanthorizons.coreapi.util.MathUtil; import com.seibel.distanthorizons.core.util.gridList.MovableGridRingList; +import it.unimi.dsi.fastutil.longs.LongArrayFIFOQueue; +import it.unimi.dsi.fastutil.longs.LongIterator; import org.apache.logging.log4j.Logger; import java.util.*; import java.util.function.Consumer; +import java.util.function.LongConsumer; /** * This class represents a quadTree of T type values. @@ -93,9 +96,9 @@ public class QuadTree //=====================// /** @return the node at the given section position */ - public final QuadNode getNode(OldDhSectionPos pos) throws IndexOutOfBoundsException { return this.getOrSetNode(pos, false, null, true); } + public final QuadNode getNode(long pos) throws IndexOutOfBoundsException { return this.getOrSetNode(pos, false, null, true); } /** @return the value at the given section position */ - public final T getValue(OldDhSectionPos pos) throws IndexOutOfBoundsException + public final T getValue(long pos) throws IndexOutOfBoundsException { QuadNode node = this.getNode(pos); if (node != null) @@ -106,7 +109,7 @@ public class QuadTree } /** @return the value that was previously in the given position, null if nothing */ - public final T setValue(OldDhSectionPos pos, T value) throws IndexOutOfBoundsException + public final T setValue(long pos, T value) throws IndexOutOfBoundsException { T previousValue = this.getValue(pos); this.getOrSetNode(pos, true, value, true); @@ -114,21 +117,21 @@ public class QuadTree } /** @param runBoundaryChecks should only ever be set to true internally for removing out of bound nodes */ - protected final QuadNode getOrSetNode(OldDhSectionPos pos, boolean setNewValue, T newValue, boolean runBoundaryChecks) throws IndexOutOfBoundsException + protected final QuadNode getOrSetNode(long pos, boolean setNewValue, T newValue, boolean runBoundaryChecks) throws IndexOutOfBoundsException { 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.convertNewToDetailLevel(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: [" + DhSectionPos.toString(pos) + "] = block pos: " + DhSectionPos.convertToDetailLevel(LodUtil.BLOCK_DETAIL_LEVEL, pos)); } - OldDhSectionPos rootPos = pos.convertNewToDetailLevel(this.treeMinDetailLevel); - int ringListPosX = rootPos.getX(); - int ringListPosZ = rootPos.getZ(); + long rootPos = DhSectionPos.convertToDetailLevel(this.treeMinDetailLevel, pos); + int ringListPosX = DhSectionPos.getX(rootPos); + int ringListPosZ = DhSectionPos.getZ(rootPos); QuadNode topQuadNode = this.topRingList.get(ringListPosX, ringListPosZ); if (topQuadNode == null) @@ -146,7 +149,7 @@ public class QuadTree } } - if (!topQuadNode.sectionPos.contains(pos)) + if (!DhSectionPos.contains(topQuadNode.sectionPos, pos)) { LodUtil.assertNotReach("failed to get a root node that contains the input position: " + pos + " root node pos: " + topQuadNode.sectionPos); } @@ -160,10 +163,10 @@ public class QuadTree return returnNode; } - public boolean isSectionPosInBounds(OldDhSectionPos testPos) + public boolean isSectionPosInBounds(long testPos) { // check if the testPos is within the detail level limits of the tree - boolean detailLevelWithinBounds = this.treeMaxDetailLevel <= testPos.getDetailLevel() && testPos.getDetailLevel() <= this.treeMinDetailLevel; + boolean detailLevelWithinBounds = this.treeMaxDetailLevel <= DhSectionPos.getDetailLevel(testPos) && DhSectionPos.getDetailLevel(testPos) <= this.treeMinDetailLevel; if (!detailLevelWithinBounds) { return false; @@ -174,9 +177,9 @@ public class QuadTree DhBlockPos2D treeBlockCorner = this.centerBlockPos.add(new DhBlockPos2D(-this.diameterInBlocks / 2, -this.diameterInBlocks / 2)); DhLodPos treeCornerPos = new DhLodPos((byte) 0, treeBlockCorner.x, treeBlockCorner.z); - OldDhSectionPos inputSectionCorner = testPos.convertNewToDetailLevel((byte) 0); - DhLodPos inputCornerPos = new DhLodPos((byte) 0, inputSectionCorner.getX(), inputSectionCorner.getZ()); - int inputBlockWidth = BitShiftUtil.powerOfTwo(testPos.getDetailLevel()); + long inputSectionCorner = DhSectionPos.convertToDetailLevel((byte) 0, testPos); + DhLodPos inputCornerPos = new DhLodPos((byte) 0, DhSectionPos.getX(inputSectionCorner), DhSectionPos.getZ(inputSectionCorner)); + int inputBlockWidth = BitShiftUtil.powerOfTwo(DhSectionPos.getDetailLevel(testPos)); return DoSquaresOverlap(treeCornerPos, this.diameterInBlocks, inputCornerPos, inputBlockWidth); } @@ -202,13 +205,13 @@ public class QuadTree } - public int getNonNullChildCountAtPos(OldDhSectionPos pos) { return this.getChildCountAtPos(pos, false); } - public int getChildCountAtPos(OldDhSectionPos pos, boolean includeNullValues) + public int getNonNullChildCountAtPos(long pos) { return this.getChildCountAtPos(pos, false); } + public int getChildCountAtPos(long pos, boolean includeNullValues) { int childCount = 0; for (int i = 0; i < 4; i++) { - OldDhSectionPos childPos = pos.getChildByIndex(i); + long childPos = DhSectionPos.getChildByIndex(i, pos); if (this.isSectionPosInBounds(childPos)) { T value = this.getValue(childPos); @@ -229,7 +232,7 @@ public class QuadTree //===========// /** can include null nodes */ - public Iterator rootNodePosIterator() { return new QuadTreeRootPosIterator(true); } + public LongIterator rootNodePosIterator() { return new QuadTreeRootPosIterator(true); } public Iterator> nodeIterator() { return new QuadTreeNodeIterator(false); } public Iterator> leafNodeIterator() { return new QuadTreeNodeIterator(true); } @@ -394,9 +397,9 @@ public class QuadTree // iterator classes // //==================// - private class QuadTreeRootPosIterator implements Iterator + private class QuadTreeRootPosIterator implements LongIterator { - private final Queue iteratorPosQueue = new ArrayDeque<>(); + private final LongArrayFIFOQueue iteratorPosQueue = new LongArrayFIFOQueue(); @@ -406,11 +409,10 @@ public class QuadTree { if (node != null || includeNullNodes) { - // TODO can these DhSectionPos be pooled? - OldDhSectionPos rootPos = new OldDhSectionPos(QuadTree.this.treeMinDetailLevel, pos2D.x, pos2D.y); + long rootPos = DhSectionPos.encode(QuadTree.this.treeMinDetailLevel, pos2D.x, pos2D.y); if (QuadTree.this.isSectionPosInBounds(rootPos)) { - this.iteratorPosQueue.add(rootPos); + this.iteratorPosQueue.enqueue(rootPos); } } }); @@ -422,7 +424,7 @@ public class QuadTree public boolean hasNext() { return this.iteratorPosQueue.size() != 0; } @Override - public OldDhSectionPos next() + public long nextLong() { if (this.iteratorPosQueue.size() == 0) { @@ -430,7 +432,7 @@ public class QuadTree } - OldDhSectionPos sectionPos = this.iteratorPosQueue.poll(); + long sectionPos = this.iteratorPosQueue.dequeueLong(); return sectionPos; } @@ -440,7 +442,7 @@ public class QuadTree public void remove() { throw new UnsupportedOperationException("remove"); } @Override - public void forEachRemaining(Consumer action) { Iterator.super.forEachRemaining(action); } + public void forEachRemaining(LongConsumer action) { LongIterator.super.forEachRemaining(action); } } @@ -498,7 +500,7 @@ public class QuadTree Iterator> nodeIterator = null; while ((nodeIterator == null || !nodeIterator.hasNext()) && this.rootNodeIterator.hasNext()) { - OldDhSectionPos sectionPos = this.rootNodeIterator.next(); + long sectionPos = this.rootNodeIterator.nextLong(); QuadNode rootNode = QuadTree.this.getNode(sectionPos); if (rootNode != null) { 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 639f8e40a..bc014863b 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 @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.core.util.objects.quadTree.iterators; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.util.objects.quadTree.QuadNode; import java.util.Iterator; @@ -36,7 +37,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.getDetailLevel() > parentNode.minimumDetailLevel) + if (DhSectionPos.getDetailLevel(parentNode.sectionPos) > 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/QuadNodeDirectChildPosIterator.java b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/iterators/QuadNodeDirectChildPosIterator.java index 804430d6c..85535846f 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/iterators/QuadNodeDirectChildPosIterator.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/quadTree/iterators/QuadNodeDirectChildPosIterator.java @@ -19,14 +19,16 @@ package com.seibel.distanthorizons.core.util.objects.quadTree.iterators; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.util.objects.quadTree.QuadNode; +import it.unimi.dsi.fastutil.longs.LongIterator; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.function.Consumer; +import java.util.function.LongConsumer; -public class QuadNodeDirectChildPosIterator implements Iterator +public class QuadNodeDirectChildPosIterator implements LongIterator { private final QuadNodeChildIndexIterator childIndexIterator; private final QuadNode parentNode; @@ -44,7 +46,7 @@ public class QuadNodeDirectChildPosIterator implements Iterator implements Iterator implements Iterator action) { Iterator.super.forEachRemaining(action); } + public void forEachRemaining(LongConsumer action) { LongIterator.super.forEachRemaining(action); } } \ No newline at end of file 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 13745870e..54fb3ae01 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 @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.core.util.objects.quadTree.iterators; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.util.objects.quadTree.QuadNode; import java.util.Iterator; @@ -46,7 +47,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.getDetailLevel(); + this.iteratorDetailLevel = DhSectionPos.getDetailLevel(rootNode.sectionPos); if (!this.onlyReturnLeafValues) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/threading/PositionalLockProvider.java b/core/src/main/java/com/seibel/distanthorizons/core/util/threading/PositionalLockProvider.java index eed050857..c169a9474 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/threading/PositionalLockProvider.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/threading/PositionalLockProvider.java @@ -1,7 +1,7 @@ package com.seibel.distanthorizons.core.util.threading; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.util.ThreadUtil; import org.apache.logging.log4j.Logger; @@ -15,7 +15,7 @@ import java.util.concurrent.locks.ReentrantLock; /** * Handles creating and destroying {@link ReentrantLock}'s for - * a given {@link OldDhSectionPos}. + * a given {@link DhSectionPos}. * This is necessary since we need an unlimited number of locks * when handling data updating, but we don't want to infinitely create locks. * This provider will create/destroy locks as necessary given the current requirements by the file handlers. @@ -32,7 +32,7 @@ public class PositionalLockProvider private static final int MAX_NUMBER_OF_LOCKS = 100; - private final ConcurrentHashMap lockByPos = new ConcurrentHashMap<>(); + private final ConcurrentHashMap lockByPos = new ConcurrentHashMap<>(); private final AtomicBoolean lockRemovalThreadRunning = new AtomicBoolean(false); @@ -50,7 +50,7 @@ public class PositionalLockProvider // getter // //========// - public ReentrantLock getLock(OldDhSectionPos pos) + public ReentrantLock getLock(long pos) { return this.lockByPos.compute(pos, (ignorePos, lock) -> { @@ -76,14 +76,14 @@ public class PositionalLockProvider Thread.sleep(CLEANUP_THREAD_MAX_FREQUENCY_IN_MS); // walk over every lock and check which ones need to be removed - Iterator keySet = this.lockByPos.keySet().iterator(); + Iterator keySet = this.lockByPos.keySet().iterator(); while (keySet.hasNext()) { try { long currentTime = System.currentTimeMillis(); - OldDhSectionPos pos = keySet.next(); + long pos = keySet.next(); ExpiringLock lock = this.lockByPos.get(pos); // don't try removing a lock that's currently in use @@ -92,7 +92,7 @@ public class PositionalLockProvider if (currentTime > lock.expirationTimeInMs) { this.lockByPos.remove(pos); - //LOGGER.info("removed lock: "+pos); + //LOGGER.info("removed lock: "+DhSectionPos.toString(pos)); } lock.unlock(); } diff --git a/core/src/test/java/tests/CompressionTest.java b/core/src/test/java/tests/CompressionTest.java index 0db0e148b..98b531d3e 100644 --- a/core/src/test/java/tests/CompressionTest.java +++ b/core/src/test/java/tests/CompressionTest.java @@ -21,9 +21,10 @@ package tests; import com.seibel.distanthorizons.api.enums.config.EDhApiDataCompressionMode; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.sql.dto.FullDataSourceV2DTO; import com.seibel.distanthorizons.core.sql.repo.FullDataSourceV2Repo; +import it.unimi.dsi.fastutil.longs.LongArrayList; import org.junit.Assert; import java.io.*; @@ -272,7 +273,7 @@ public class CompressionTest - ArrayList positionList = uncompressedRepo.getAllPositions(); + LongArrayList positionList = uncompressedRepo.getAllPositions(); totalUncompressedFileSizeInBytes = uncompressedRepo.getTotalDataSizeInBytes(); System.out.println("Found [" + positionList.size() + "] DTOs."); @@ -282,7 +283,7 @@ public class CompressionTest { try { - OldDhSectionPos pos = positionList.get(i); + long pos = positionList.getLong(i); if (i % 20 == 0) { System.out.println(i + "/" + maxTestPosition); diff --git a/core/src/test/java/tests/DhSectionPosTest.java b/core/src/test/java/tests/DhSectionPosTest.java index 89f459b7b..4bbfdf803 100644 --- a/core/src/test/java/tests/DhSectionPosTest.java +++ b/core/src/test/java/tests/DhSectionPosTest.java @@ -94,6 +94,15 @@ public class DhSectionPosTest Assert.assertFalse("position should be out of bounds", DhSectionPos.contains(root, child)); child = DhSectionPos.encode((byte) 9, 5, 5); Assert.assertFalse("position should be out of bounds", DhSectionPos.contains(root, child)); + + + Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encode((byte) 6, 0, 0), DhSectionPos.encode((byte) 0, 0, 0))); + Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encode((byte) 6, 0, 0), DhSectionPos.encode((byte) 1, 0, 0))); + Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encode((byte) 6, 0, 0), DhSectionPos.encode((byte) 2, 0, 0))); + Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encode((byte) 6, 0, 0), DhSectionPos.encode((byte) 3, 0, 0))); + Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encode((byte) 6, 0, 0), DhSectionPos.encode((byte) 4, 0, 0))); + Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encode((byte) 6, 0, 0), DhSectionPos.encode((byte) 5, 0, 0))); + Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encode((byte) 6, 0, 0), DhSectionPos.encode((byte) 6, 0, 0))); } @Test @@ -161,23 +170,6 @@ public class DhSectionPosTest } - @Test - public void getCenterBlockTest() - { - long node = DhSectionPos.encode((byte) 1, 2303, 0); - DhBlockPos2D centerBlockPos = DhSectionPos.getCenterBlockPos(node); - DhBlockPos2D expectedCenterNode = new DhBlockPos2D(4606, 0); - Assert.assertEquals(expectedCenterNode, centerBlockPos); - - - - node = DhSectionPos.encode((byte) 10, 0, 0); // 1024 blocks wide - centerBlockPos = DhSectionPos.getCenterBlockPos(node); - expectedCenterNode = new DhBlockPos2D(1024 / 2, 1024 / 2); - Assert.assertEquals(expectedCenterNode, centerBlockPos); - - } - @Test public void getCenterBlock2DTest() { @@ -365,33 +357,47 @@ public class DhSectionPosTest } @Test - public void getCenterBlockPos() + public void getCenterBlockPosOrigin() { long originSectionPos = DhSectionPos.encode((byte) 0,0,0); long sectionPos = DhSectionPos.encode((byte) 0,-10000,5000); + + // 1x1 blocks Assert.assertEquals(new DhBlockPos2D(0, 0), DhSectionPos.getCenterBlockPos(originSectionPos)); Assert.assertEquals(new DhBlockPos2D(-10000, 5000), DhSectionPos.getCenterBlockPos(sectionPos)); + // 2x2 blocks originSectionPos = DhSectionPos.convertToDetailLevel((byte) 1, originSectionPos); Assert.assertEquals(new DhBlockPos2D(0, 0), DhSectionPos.getCenterBlockPos(originSectionPos)); sectionPos = DhSectionPos.convertToDetailLevel((byte) 1, sectionPos); Assert.assertEquals(new DhBlockPos2D(-10000, 5000), DhSectionPos.getCenterBlockPos(sectionPos)); + //sectionPos = DhSectionPos.encode((byte) 1, 2303, 0); + //Assert.assertEquals(new DhBlockPos2D(4606, 0), DhSectionPos.getCenterBlockPos(sectionPos)); + // 4x4 blocks + originSectionPos = DhSectionPos.convertToDetailLevel((byte) 2, originSectionPos); + Assert.assertEquals(new DhBlockPos2D(2, 2), DhSectionPos.getCenterBlockPos(originSectionPos)); + sectionPos = DhSectionPos.convertToDetailLevel((byte) 2, sectionPos); + Assert.assertEquals(new DhBlockPos2D(-9998, 5002), DhSectionPos.getCenterBlockPos(sectionPos)); + + + // 64x64 blocks originSectionPos = DhSectionPos.convertToDetailLevel(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, originSectionPos); Assert.assertEquals(new DhBlockPos2D(32, 32), DhSectionPos.getCenterBlockPos(originSectionPos)); sectionPos = DhSectionPos.convertToDetailLevel(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPos); Assert.assertEquals(new DhBlockPos2D(-10016, 5024), DhSectionPos.getCenterBlockPos(sectionPos)); - - + + + // 32,768 x 32,768 blocks originSectionPos = DhSectionPos.convertToDetailLevel(DhSectionPos.SECTION_REGION_DETAIL_LEVEL, originSectionPos); Assert.assertEquals(new DhBlockPos2D(16384, 16384), DhSectionPos.getCenterBlockPos(originSectionPos)); sectionPos = DhSectionPos.convertToDetailLevel(DhSectionPos.SECTION_REGION_DETAIL_LEVEL, sectionPos); Assert.assertEquals(new DhBlockPos2D(-16384, 16384), DhSectionPos.getCenterBlockPos(sectionPos)); - + } @Test diff --git a/core/src/test/java/tests/QuadTreeTest.java b/core/src/test/java/tests/QuadTreeTest.java index 1fa54eb17..e731cca49 100644 --- a/core/src/test/java/tests/QuadTreeTest.java +++ b/core/src/test/java/tests/QuadTreeTest.java @@ -21,12 +21,13 @@ package tests; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos2D; -import com.seibel.distanthorizons.core.pos.OldDhSectionPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.coreapi.util.BitShiftUtil; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.coreapi.util.MathUtil; import com.seibel.distanthorizons.core.util.objects.quadTree.QuadNode; import com.seibel.distanthorizons.core.util.objects.quadTree.QuadTree; +import it.unimi.dsi.fastutil.longs.LongIterator; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.core.config.Configurator; @@ -59,30 +60,30 @@ public class QuadTreeTest // (pseudo) root node // - testSet(tree, new OldDhSectionPos((byte) 10, 0, 0), 0); + testSet(tree, DhSectionPos.encode((byte) 10, 0, 0), 0); // first child (0,0) // - testSet(tree, new OldDhSectionPos((byte) 9, 0, 0), 1); - testSet(tree, new OldDhSectionPos((byte) 9, 1, 0), 2); - testSet(tree, new OldDhSectionPos((byte) 9, 0, 1), 3); - testSet(tree, new OldDhSectionPos((byte) 9, 1, 1), 4); + testSet(tree, DhSectionPos.encode((byte) 9, 0, 0), 1); + testSet(tree, DhSectionPos.encode((byte) 9, 1, 0), 2); + testSet(tree, DhSectionPos.encode((byte) 9, 0, 1), 3); + testSet(tree, DhSectionPos.encode((byte) 9, 1, 1), 4); // second child (0,0) (0,0) // - testSet(tree, new OldDhSectionPos((byte) 8, 0, 0), 5); - testSet(tree, new OldDhSectionPos((byte) 8, 1, 0), 6); - testSet(tree, new OldDhSectionPos((byte) 8, 0, 1), 7); - testSet(tree, new OldDhSectionPos((byte) 8, 1, 1), 8); + testSet(tree, DhSectionPos.encode((byte) 8, 0, 0), 5); + testSet(tree, DhSectionPos.encode((byte) 8, 1, 0), 6); + testSet(tree, DhSectionPos.encode((byte) 8, 0, 1), 7); + testSet(tree, DhSectionPos.encode((byte) 8, 1, 1), 8); // second child (0,0) (1,1) // - testSet(tree, new OldDhSectionPos((byte) 8, 2, 2), 9); - testSet(tree, new OldDhSectionPos((byte) 8, 3, 2), 10); - testSet(tree, new OldDhSectionPos((byte) 8, 2, 3), 11); - testSet(tree, new OldDhSectionPos((byte) 8, 3, 3), 12); + testSet(tree, DhSectionPos.encode((byte) 8, 2, 2), 9); + testSet(tree, DhSectionPos.encode((byte) 8, 3, 2), 10); + testSet(tree, DhSectionPos.encode((byte) 8, 2, 3), 11); + testSet(tree, DhSectionPos.encode((byte) 8, 3, 3), 12); // third child (0,0) (1,0) (0,0) // - testSet(tree, new OldDhSectionPos((byte) 7, 5, 0), 9); - testSet(tree, new OldDhSectionPos((byte) 7, 6, 0), 10); - testSet(tree, new OldDhSectionPos((byte) 7, 5, 1), 11); - testSet(tree, new OldDhSectionPos((byte) 7, 6, 1), 12); + testSet(tree, DhSectionPos.encode((byte) 7, 5, 0), 9); + testSet(tree, DhSectionPos.encode((byte) 7, 6, 0), 10); + testSet(tree, DhSectionPos.encode((byte) 7, 5, 1), 11); + testSet(tree, DhSectionPos.encode((byte) 7, 6, 1), 12); } @@ -94,13 +95,13 @@ public class QuadTreeTest // root node // - testSet(tree, new OldDhSectionPos((byte) 10, -1, -1), 0); + testSet(tree, DhSectionPos.encode((byte) 10, -1, -1), 0); // first child (-1,-1) // - testSet(tree, new OldDhSectionPos((byte) 9, -2, -1), 1); - testSet(tree, new OldDhSectionPos((byte) 9, -1, -1), 2); - testSet(tree, new OldDhSectionPos((byte) 9, -2, -2), 3); - testSet(tree, new OldDhSectionPos((byte) 9, -1, -2), 4); + testSet(tree, DhSectionPos.encode((byte) 9, -2, -1), 1); + testSet(tree, DhSectionPos.encode((byte) 9, -1, -1), 2); + testSet(tree, DhSectionPos.encode((byte) 9, -2, -2), 3); + testSet(tree, DhSectionPos.encode((byte) 9, -1, -2), 4); // TODO // // second child (-1,-1) (0,0) // @@ -131,36 +132,36 @@ public class QuadTreeTest // wrong detail level on purpose, if the detail level was 0 (block) this should work - OldDhSectionPos outOfBoundsPos = new OldDhSectionPos(OldDhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2), 0); + long outOfBoundsPos = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2), 0); testSet(tree, outOfBoundsPos, -1, IndexOutOfBoundsException.class); Assert.assertEquals("incorrect leaf node count", 0, tree.leafNodeCount()); // out of bounds // - outOfBoundsPos = new OldDhSectionPos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) + 1, 0); + outOfBoundsPos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) + 1, 0); testSet(tree, outOfBoundsPos, -1, IndexOutOfBoundsException.class); Assert.assertEquals("incorrect leaf node count", 0, tree.leafNodeCount()); - outOfBoundsPos = new OldDhSectionPos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2), 0); + outOfBoundsPos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2), 0); testSet(tree, outOfBoundsPos, -1, IndexOutOfBoundsException.class); Assert.assertEquals("incorrect leaf node count", 0, tree.leafNodeCount()); // in bounds // - outOfBoundsPos = new OldDhSectionPos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 1, 0); + outOfBoundsPos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 1, 0); testSet(tree, outOfBoundsPos, 0); Assert.assertEquals("incorrect leaf node count", 1, tree.leafNodeCount()); - outOfBoundsPos = new OldDhSectionPos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 3, 0); + outOfBoundsPos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 3, 0); testSet(tree, outOfBoundsPos, 0); Assert.assertEquals("incorrect leaf node count", 2, tree.leafNodeCount()); // TODO this position probably has trouble with getting the center. - outOfBoundsPos = new OldDhSectionPos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 2, 0); + outOfBoundsPos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 2, 0); testSet(tree, outOfBoundsPos, 0); Assert.assertEquals("incorrect leaf node count", 3, tree.leafNodeCount()); - outOfBoundsPos = new OldDhSectionPos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 4, 0); + outOfBoundsPos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 4, 0); testSet(tree, outOfBoundsPos, 0); Assert.assertEquals("incorrect leaf node count", 4, tree.leafNodeCount()); @@ -173,15 +174,15 @@ public class QuadTreeTest Assert.assertEquals("Test may need to be re-calculated for different max detail level.", 9, tree.treeMinDetailLevel); - OldDhSectionPos rootPos = new OldDhSectionPos((byte) 9, 0, -1); + long rootPos = DhSectionPos.encode((byte) 9, 0, -1); testSet(tree, rootPos, 1); // pos is in tree, but out of range - OldDhSectionPos midPos = new OldDhSectionPos((byte) 8, 0, -1); + long midPos = DhSectionPos.encode((byte) 8, 0, -1); testSet(tree, midPos, 2, IndexOutOfBoundsException.class); // pos is in tree, but out of range - OldDhSectionPos leafPos = new OldDhSectionPos((byte) 7, 0, -2); + long leafPos = DhSectionPos.encode((byte) 7, 0, -2); testSet(tree, leafPos, 3, IndexOutOfBoundsException.class); } @@ -197,13 +198,13 @@ public class QuadTreeTest // (pseudo) root nodes // - testSet(tree, new OldDhSectionPos((byte) 10, 0, 0), 1); + testSet(tree, DhSectionPos.encode((byte) 10, 0, 0), 1); // first child (0,0) // - OldDhSectionPos nw = new OldDhSectionPos(OldDhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0); - OldDhSectionPos ne = new OldDhSectionPos(OldDhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 1, 0); - OldDhSectionPos sw = new OldDhSectionPos(OldDhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 1); - OldDhSectionPos se = new OldDhSectionPos(OldDhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 1, 1); + long nw = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0); + long ne = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 1, 0); + long sw = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 1); + long se = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 1, 1); testSet(tree, nw, 2); testSet(tree, ne, 3); @@ -259,12 +260,12 @@ public class QuadTreeTest Assert.assertEquals("Tree center incorrect", DhBlockPos2D.ZERO, tree.getCenterBlockPos()); // on the negative X edge - OldDhSectionPos edgePos = new OldDhSectionPos(LodUtil.BLOCK_DETAIL_LEVEL, -treeParams.getWidthInBlocks() / 2, 0); + long edgePos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, -treeParams.getWidthInBlocks() / 2, 0); testSet(tree, edgePos, 1); Assert.assertEquals("incorrect leaf node count", 1, tree.leafNodeCount()); // +1 root node from the negative X edge - OldDhSectionPos adjacentEdgePos = new OldDhSectionPos(LodUtil.BLOCK_DETAIL_LEVEL, (-treeParams.getWidthInBlocks() / 2) + pseudoRootNodeWidthInBlocks, 0); + long adjacentEdgePos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (-treeParams.getWidthInBlocks() / 2) + pseudoRootNodeWidthInBlocks, 0); testSet(tree, adjacentEdgePos, 2); Assert.assertEquals("incorrect leaf node count", 2, tree.leafNodeCount()); @@ -284,24 +285,24 @@ public class QuadTreeTest // (pseudo) root nodes // - testSet(tree, new OldDhSectionPos((byte) 10, 0, 0), 1); - testSet(tree, new OldDhSectionPos((byte) 10, 1, 0), 2); + testSet(tree, DhSectionPos.encode((byte) 10, 0, 0), 1); + testSet(tree, DhSectionPos.encode((byte) 10, 1, 0), 2); // first child (0,0) // - testSet(tree, new OldDhSectionPos((byte) 9, 0, 0), 3); - testSet(tree, new OldDhSectionPos((byte) 9, 1, 0), 4); - testSet(tree, new OldDhSectionPos((byte) 9, 0, 1), 5); - testSet(tree, new OldDhSectionPos((byte) 9, 1, 1), 6); + testSet(tree, DhSectionPos.encode((byte) 9, 0, 0), 3); + testSet(tree, DhSectionPos.encode((byte) 9, 1, 0), 4); + testSet(tree, DhSectionPos.encode((byte) 9, 0, 1), 5); + testSet(tree, DhSectionPos.encode((byte) 9, 1, 1), 6); // root nodes int rootNodeCount = 0; - Iterator rootNodePosIterator = tree.rootNodePosIterator(); + LongIterator rootNodePosIterator = tree.rootNodePosIterator(); while (rootNodePosIterator.hasNext()) { - QuadNode rootNode = tree.getNode(rootNodePosIterator.next()); + QuadNode rootNode = tree.getNode(rootNodePosIterator.nextLong()); if (rootNode != null) { rootNodeCount++; @@ -331,20 +332,19 @@ public class QuadTreeTest @Test public void NewQuadTreeIterationTest() { - AbstractTestTreeParams treeParams = new LargeTestTree(); - QuadNode rootNode = new QuadNode<>(new OldDhSectionPos((byte) 10, 0, 0), LodUtil.BLOCK_DETAIL_LEVEL); + QuadNode rootNode = new QuadNode<>(DhSectionPos.encode((byte) 10, 0, 0), LodUtil.BLOCK_DETAIL_LEVEL); - rootNode.setValue(new OldDhSectionPos((byte) 10, 0, 0), 0); + rootNode.setValue(DhSectionPos.encode((byte) 10, 0, 0), 0); - rootNode.setValue(new OldDhSectionPos((byte) 9, 0, 0), 1); - rootNode.setValue(new OldDhSectionPos((byte) 9, 1, 0), 1); - rootNode.setValue(new OldDhSectionPos((byte) 9, 0, 1), 1); - rootNode.setValue(new OldDhSectionPos((byte) 9, 1, 1), null); + rootNode.setValue(DhSectionPos.encode((byte) 9, 0, 0), 1); + rootNode.setValue(DhSectionPos.encode((byte) 9, 1, 0), 1); + rootNode.setValue(DhSectionPos.encode((byte) 9, 0, 1), 1); + rootNode.setValue(DhSectionPos.encode((byte) 9, 1, 1), null); - rootNode.setValue(new OldDhSectionPos((byte) 8, 0, 0), 2); - rootNode.setValue(new OldDhSectionPos((byte) 8, 1, 0), 2); - rootNode.setValue(new OldDhSectionPos((byte) 8, 0, 1), 2); - rootNode.setValue(new OldDhSectionPos((byte) 8, 1, 1), null); + rootNode.setValue(DhSectionPos.encode((byte) 8, 0, 0), 2); + rootNode.setValue(DhSectionPos.encode((byte) 8, 1, 0), 2); + rootNode.setValue(DhSectionPos.encode((byte) 8, 0, 1), 2); + rootNode.setValue(DhSectionPos.encode((byte) 8, 1, 1), null); @@ -411,14 +411,14 @@ public class QuadTreeTest { AbstractTestTreeParams treeParams = new TinyTestTree(); final QuadTree tree = new QuadTree<>(treeParams.getWidthInBlocks(), treeParams.getPositiveEdgeCenterPos(), LodUtil.BLOCK_DETAIL_LEVEL); - testSet(tree, new OldDhSectionPos(tree.treeMinDetailLevel, 0, 0), 0); + testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 0, 0), 0); // confirm the root node were added int rootNodeCount = 0; - Iterator rootNodePosIterator = tree.rootNodePosIterator(); + LongIterator rootNodePosIterator = tree.rootNodePosIterator(); while (rootNodePosIterator.hasNext()) { - QuadNode rootNode = tree.getNode(rootNodePosIterator.next()); + QuadNode rootNode = tree.getNode(rootNodePosIterator.nextLong()); if (rootNode != null) { rootNodeCount++; @@ -431,7 +431,7 @@ public class QuadTreeTest rootNodePosIterator = tree.rootNodePosIterator(); while (rootNodePosIterator.hasNext()) { - OldDhSectionPos rootNodePos = rootNodePosIterator.next(); + long rootNodePos = rootNodePosIterator.nextLong(); QuadNode rootNode = tree.getNode(rootNodePos); if (rootNode != null) { @@ -468,10 +468,10 @@ public class QuadTreeTest tree.setCenterBlockPos(treeMovePos); Assert.assertEquals("tree move failed, incorrect position after move", treeMovePos, tree.getCenterBlockPos()); - Iterator rootNodePosIterator = tree.rootNodePosIterator(); + LongIterator rootNodePosIterator = tree.rootNodePosIterator(); while (rootNodePosIterator.hasNext()) { - testSet(tree, rootNodePosIterator.next(), 0); + testSet(tree, rootNodePosIterator.nextLong(), 0); } @@ -480,7 +480,7 @@ public class QuadTreeTest rootNodePosIterator = tree.rootNodePosIterator(); while (rootNodePosIterator.hasNext()) { - QuadNode rootNode = tree.getNode(rootNodePosIterator.next()); + QuadNode rootNode = tree.getNode(rootNodePosIterator.nextLong()); if (rootNode != null) { rootNodeCount++; @@ -499,16 +499,16 @@ public class QuadTreeTest Assert.assertEquals("incorrect tree width", treeParams.getWidthInBlocks(), tree.diameterInBlocks()); - testSet(tree, new OldDhSectionPos(tree.treeMinDetailLevel, 0, 0), 0); + testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 0, 0), 0); - testSet(tree, new OldDhSectionPos(tree.treeMinDetailLevel, -1, -1), -1, IndexOutOfBoundsException.class); - testSet(tree, new OldDhSectionPos(tree.treeMinDetailLevel, 1, 1), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, -1, -1), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 1, 1), -1, IndexOutOfBoundsException.class); int rootNodeCount = 0; - Iterator rootNodeIterator = tree.rootNodePosIterator(); + LongIterator rootNodeIterator = tree.rootNodePosIterator(); while (rootNodeIterator.hasNext()) { - QuadNode rootNode = tree.getNode(rootNodeIterator.next()); + QuadNode rootNode = tree.getNode(rootNodeIterator.nextLong()); if (rootNode != null) { rootNodeCount++; @@ -529,25 +529,25 @@ public class QuadTreeTest // 2x2 valid positions (overlap the tree's width) - testSet(tree, new OldDhSectionPos(tree.treeMinDetailLevel, 0, 0), 0); - testSet(tree, new OldDhSectionPos(tree.treeMinDetailLevel, -1, 0), 0); - testSet(tree, new OldDhSectionPos(tree.treeMinDetailLevel, 0, -1), 0); - testSet(tree, new OldDhSectionPos(tree.treeMinDetailLevel, -1, -1), 0); + testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 0, 0), 0); + testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, -1, 0), 0); + testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 0, -1), 0); + testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, -1, -1), 0); // invalid positions - testSet(tree, new OldDhSectionPos(tree.treeMinDetailLevel, -1, 1), -1, IndexOutOfBoundsException.class); - testSet(tree, new OldDhSectionPos(tree.treeMinDetailLevel, 0, 1), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, -1, 1), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 0, 1), -1, IndexOutOfBoundsException.class); - testSet(tree, new OldDhSectionPos(tree.treeMinDetailLevel, 1, 0), -1, IndexOutOfBoundsException.class); - testSet(tree, new OldDhSectionPos(tree.treeMinDetailLevel, 1, 1), -1, IndexOutOfBoundsException.class); - testSet(tree, new OldDhSectionPos(tree.treeMinDetailLevel, 1, -1), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 1, 0), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 1, 1), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 1, -1), -1, IndexOutOfBoundsException.class); int rootNodeCount = 0; - Iterator rootNodeIterator = tree.rootNodePosIterator(); + LongIterator rootNodeIterator = tree.rootNodePosIterator(); while (rootNodeIterator.hasNext()) { - QuadNode rootNode = tree.getNode(rootNodeIterator.next()); + QuadNode rootNode = tree.getNode(rootNodeIterator.nextLong()); if (rootNode != null) { rootNodeCount++; @@ -565,17 +565,17 @@ public class QuadTreeTest Assert.assertEquals("Test detail level's need to be adjusted. This isn't necessarily a failed test.", 10, tree.treeMinDetailLevel); // valid detail levels - testSet(tree, new OldDhSectionPos((byte) 10, 0, 0), 1); - testSet(tree, new OldDhSectionPos((byte) 9, 0, 0), 2); - testSet(tree, new OldDhSectionPos((byte) 8, 0, 0), 3); + testSet(tree, DhSectionPos.encode((byte) 10, 0, 0), 1); + testSet(tree, DhSectionPos.encode((byte) 9, 0, 0), 2); + testSet(tree, DhSectionPos.encode((byte) 8, 0, 0), 3); // detail level too low - testSet(tree, new OldDhSectionPos((byte) 7, 0, 0), -1, IndexOutOfBoundsException.class); - testSet(tree, new OldDhSectionPos((byte) 6, 0, 0), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encode((byte) 7, 0, 0), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encode((byte) 6, 0, 0), -1, IndexOutOfBoundsException.class); // detail level too high - testSet(tree, new OldDhSectionPos((byte) 11, 0, 0), -1, IndexOutOfBoundsException.class); - testSet(tree, new OldDhSectionPos((byte) 12, 0, 0), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encode((byte) 11, 0, 0), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encode((byte) 12, 0, 0), -1, IndexOutOfBoundsException.class); } @@ -587,25 +587,25 @@ public class QuadTreeTest Assert.assertEquals("Test detail level's need to be adjusted. This isn't necessarily a failed test.", 10, tree.treeMinDetailLevel); // create the root node - testSet(tree, new OldDhSectionPos((byte) 10, 0, 0), 1); + testSet(tree, DhSectionPos.encode((byte) 10, 0, 0), 1); AtomicInteger minimumDetailLevelReachedRef = new AtomicInteger(tree.treeMinDetailLevel); // recurse down the tree - Iterator rootNodePosIterator = tree.rootNodePosIterator(); + LongIterator rootNodePosIterator = tree.rootNodePosIterator(); while (rootNodePosIterator.hasNext()) { - OldDhSectionPos sectionPos = rootNodePosIterator.next(); + long sectionPos = rootNodePosIterator.nextLong(); QuadNode rootNode = tree.getNode(sectionPos); if (rootNode != null) { // fill in the root node's direct children - Iterator childPosIterator = rootNode.getChildPosIterator(); + LongIterator childPosIterator = rootNode.getChildPosIterator(); while (childPosIterator.hasNext()) { - OldDhSectionPos rootChildPos = childPosIterator.next(); + long rootChildPos = childPosIterator.nextLong(); rootNode.setValue(rootChildPos, 0); } @@ -618,7 +618,7 @@ public class QuadTreeTest QuadNode childNode = ChildIterator.next(); Assert.assertNotNull(childNode); // TODO is this correct? - recursivelyCreateNodeChildren(childNode, tree.treeMaxDetailLevel, minimumDetailLevelReachedRef); + this.recursivelyCreateNodeChildren(childNode, tree.treeMaxDetailLevel, minimumDetailLevelReachedRef); } } } @@ -634,10 +634,10 @@ public class QuadTreeTest // fill in the null children - Iterator directChildIterator = node.getChildPosIterator(); + LongIterator directChildIterator = node.getChildPosIterator(); while (directChildIterator.hasNext()) { - node.setValue(directChildIterator.next(), 0); + node.setValue(directChildIterator.nextLong(), 0); childNodesCreated = true; } @@ -646,10 +646,10 @@ public class QuadTreeTest directChildIterator = node.getChildPosIterator(); while (directChildIterator.hasNext()) { - OldDhSectionPos sectionPos = directChildIterator.next(); + long sectionPos = directChildIterator.nextLong(); QuadNode childNode = node.getNode(sectionPos); - Assert.assertTrue("Child node recurred too low. Min detail level: " + minDetailLevel + ", node detail level: " + childNode.sectionPos.getDetailLevel(), childNode.sectionPos.getDetailLevel() >= minDetailLevel); + Assert.assertTrue("Child node recurred too low. Min detail level: " + minDetailLevel + ", node detail level: " + DhSectionPos.getDetailLevel(childNode.sectionPos), DhSectionPos.getDetailLevel(childNode.sectionPos) >= 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.getDetailLevel() < minimumDetailLevelReachedRef.get()) + if ( DhSectionPos.getDetailLevel(node.sectionPos) < minimumDetailLevelReachedRef.get()) { - minimumDetailLevelReachedRef.set(node.sectionPos.getDetailLevel()); + minimumDetailLevelReachedRef.set( DhSectionPos.getDetailLevel(node.sectionPos)); } @@ -667,22 +667,22 @@ public class QuadTreeTest // assertions if (childNodesCreated) { - Assert.assertTrue("node children created below minimum detail level", node.sectionPos.getDetailLevel() >= minDetailLevel); + Assert.assertTrue("node children created below minimum detail level", DhSectionPos.getDetailLevel( node.sectionPos) >= minDetailLevel); } if (childNodesIterated) { - Assert.assertTrue("node children iterated below minimum detail level", node.sectionPos.getDetailLevel() - 1 >= minDetailLevel); + Assert.assertTrue("node children iterated below minimum detail level", DhSectionPos.getDetailLevel(node.sectionPos) - 1 >= minDetailLevel); } } @Test public void quadNodeChildPositionIndexTest() { - QuadNode rootNode = new QuadNode<>(new OldDhSectionPos((byte) 10, 0, 0), (byte) 0); - Iterator directChildPosIterator = rootNode.getChildPosIterator(); + QuadNode rootNode = new QuadNode<>(DhSectionPos.encode((byte) 10, 0, 0), (byte) 0); + LongIterator directChildPosIterator = rootNode.getChildPosIterator(); while (directChildPosIterator.hasNext()) { - OldDhSectionPos sectionPos = directChildPosIterator.next(); + long sectionPos = directChildPosIterator.nextLong(); Assert.assertNotEquals("Root node pos shouldn't be included in direct child pos iteration", sectionPos, rootNode.sectionPos); rootNode.setValue(sectionPos, 1); @@ -692,9 +692,9 @@ public class QuadTreeTest for (int i = 0; i < 4; i++) { - OldDhSectionPos childPos = rootNode.sectionPos.getChildByIndex(i); + long childPos = DhSectionPos.getChildByIndex(i, rootNode.sectionPos); QuadNode childNode = rootNode.getChildByIndex(i); - Assert.assertEquals("child position not the same as " + OldDhSectionPos.class.getSimpleName() + "'s getChildByIndex()", childPos, childNode.sectionPos); + Assert.assertEquals("child position not the same as " + long.class.getSimpleName() + "'s getChildByIndex()", childPos, childNode.sectionPos); } } @@ -708,7 +708,7 @@ public class QuadTreeTest // center root node - OldDhSectionPos centerNodePos = new OldDhSectionPos((byte) 1, 0, 0); + long centerNodePos = DhSectionPos.encode((byte) 1, 0, 0); // create node tree.setValue(centerNodePos, 0); @@ -716,10 +716,10 @@ public class QuadTreeTest Assert.assertNotNull(centerRootNode); // child pos in bounds of the tree - Iterator childPosIterator = centerRootNode.getChildPosIterator(); + LongIterator childPosIterator = centerRootNode.getChildPosIterator(); while (childPosIterator.hasNext()) { - OldDhSectionPos childPos = childPosIterator.next(); + long childPos = childPosIterator.nextLong(); centerRootNode.setValue(childPos, 1); } Assert.assertEquals("center node not filled", 4, centerRootNode.getNonNullChildCount()); @@ -727,7 +727,7 @@ public class QuadTreeTest // edge root node - OldDhSectionPos offsetNodePos = new OldDhSectionPos((byte) 1, -17, -16); + long offsetNodePos = DhSectionPos.encode((byte) 1, -17, -16); // create node tree.setValue(offsetNodePos, 0); @@ -738,7 +738,7 @@ public class QuadTreeTest childPosIterator = offsetRootNode.getChildPosIterator(); while (childPosIterator.hasNext()) { - OldDhSectionPos childPos = childPosIterator.next(); + long childPos = childPosIterator.nextLong(); offsetRootNode.setValue(childPos, 1); } // TODO James thought this shouldn't work for all 4 nodes, but he must've thought wrong. @@ -772,7 +772,7 @@ public class QuadTreeTest // - testSet(tree, new OldDhSectionPos((byte) 0, 0, 0), 1); + testSet(tree, DhSectionPos.encode((byte) 0, 0, 0), 1); Assert.assertEquals(1, tree.count()); tree.setCenterBlockPos(new DhBlockPos2D(treeWidth + (treeWidth / 2), 0)); Assert.assertEquals(0, tree.count()); @@ -783,21 +783,21 @@ public class QuadTreeTest //@Test public void autoDeleteNullQuadNodeChildTest() { - QuadNode rootNode = new QuadNode<>(new OldDhSectionPos((byte) 10, 0, 0), LodUtil.BLOCK_DETAIL_LEVEL); + QuadNode rootNode = new QuadNode<>(DhSectionPos.encode((byte) 10, 0, 0), LodUtil.BLOCK_DETAIL_LEVEL); - rootNode.setValue(new OldDhSectionPos((byte) 10, 0, 0), 0); + rootNode.setValue(DhSectionPos.encode((byte) 10, 0, 0), 0); - OldDhSectionPos midNodePos = new OldDhSectionPos((byte) 9, 0, 0); + long midNodePos = DhSectionPos.encode((byte) 9, 0, 0); //rootNode.setValue(midNodePos, null); // holds detail 8 - rootNode.setValue(new OldDhSectionPos((byte) 9, 1, 0), 1); - rootNode.setValue(new OldDhSectionPos((byte) 9, 0, 1), 1); - rootNode.setValue(new OldDhSectionPos((byte) 9, 1, 1), 1); + rootNode.setValue(DhSectionPos.encode((byte) 9, 1, 0), 1); + rootNode.setValue(DhSectionPos.encode((byte) 9, 0, 1), 1); + rootNode.setValue(DhSectionPos.encode((byte) 9, 1, 1), 1); - rootNode.setValue(new OldDhSectionPos((byte) 8, 0, 0), 2); - rootNode.setValue(new OldDhSectionPos((byte) 8, 1, 0), 2); - rootNode.setValue(new OldDhSectionPos((byte) 8, 0, 1), 2); - rootNode.setValue(new OldDhSectionPos((byte) 8, 1, 1), 2); + rootNode.setValue(DhSectionPos.encode((byte) 8, 0, 0), 2); + rootNode.setValue(DhSectionPos.encode((byte) 8, 1, 0), 2); + rootNode.setValue(DhSectionPos.encode((byte) 8, 0, 1), 2); + rootNode.setValue(DhSectionPos.encode((byte) 8, 1, 1), 2); @@ -810,12 +810,12 @@ public class QuadTreeTest // test removing nodes // // remove two leaf nodes from the root - OldDhSectionPos leafPos = new OldDhSectionPos((byte) 9, 1, 1); + long leafPos = DhSectionPos.encode((byte) 9, 1, 1); rootNode.setValue(leafPos, null); Assert.assertEquals(3, rootNode.getNonNullChildCount()); Assert.assertNull("Node wasn't deleted", rootNode.getNode(leafPos)); - leafPos = new OldDhSectionPos((byte) 9, 0, 1); + leafPos = DhSectionPos.encode((byte) 9, 0, 1); rootNode.setValue(leafPos, null); Assert.assertEquals(2, rootNode.getNonNullChildCount()); Assert.assertNull("Node wasn't deleted", rootNode.getNode(leafPos)); @@ -827,13 +827,13 @@ public class QuadTreeTest Assert.assertEquals(4, rootNode.getNode(midNodePos).getNonNullChildCount()); // remove all but one, mid-node should still be present - rootNode.setValue(new OldDhSectionPos((byte) 8, 0, 0), null); - rootNode.setValue(new OldDhSectionPos((byte) 8, 0, 1), null); - rootNode.setValue(new OldDhSectionPos((byte) 8, 1, 0), null); + rootNode.setValue(DhSectionPos.encode((byte) 8, 0, 0), null); + rootNode.setValue(DhSectionPos.encode((byte) 8, 0, 1), null); + rootNode.setValue(DhSectionPos.encode((byte) 8, 1, 0), null); Assert.assertEquals(1, rootNode.getNode(midNodePos).getNonNullChildCount()); // remove last mid-node child, mid-node should now be removed - rootNode.setValue(new OldDhSectionPos((byte) 8, 1, 1), null); + rootNode.setValue(DhSectionPos.encode((byte) 8, 1, 1), null); Assert.assertNull("Mid node not deleted.", rootNode.getNode(midNodePos)); Assert.assertEquals(3, rootNode.getNonNullChildCount()); @@ -847,8 +847,8 @@ public class QuadTreeTest // helper methods // //================// - private static void testSet(QuadTree tree, OldDhSectionPos pos, Integer setValue) { testSet(tree, pos, setValue, null); } - private static void testSet(QuadTree tree, OldDhSectionPos pos, Integer setValue, Class expectedExceptionClass) + private static void testSet(QuadTree tree, long pos, Integer setValue) { testSet(tree, pos, setValue, null); } + private static void testSet(QuadTree tree, long pos, Integer setValue, Class expectedExceptionClass) { // set try @@ -860,7 +860,7 @@ public class QuadTreeTest if (expectedExceptionClass == null || e.getClass() != expectedExceptionClass) { e.printStackTrace(); - Assert.fail("set failed " + pos + " with exception " + e.getClass() + ", expected exception: " + expectedExceptionClass + ". error: " + e.getMessage()); + Assert.fail("set failed [" + DhSectionPos.toString(pos) + "] with exception [" + e.getClass() + "], expected exception: [" + expectedExceptionClass + "]. error: " + e.getMessage()); } } @@ -869,20 +869,20 @@ public class QuadTreeTest testGet(tree, pos, setValue, expectedExceptionClass); } - private static void testGet(QuadTree tree, OldDhSectionPos pos, Integer getValue) { testSet(tree, pos, getValue, null); } - private static void testGet(QuadTree tree, OldDhSectionPos pos, Integer getValue, Class expectedExceptionClass) + private static void testGet(QuadTree tree, long pos, Integer getValue) { testSet(tree, pos, getValue, null); } + private static void testGet(QuadTree tree, long pos, Integer getValue, Class expectedExceptionClass) { try { Integer getResult = tree.getValue(pos); - Assert.assertEquals("get failed " + pos, getValue, getResult); + Assert.assertEquals("get failed [" + DhSectionPos.toString(pos) + "]", getValue, getResult); } catch (Exception e) { if (expectedExceptionClass == null || e.getClass() != expectedExceptionClass) { e.printStackTrace(); - Assert.fail("get failed " + pos + " with exception " + e.getClass() + ", expected exception: " + expectedExceptionClass + ". error: " + e.getMessage()); + Assert.fail("get failed [" + DhSectionPos.toString(pos) + "] with exception " + e.getClass() + ", expected exception: " + expectedExceptionClass + ". error: " + e.getMessage()); } } }