Replace DhSectionPos with long primitives to reduce GC

This commit is contained in:
James Seibel
2024-05-16 22:07:57 -05:00
parent cd5ff8ce35
commit 172e7560fd
47 changed files with 583 additions and 1012 deletions
@@ -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
{
@@ -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<Integer> columnBuilderDebugDetailLevel = new ConfigEntry.Builder<Integer>()
.set((int) OldDhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL)
.set((int) DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL)
.setAppearance(EConfigEntryAppearance.ONLY_IN_GUI)
.addListener(DebugColumnConfigEventHandler.INSTANCE)
.build();
@@ -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<Entry> 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;
@@ -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<IDhLevel>
{
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<IDhLevel>
/** 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<IDhLevel>
// 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<IDhLevel>
//=====================//
@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; }
@@ -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}. <br><br>
* This data source contains every datapoint over its given {@link DhSectionPos}. <br><br>
*
* @see FullDataPointUtil
* @see FullDataSourceV1
@@ -71,9 +71,9 @@ public class FullDataSourceV2 implements IDataSource<IDhLevel>
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<IDhLevel>
// 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<IDhLevel>
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<IDhLevel>
}
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<IDhLevel>
}
// 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<IDhLevel>
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<IDhLevel>
}
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<IDhLevel>
// 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<IDhLevel>
*
* @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<IDhLevel>
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<IDhLevel>
// 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<IDhLevel>
//=====================//
@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<IDhLevel>
//================//
@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<IDhLevel>
}
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<IDhLevel>
}
FullDataSourceV2 other = (FullDataSourceV2) obj;
if (!other.pos.equals(this.pos))
if (other.pos != this.pos)
{
return false;
}
@@ -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<IDhClientLevel>
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<ColumnRenderSource, IDhClientLevel> 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<IDhClientLevel>
/** 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<IDhClientLevel>
//==============//
/**
* 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<IDhClientLevel>
}
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<IDhClientLevel>
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<IDhClientLevel>
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<IDhClientLevel>
// 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; }
@@ -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;
}
@@ -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<Long> iterator()
default LongIterator iterator()
{
return new Iterator<Long>()
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++); }
};
}
@@ -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<OldDhSectionPos> 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();
@@ -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++)
@@ -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
<TDataSource extends IDataSource<TDhLevel>,
TDTO extends IBaseDTO<OldDhSectionPos>,
TRepo extends AbstractDhRepo<OldDhSectionPos, TDTO>,
TDTO extends IBaseDTO<Long>,
TRepo extends AbstractDhRepo<Long, TDTO>,
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<OldDhSectionPos> lockedPosSet = ConcurrentHashMap.newKeySet();
public final ConcurrentHashMap<OldDhSectionPos, AtomicInteger> queuedUpdateCountsByPos = new ConcurrentHashMap<>();
public final Set<Long> lockedPosSet = ConcurrentHashMap.newKeySet();
public final ConcurrentHashMap<Long, AtomicInteger> 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<TDataSource> getAsync(OldDhSectionPos pos)
public CompletableFuture<TDataSource> 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) ->
{
@@ -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<TDataSource extends IDataSource<TDhLevel>, TDhLevel
private final ArrayList<TDataSource> pooledDataSources = new ArrayList<>();
private final ReentrantLock poolLock = new ReentrantLock();
private final Function<OldDhSectionPos, TDataSource> createEmptyDatasourceFunc;
private final Function<Long, TDataSource> createEmptyDatasourceFunc;
@Nullable
private final IPrepPooledDataSourceFunc<TDataSource, TDhLevel> prepDatasourceFunc;
@@ -36,7 +36,7 @@ public class DataSourcePool<TDataSource extends IDataSource<TDhLevel>, TDhLevel
// constructor //
//=============//
public DataSourcePool(Function<OldDhSectionPos, TDataSource> createEmptyDatasourceFunc, @Nullable IPrepPooledDataSourceFunc<TDataSource, TDhLevel> prepDatasourceFunc)
public DataSourcePool(Function<Long, TDataSource> createEmptyDatasourceFunc, @Nullable IPrepPooledDataSourceFunc<TDataSource, TDhLevel> prepDatasourceFunc)
{
this.createEmptyDatasourceFunc = createEmptyDatasourceFunc;
this.prepDatasourceFunc = prepDatasourceFunc;
@@ -50,12 +50,12 @@ public class DataSourcePool<TDataSource extends IDataSource<TDhLevel>, 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<TDataSource extends IDataSource<TDhLevel>, TDhLevel
public interface IPrepPooledDataSourceFunc<TDataSource extends IDataSource<TDhLevel>, 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);
}
}
@@ -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 <TDhLevel> there are times when we need specifically a client level vs a more generic level
*/
public interface IDataSource<TDhLevel extends IDhLevel> extends IBaseDTO<OldDhSectionPos>, AutoCloseable
public interface IDataSource<TDhLevel extends IDhLevel> extends IBaseDTO<Long>, AutoCloseable
{
OldDhSectionPos getPos();
Long getPos();
/** @return true if the data was changed */
boolean update(FullDataSourceV2 chunkData, TDhLevel level);
@@ -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<OldDhSectionPos, FullDataSourceV2> dataSourceByPosition = new ConcurrentHashMap<>();
private final ConcurrentHashMap<OldDhSectionPos, TimerTask> saveTimerTasksBySectionPos = new ConcurrentHashMap<>();
public final ConcurrentHashMap<Long, FullDataSourceV2> dataSourceByPosition = new ConcurrentHashMap<>();
private final ConcurrentHashMap<Long, TimerTask> 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)
@@ -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<TDhLevel extends IDhLevel>
*
* This call is concurrent. I.e. it supports being called by multiple threads at the same time.
*/
public CompletableFuture<FullDataSourceV1> getAsync(OldDhSectionPos pos)
public CompletableFuture<FullDataSourceV1> getAsync(long pos)
{
ThreadPoolExecutor executor = ThreadPoolUtil.getFileHandlerExecutor();
if (executor == null || executor.isTerminated())
@@ -113,10 +114,10 @@ public class FullDataSourceProviderV1<TDhLevel extends IDhLevel>
/**
* 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<TDhLevel extends IDhLevel>
{
// 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<TDhLevel extends IDhLevel>
{
ArrayList<FullDataSourceV1> dataSourceList = new ArrayList<>();
ArrayList<OldDhSectionPos> 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<TDhLevel extends IDhLevel>
return dataSourceList;
}
public void markMigrationFailed(OldDhSectionPos pos) { ((FullDataSourceV1Repo) this.repo).markMigrationFailed(pos); }
public void markMigrationFailed(long pos) { ((FullDataSourceV1Repo) this.repo).markMigrationFailed(pos); }
@@ -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<OldDhSectionPos> parentUpdatingPosSet = ConcurrentHashMap.newKeySet();
public final Set<Long> 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<OldDhSectionPos> 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<OldDhSectionPos, HashSet<OldDhSectionPos>> updatePosByParentPos = new HashMap<>();
for (OldDhSectionPos pos : parentUpdatePosList)
HashMap<Long, HashSet<Long>> 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<OldDhSectionPos> 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<OldDhSectionPos, Boolean> removeIf) { }
public void removeRetrievalRequestIf(DhSectionPos.ICancelablePrimitiveLongConsumer removeIf) { }
public void clearRetrievalQueue() { }
@@ -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<WorldGenResult> worldGenFuture = worldGenQueue.submitGenTask(genPos, (byte) (genPos.getDetailLevel() - OldDhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL), genTask);
CompletableFuture<WorldGenResult> 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<OldDhSectionPos, Boolean> 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<OldDhSectionPos> 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<OldDhSectionPos> 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);
}
@@ -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");
@@ -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<OldDhSectionPos, Boolean> removeIf);
void removeRetrievalRequestIf(DhSectionPos.ICancelablePrimitiveLongConsumer removeIf);
CompletableFuture<WorldGenResult> submitGenTask(OldDhSectionPos pos, byte requiredDataDetail, IWorldGenTaskTracker tracker);
CompletableFuture<WorldGenResult> submitGenTask(long pos, byte requiredDataDetail, IWorldGenTaskTracker tracker);
@@ -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<OldDhSectionPos, WorldGenTask> waitingTasks = new ConcurrentHashMap<>();
private final ConcurrentHashMap<Long, WorldGenTask> waitingTasks = new ConcurrentHashMap<>();
private final ConcurrentHashMap<OldDhSectionPos, InProgressWorldGenTaskGroup> inProgressGenTasksByLodPos = new ConcurrentHashMap<>();
private final ConcurrentHashMap<Long, InProgressWorldGenTaskGroup> 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<OldDhSectionPos, StackTraceElement[]> alreadyGeneratedPosHashSet = new HashMap<>(MAX_ALREADY_GENERATED_COUNT);
private final Queue<OldDhSectionPos> alreadyGeneratedPosQueue = new LinkedList<>();
private final HashMap<Long, StackTraceElement[]> 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<WorldGenResult> submitGenTask(OldDhSectionPos pos, byte requiredDataDetail, IWorldGenTaskTracker tracker)
public CompletableFuture<WorldGenResult> 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<WorldGenResult> future = new CompletableFuture<>();
@@ -160,11 +161,11 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb
}
@Override
public void removeRetrievalRequestIf(Function<OldDhSectionPos, Boolean> 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<CompletableFuture<WorldGenResult>> 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<WorldGenResult> 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);
}
@@ -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<CompletableFuture<WorldGenResult>> childFutures = new LinkedList<>();
public static WorldGenResult CreateSplit(Collection<CompletableFuture<WorldGenResult>> 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<CompletableFuture<WorldGenResult>> childFutures)
public static WorldGenResult CreateSplit(Collection<CompletableFuture<WorldGenResult>> 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<CompletableFuture<WorldGenResult>> childFutures)
{
this.success = success;
this.pos = pos;
@@ -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<WorldGenResult> future;
public WorldGenTask(OldDhSectionPos pos, byte dataDetail, IWorldGenTaskTracker taskTracker, CompletableFuture<WorldGenResult> future)
public WorldGenTask(long pos, byte dataDetail, IWorldGenTaskTracker taskTracker, CompletableFuture<WorldGenResult> future)
{
this.dataDetailLevel = dataDetail;
this.pos = pos;
@@ -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<WorldGenTask> worldGenTasks = new LinkedList<>();
public WorldGenTaskGroup(OldDhSectionPos pos, byte dataDetail)
public WorldGenTaskGroup(long pos, byte dataDetail)
{
this.pos = pos;
this.dataDetail = dataDetail;
@@ -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<OldDhSectionPos, HashSet<DhChunkPos>> updatedChunkPosSetBySectionPos = new ConcurrentHashMap<>();
/** contains the {@link DhChunkPos} for each {@link DhSectionPos} that are queued to save via {@link AbstractDhLevel#delayedFullDataSourceSaveCache} */
protected final ConcurrentHashMap<Long, HashSet<DhChunkPos>> updatedChunkPosSetBySectionPos = new ConcurrentHashMap<>();
@@ -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)
@@ -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(
@@ -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
}
@@ -53,7 +53,7 @@ public class DhLodPos implements Comparable<DhLodPos>
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<DhLodPos>
}
/**
* @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>
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);
}
@@ -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. <br><br>
*
@@ -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
@@ -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 <https://www.gnu.org/licenses/>.
*/
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. <br><br>
*
* 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}).<br><br>
*
* <strong>Why does the smallest render section represent 2x2 MC chunks (section detail level 6)? </strong> <br>
* 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. <br>
* <strong>Too small</strong>, and we'll have 1,000s of sections running around, all needing individual files and render buffers.<br>
* <strong>Too big</strong>, and the LOD dropoff will be very noticeable.<br>
* 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: <br>
* 0 -> 1 <br>
* 1 -> 2 <br>
* 2 -> 4 <br>
* 3 -> 8 <br>
* 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 <br><br>
*
* Relative child positions returned for each index: <br>
* 0 = (0,0) - North West <br>
* 1 = (1,0) - South West <br>
* 2 = (0,1) - North East <br>
* 3 = (1,1) - South East <br>
*
* @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<OldDhSectionPos> 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<OldDhSectionPos, Boolean> 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<OldDhSectionPos> 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<OldDhSectionPos> 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. <br>
* Can be useful to prevent duplicate allocations in high traffic loops but should
* be used sparingly as it could accidentally cause bugs due to unexpected modifications.
*/
public void mutate(byte sectionDetailLevel, int sectionX, int sectionZ)
{
this.detailLevel = sectionDetailLevel;
this.x = sectionX;
this.z = sectionZ;
}
@Override
public void convertSelfToDetailLevel(byte newDetailLevel) { super.convertSelfToDetailLevel(newDetailLevel); }
//==================//
// property getters //
//==================//
public void setDetailLevel(byte sectionDetailLevel) { this.detailLevel = sectionDetailLevel; }
public void setX(int sectionX) { this.x = sectionX; }
public void setZ(int sectionZ) { this.z = sectionZ; }
}
}
@@ -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<LodRenderSection> implements IDebugRen
private final FullDataSourceProviderV2 fullDataSourceProvider;
/**
* This holds every {@link OldDhSectionPos} that should be reloaded next tick. <br>
* This holds every {@link DhSectionPos} that should be reloaded next tick. <br>
* This is a {@link ConcurrentLinkedQueue} because new sections can be added to this list via the world generator threads.
*/
private final ConcurrentLinkedQueue<OldDhSectionPos> sectionsToReload = new ConcurrentLinkedQueue<>();
private final ConcurrentLinkedQueue<Long> sectionsToReload = new ConcurrentLinkedQueue<>();
private final IDhClientLevel level; //FIXME: Proper hierarchy to remove this reference!
private final ConfigChangeListener<EDhApiHorizontalQuality> horizontalScaleChangeListener;
private final ReentrantLock treeReadWriteLock = new ReentrantLock();
@@ -181,12 +182,12 @@ public class LodQuadTree extends QuadTree<LodRenderSection> 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<LodRenderSection> 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<LodRenderSection> implements IDebugRen
// walk through each root node
ArrayList<LodRenderSection> nodesNeedingRetrieval = new ArrayList<>();
ArrayList<LodRenderSection> nodesNeedingLoading = new ArrayList<>();
Iterator<OldDhSectionPos> 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<LodRenderSection> 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<LodRenderSection> 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<LodRenderSection> rootNode, QuadNode<LodRenderSection> quadNode, OldDhSectionPos sectionPos,
QuadNode<LodRenderSection> rootNode, QuadNode<LodRenderSection> quadNode, long sectionPos,
boolean parentSectionIsRendering,
ArrayList<LodRenderSection> nodesNeedingRetrieval,
ArrayList<LodRenderSection> nodesNeedingLoading)
@@ -292,20 +293,20 @@ public class LodQuadTree extends QuadTree<LodRenderSection> 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<OldDhSectionPos> childPosIterator = quadNode.getChildPosIterator();
LongIterator childPosIterator = quadNode.getChildPosIterator();
while (childPosIterator.hasNext())
{
OldDhSectionPos childPos = childPosIterator.next();
long childPos = childPosIterator.nextLong();
QuadNode<LodRenderSection> 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<LodRenderSection> implements IDebugRen
childPosIterator = quadNode.getChildPosIterator();
while (childPosIterator.hasNext())
{
OldDhSectionPos childPos = childPosIterator.next();
long childPos = childPosIterator.nextLong();
QuadNode<LodRenderSection> childNode = rootNode.getNode(childPos);
boolean childSectionLoaded = this.recursivelyUpdateRenderSectionNode(playerPos, rootNode, childNode, childPos, parentSectionIsRendering, nodesNeedingRetrieval, nodesNeedingLoading);
@@ -348,7 +349,7 @@ public class LodQuadTree extends QuadTree<LodRenderSection> 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<LodRenderSection> 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<LodRenderSection> 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<LodRenderSection> implements IDebugRen
* Can be called whenever a render section's data needs to be refreshed. <br>
* 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<LodRenderSection> 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<LodRenderSection> 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);
});
@@ -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<OldDhSectionPos> 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 */ }
@@ -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<LoadedRenderBuffer> 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<LodRenderSection> 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;
@@ -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);
}
}
@@ -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<OldDhSectionPos>
public class FullDataSourceV1DTO implements IBaseDTO<Long>
{
public OldDhSectionPos pos;
public long pos;
public int checksum;
public byte dataDetailLevel;
public EDhApiWorldGenerationStep worldGenStep;
@@ -52,7 +52,7 @@ public class FullDataSourceV1DTO implements IBaseDTO<OldDhSectionPos>
// 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<OldDhSectionPos>
//===========//
@Override
public OldDhSectionPos getKey() { return this.pos; }
public Long getKey() { return this.pos; }
}
@@ -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<OldDhSectionPos>
public class FullDataSourceV2DTO implements IBaseDTO<Long>
{
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<OldDhSectionPos>
}
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<OldDhSectionPos>
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<OldDhSectionPos>
//===========//
@Override
public OldDhSectionPos getKey() { return this.pos; }
public Long getKey() { return this.pos; }
@@ -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<OldDhSectionPos, FullDataSourceV1DTO>
public class FullDataSourceV1Repo extends AbstractDhRepo<Long, FullDataSourceV1DTO>
{
public static final String TABLE_NAME = "Legacy_FullData_V1";
@@ -57,7 +58,7 @@ public class FullDataSourceV1Repo extends AbstractDhRepo<OldDhSectionPos, FullDa
public String getTableName() { return TABLE_NAME; }
@Override
public String createWhereStatement(OldDhSectionPos pos) { return "DhSectionPos = '"+serializeSectionPos(pos)+"'"; }
public String createWhereStatement(Long pos) { return "DhSectionPos = '"+serializeSectionPos(pos)+"'"; }
@@ -69,7 +70,7 @@ public class FullDataSourceV1Repo extends AbstractDhRepo<OldDhSectionPos, FullDa
public FullDataSourceV1DTO convertDictionaryToDto(Map<String, Object> 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<OldDhSectionPos, FullDa
/**
* Returns the highest numerical detail level in this table. <Br>
* 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<OldDhSectionPos, FullDa
maxDetailLevel = (int)resultMap.get("maxDetailLevel");
}
return maxDetailLevel + OldDhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL;
return maxDetailLevel + DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL;
}
@@ -207,9 +208,9 @@ public class FullDataSourceV1Repo extends AbstractDhRepo<OldDhSectionPos, FullDa
}
/** Returns the new "returnCount" positions that need to be migrated */
public ArrayList<OldDhSectionPos> getPositionsToMigrate(int returnCount)
public LongArrayList getPositionsToMigrate(int returnCount)
{
ArrayList<OldDhSectionPos> list = new ArrayList<>();
LongArrayList list = new LongArrayList();
List<Map<String, Object>> resultMapList = this.queryDictionary(
"select DhSectionPos " +
@@ -220,14 +221,14 @@ public class FullDataSourceV1Repo extends AbstractDhRepo<OldDhSectionPos, FullDa
for (Map<String, Object> 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<OldDhSectionPos, FullDa
}
}
/** Returns single quote surrounded {@link OldDhSectionPos} serailzed values */
/** Returns single quote surrounded {@link DhSectionPos} serailzed values */
public ArrayList<String> getUnusedDataSourcePositionStringList(int deleteCount)
{
List<Map<String, Object>> deletePosResultMapList = this.queryDictionary(
@@ -291,17 +292,24 @@ public class FullDataSourceV1Repo extends AbstractDhRepo<OldDhSectionPos, FullDa
// section pos helpers //
//=====================//
private static String serializeSectionPos(OldDhSectionPos pos) { return "[" + pos.getDetailLevel() + ',' + pos.getX() + ',' + pos.getZ() + ']'; }
private static String serializeSectionPos(long pos) { return "[" + DhSectionPos.getDetailLevel(pos) + ',' + DhSectionPos.getX(pos) + ',' + DhSectionPos.getZ(pos) + ']'; }
@Nullable
private static OldDhSectionPos deserializeSectionPos(String value)
private static Long deserializeSectionPos(String value)
{
if (value.charAt(0) != '[' || value.charAt(value.length() - 1) != ']') return null;
String[] split = value.substring(1, value.length() - 1).split(",");
if (split.length != 3) return null;
return new OldDhSectionPos(Byte.parseByte(split[0]), Integer.parseInt(split[1]), Integer.parseInt(split[2]));
if (value.charAt(0) != '[' || value.charAt(value.length() - 1) != ']')
{
return null;
}
String[] split = value.substring(1, value.length() - 1).split(",");
if (split.length != 3)
{
return null;
}
return DhSectionPos.encode(Byte.parseByte(split[0]), Integer.parseInt(split[1]), Integer.parseInt(split[2]));
}
}
@@ -22,9 +22,10 @@ package com.seibel.distanthorizons.core.sql.repo;
import com.seibel.distanthorizons.api.enums.config.EDhApiDataCompressionMode;
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.sql.dto.FullDataSourceV2DTO;
import com.seibel.distanthorizons.core.util.objects.dataStreams.DhDataInputStream;
import it.unimi.dsi.fastutil.longs.LongArrayList;
import org.apache.logging.log4j.Logger;
import java.io.ByteArrayInputStream;
@@ -35,7 +36,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class FullDataSourceV2Repo extends AbstractDhRepo<OldDhSectionPos, FullDataSourceV2DTO>
public class FullDataSourceV2Repo extends AbstractDhRepo<Long, FullDataSourceV2DTO>
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
@@ -60,10 +61,10 @@ public class FullDataSourceV2Repo extends AbstractDhRepo<OldDhSectionPos, FullDa
public String getTableName() { return "FullData"; }
@Override
public String createWhereStatement(OldDhSectionPos pos)
public String createWhereStatement(Long pos)
{
int detailLevel = pos.getDetailLevel() - OldDhSectionPos.SECTION_BLOCK_DETAIL_LEVEL;
return "DetailLevel = '"+detailLevel+"' AND PosX = '"+pos.getX()+"' AND PosZ = '"+pos.getZ()+"'";
int detailLevel = DhSectionPos.getDetailLevel(pos) - DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL;
return "DetailLevel = '"+detailLevel+"' AND PosX = '"+DhSectionPos.getX(pos)+"' AND PosZ = '"+DhSectionPos.getZ(pos)+"'";
}
@@ -76,10 +77,10 @@ public class FullDataSourceV2Repo extends AbstractDhRepo<OldDhSectionPos, FullDa
public FullDataSourceV2DTO convertDictionaryToDto(Map<String, Object> 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<OldDhSectionPos, FullDa
PreparedStatement statement = this.createPreparedStatement(sql);
int i = 1;
statement.setObject(i++, dto.pos.getDetailLevel() - OldDhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL);
statement.setObject(i++, dto.pos.getX());
statement.setObject(i++, dto.pos.getZ());
statement.setObject(i++, DhSectionPos.getDetailLevel(dto.pos) - DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL);
statement.setObject(i++, DhSectionPos.getX(dto.pos));
statement.setObject(i++, DhSectionPos.getZ(dto.pos));
statement.setObject(i++, dto.levelMinY);
statement.setObject(i++, dto.dataChecksum);
@@ -189,9 +190,9 @@ public class FullDataSourceV2Repo extends AbstractDhRepo<OldDhSectionPos, FullDa
statement.setObject(i++, System.currentTimeMillis()); // last modified unix time
statement.setObject(i++, dto.createdUnixDateTime);
statement.setObject(i++, dto.pos.getDetailLevel() - OldDhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL);
statement.setObject(i++, dto.pos.getX());
statement.setObject(i++, dto.pos.getZ());
statement.setObject(i++, DhSectionPos.getDetailLevel(dto.pos) - DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL);
statement.setObject(i++, DhSectionPos.getX(dto.pos));
statement.setObject(i++, DhSectionPos.getZ(dto.pos));
return statement;
}
@@ -200,21 +201,21 @@ public class FullDataSourceV2Repo extends AbstractDhRepo<OldDhSectionPos, FullDa
// updates //
public void setApplyToParent(OldDhSectionPos pos, boolean applyToParent) throws SQLException
public void setApplyToParent(long pos, boolean applyToParent) throws SQLException
{
int detailLevel = pos.getDetailLevel() - OldDhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL;
int detailLevel = DhSectionPos.getDetailLevel(pos) - DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL;
String sql =
"UPDATE "+this.getTableName()+" \n" +
"SET ApplyToParent = "+applyToParent+" \n" +
"WHERE DetailLevel = "+detailLevel+" AND PosX = "+pos.getX()+" AND PosZ = "+pos.getZ();
"WHERE DetailLevel = "+detailLevel+" AND PosX = "+DhSectionPos.getX(pos)+" AND PosZ = "+DhSectionPos.getZ(pos);
this.queryDictionaryFirst(sql);
}
public ArrayList<OldDhSectionPos> getPositionsToUpdate(int returnCount)
public LongArrayList getPositionsToUpdate(int returnCount)
{
ArrayList<OldDhSectionPos> list = new ArrayList<>();
LongArrayList list = new LongArrayList();
List<Map<String, Object>> resultMapList = this.queryDictionary(
"select DetailLevel, PosX, PosZ " +
@@ -225,11 +226,11 @@ public class FullDataSourceV2Repo extends AbstractDhRepo<OldDhSectionPos, FullDa
for (Map<String, Object> 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<OldDhSectionPos, FullDa
}
/** @return null if nothing exists for this position */
public byte[] getColumnGenerationStepForPos(OldDhSectionPos pos)
public byte[] getColumnGenerationStepForPos(long pos)
{
int detailLevel = pos.getDetailLevel() - OldDhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL;
int detailLevel = DhSectionPos.getDetailLevel(pos) - DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL;
Map<String, Object> 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<OldDhSectionPos, FullDa
}
catch (IOException e)
{
LOGGER.warn("Decompression issue when getting column gen steps for pos: "+pos, e);
LOGGER.warn("Decompression issue when getting column gen steps for pos: [" + DhSectionPos.toString(pos) + "]", e);
return null;
}
}
@@ -283,9 +284,9 @@ public class FullDataSourceV2Repo extends AbstractDhRepo<OldDhSectionPos, FullDa
//===================//
/** @return every position in this database */
public ArrayList<OldDhSectionPos> getAllPositions()
public LongArrayList getAllPositions()
{
ArrayList<OldDhSectionPos> list = new ArrayList<>();
LongArrayList list = new LongArrayList();
List<Map<String, Object>> resultMapList = this.queryDictionary(
"select DetailLevel, PosX, PosZ " +
@@ -294,11 +295,11 @@ public class FullDataSourceV2Repo extends AbstractDhRepo<OldDhSectionPos, FullDa
for (Map<String, Object> 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<OldDhSectionPos, FullDa
* @return the size of the full data at the given position
* (doesn't include the size of the mapping or any other column)
*/
public long getDataSizeInBytes(OldDhSectionPos pos)
public long getDataSizeInBytes(long pos)
{
int detailLevel = pos.getDetailLevel() - OldDhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL;
int detailLevel = DhSectionPos.getDetailLevel(pos) - DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL;
Map<String, Object> 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)
{
@@ -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<T>
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<T>
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<T>
* @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<T> getNode(OldDhSectionPos sectionPos) throws IllegalArgumentException { return this.getOrSetValue(sectionPos, false, null); }
public QuadNode<T> 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<T> previousNode = this.getNode(sectionPos);
if (previousNode != null)
@@ -173,27 +174,27 @@ public class QuadNode<T>
* @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<T> getOrSetValue(OldDhSectionPos inputSectionPos, boolean replaceValue, T newValue) throws IllegalArgumentException
private QuadNode<T> 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<T>
// 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<T>
// 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<T> 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<T>
// 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<T>
// 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<T>
// 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<T>
public Iterator<QuadNode<T>> getLeafNodeIterator() { return new QuadTreeNodeIterator<>(this, true); }
/** positions can point to null children */
public Iterator<OldDhSectionPos> getChildPosIterator() { return new QuadNodeDirectChildPosIterator<>(this); }
public LongIterator getChildPosIterator() { return new QuadNodeDirectChildPosIterator<>(this); }
public Iterator<QuadNode<T>> getChildNodeIterator() { return new QuadNodeDirectChildIterator<>(this); }
@@ -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<T>
//=====================//
/** @return the node at the given section position */
public final QuadNode<T> getNode(OldDhSectionPos pos) throws IndexOutOfBoundsException { return this.getOrSetNode(pos, false, null, true); }
public final QuadNode<T> 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<T> node = this.getNode(pos);
if (node != null)
@@ -106,7 +109,7 @@ public class QuadTree<T>
}
/** @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<T>
}
/** @param runBoundaryChecks should only ever be set to true internally for removing out of bound nodes */
protected final QuadNode<T> getOrSetNode(OldDhSectionPos pos, boolean setNewValue, T newValue, boolean runBoundaryChecks) throws IndexOutOfBoundsException
protected final QuadNode<T> 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<T> topQuadNode = this.topRingList.get(ringListPosX, ringListPosZ);
if (topQuadNode == null)
@@ -146,7 +149,7 @@ public class QuadTree<T>
}
}
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<T>
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<T>
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<T>
}
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<T>
//===========//
/** can include null nodes */
public Iterator<OldDhSectionPos> rootNodePosIterator() { return new QuadTreeRootPosIterator(true); }
public LongIterator rootNodePosIterator() { return new QuadTreeRootPosIterator(true); }
public Iterator<QuadNode<T>> nodeIterator() { return new QuadTreeNodeIterator(false); }
public Iterator<QuadNode<T>> leafNodeIterator() { return new QuadTreeNodeIterator(true); }
@@ -394,9 +397,9 @@ public class QuadTree<T>
// iterator classes //
//==================//
private class QuadTreeRootPosIterator implements Iterator<OldDhSectionPos>
private class QuadTreeRootPosIterator implements LongIterator
{
private final Queue<OldDhSectionPos> iteratorPosQueue = new ArrayDeque<>();
private final LongArrayFIFOQueue iteratorPosQueue = new LongArrayFIFOQueue();
@@ -406,11 +409,10 @@ public class QuadTree<T>
{
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<T>
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<T>
}
OldDhSectionPos sectionPos = this.iteratorPosQueue.poll();
long sectionPos = this.iteratorPosQueue.dequeueLong();
return sectionPos;
}
@@ -440,7 +442,7 @@ public class QuadTree<T>
public void remove() { throw new UnsupportedOperationException("remove"); }
@Override
public void forEachRemaining(Consumer<? super OldDhSectionPos> action) { Iterator.super.forEachRemaining(action); }
public void forEachRemaining(LongConsumer action) { LongIterator.super.forEachRemaining(action); }
}
@@ -498,7 +500,7 @@ public class QuadTree<T>
Iterator<QuadNode<T>> nodeIterator = null;
while ((nodeIterator == null || !nodeIterator.hasNext()) && this.rootNodeIterator.hasNext())
{
OldDhSectionPos sectionPos = this.rootNodeIterator.next();
long sectionPos = this.rootNodeIterator.nextLong();
QuadNode<T> rootNode = QuadTree.this.getNode(sectionPos);
if (rootNode != null)
{
@@ -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<T> implements Iterator<Integer>
public QuadNodeChildIndexIterator(QuadNode<T> parentNode, boolean returnNullChildPos)
{
// only get the children if this section isn't at the bottom of the tree
if (parentNode.sectionPos.getDetailLevel() > parentNode.minimumDetailLevel)
if (DhSectionPos.getDetailLevel(parentNode.sectionPos) > parentNode.minimumDetailLevel)
{
// go over each child pos
for (int i = 0; i < 4; i++)
@@ -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<T> implements Iterator<OldDhSectionPos>
public class QuadNodeDirectChildPosIterator<T> implements LongIterator
{
private final QuadNodeChildIndexIterator<T> childIndexIterator;
private final QuadNode<T> parentNode;
@@ -44,7 +46,7 @@ public class QuadNodeDirectChildPosIterator<T> implements Iterator<OldDhSectionP
public boolean hasNext() { return this.childIndexIterator.hasNext(); }
@Override
public OldDhSectionPos next()
public long nextLong()
{
if (!this.hasNext())
{
@@ -53,7 +55,7 @@ public class QuadNodeDirectChildPosIterator<T> implements Iterator<OldDhSectionP
int childIndex = this.childIndexIterator.next();
OldDhSectionPos sectionPos = this.parentNode.sectionPos.getChildByIndex(childIndex);
long sectionPos = DhSectionPos.getChildByIndex(childIndex, this.parentNode.sectionPos);
return sectionPos;
}
@@ -63,6 +65,6 @@ public class QuadNodeDirectChildPosIterator<T> implements Iterator<OldDhSectionP
public void remove() { throw new UnsupportedOperationException("remove"); }
@Override
public void forEachRemaining(Consumer<? super OldDhSectionPos> action) { Iterator.super.forEachRemaining(action); }
public void forEachRemaining(LongConsumer action) { LongIterator.super.forEachRemaining(action); }
}
@@ -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<T> implements Iterator<QuadNode<T>>
this.onlyReturnLeafValues = onlyReturnLeafValues;
// TODO the naming conversion for these are flipped in a lot of places
this.highestDetailLevel = rootNode.minimumDetailLevel;
this.iteratorDetailLevel = rootNode.sectionPos.getDetailLevel();
this.iteratorDetailLevel = DhSectionPos.getDetailLevel(rootNode.sectionPos);
if (!this.onlyReturnLeafValues)
@@ -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<OldDhSectionPos, ExpiringLock> lockByPos = new ConcurrentHashMap<>();
private final ConcurrentHashMap<Long, ExpiringLock> 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<OldDhSectionPos> keySet = this.lockByPos.keySet().iterator();
Iterator<Long> 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();
}
@@ -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<OldDhSectionPos> 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);
+27 -21
View File
@@ -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
+137 -137
View File
@@ -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<OldDhSectionPos> rootNodePosIterator = tree.rootNodePosIterator();
LongIterator rootNodePosIterator = tree.rootNodePosIterator();
while (rootNodePosIterator.hasNext())
{
QuadNode<Integer> rootNode = tree.getNode(rootNodePosIterator.next());
QuadNode<Integer> 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<Integer> rootNode = new QuadNode<>(new OldDhSectionPos((byte) 10, 0, 0), LodUtil.BLOCK_DETAIL_LEVEL);
QuadNode<Integer> 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<Integer> 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<OldDhSectionPos> rootNodePosIterator = tree.rootNodePosIterator();
LongIterator rootNodePosIterator = tree.rootNodePosIterator();
while (rootNodePosIterator.hasNext())
{
QuadNode<Integer> rootNode = tree.getNode(rootNodePosIterator.next());
QuadNode<Integer> 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<Integer> 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<OldDhSectionPos> 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<Integer> rootNode = tree.getNode(rootNodePosIterator.next());
QuadNode<Integer> 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<OldDhSectionPos> rootNodeIterator = tree.rootNodePosIterator();
LongIterator rootNodeIterator = tree.rootNodePosIterator();
while (rootNodeIterator.hasNext())
{
QuadNode<Integer> rootNode = tree.getNode(rootNodeIterator.next());
QuadNode<Integer> 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<OldDhSectionPos> rootNodeIterator = tree.rootNodePosIterator();
LongIterator rootNodeIterator = tree.rootNodePosIterator();
while (rootNodeIterator.hasNext())
{
QuadNode<Integer> rootNode = tree.getNode(rootNodeIterator.next());
QuadNode<Integer> 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<OldDhSectionPos> rootNodePosIterator = tree.rootNodePosIterator();
LongIterator rootNodePosIterator = tree.rootNodePosIterator();
while (rootNodePosIterator.hasNext())
{
OldDhSectionPos sectionPos = rootNodePosIterator.next();
long sectionPos = rootNodePosIterator.nextLong();
QuadNode<Integer> rootNode = tree.getNode(sectionPos);
if (rootNode != null)
{
// fill in the root node's direct children
Iterator<OldDhSectionPos> 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<Integer> 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<OldDhSectionPos> 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<Integer> 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<Integer> rootNode = new QuadNode<>(new OldDhSectionPos((byte) 10, 0, 0), (byte) 0);
Iterator<OldDhSectionPos> directChildPosIterator = rootNode.getChildPosIterator();
QuadNode<Integer> 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<Integer> 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<OldDhSectionPos> 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<Integer> rootNode = new QuadNode<>(new OldDhSectionPos((byte) 10, 0, 0), LodUtil.BLOCK_DETAIL_LEVEL);
QuadNode<Integer> 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<Integer> tree, OldDhSectionPos pos, Integer setValue) { testSet(tree, pos, setValue, null); }
private static <TE extends Throwable> void testSet(QuadTree<Integer> tree, OldDhSectionPos pos, Integer setValue, Class<TE> expectedExceptionClass)
private static void testSet(QuadTree<Integer> tree, long pos, Integer setValue) { testSet(tree, pos, setValue, null); }
private static <TE extends Throwable> void testSet(QuadTree<Integer> tree, long pos, Integer setValue, Class<TE> 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<Integer> tree, OldDhSectionPos pos, Integer getValue) { testSet(tree, pos, getValue, null); }
private static <TE extends Throwable> void testGet(QuadTree<Integer> tree, OldDhSectionPos pos, Integer getValue, Class<TE> expectedExceptionClass)
private static void testGet(QuadTree<Integer> tree, long pos, Integer getValue) { testSet(tree, pos, getValue, null); }
private static <TE extends Throwable> void testGet(QuadTree<Integer> tree, long pos, Integer getValue, Class<TE> 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());
}
}
}