Add AbstractDhApiChunkWorldGenerator.generateApiChunk()

This commit is contained in:
James Seibel
2024-07-20 10:45:43 -05:00
parent f442ab56c0
commit 99dc644adf
12 changed files with 303 additions and 216 deletions
@@ -22,6 +22,8 @@ package com.seibel.distanthorizons.api.interfaces.override.worldGenerator;
import com.seibel.distanthorizons.api.enums.EDhApiDetailLevel;
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorMode;
import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable;
import com.seibel.distanthorizons.api.objects.data.DhApiChunk;
import com.seibel.distanthorizons.api.objects.data.DhApiTerrainDataPoint;
import com.seibel.distanthorizons.coreapi.util.BitShiftUtil;
import java.io.Closeable;
@@ -77,13 +79,41 @@ public abstract class AbstractDhApiChunkWorldGenerator implements Closeable, IDh
}, worldGeneratorThreadPool);
}
@Override
public final CompletableFuture<Void> generateApiChunks(
int chunkPosMinX,
int chunkPosMinZ,
byte granularity,
byte targetDataDetail,
EDhApiDistantGeneratorMode generatorMode,
ExecutorService worldGeneratorThreadPool,
Consumer<DhApiChunk> resultConsumer
)
{
return CompletableFuture.runAsync(() ->
{
// TODO what does this mean?
int genChunkWidth = BitShiftUtil.powerOfTwo(granularity - 4);
for (int chunkX = chunkPosMinX; chunkX < chunkPosMinX + genChunkWidth; chunkX++)
{
for (int chunkZ = chunkPosMinZ; chunkZ < chunkPosMinZ + genChunkWidth; chunkZ++)
{
DhApiChunk apiChunk = this.generateApiChunk(chunkX, chunkZ, generatorMode);
resultConsumer.accept(apiChunk);
}
}
}, worldGeneratorThreadPool);
}
/**
* This method is called to generate terrain over a given area
* from a thread defined by Distant Horizons. <br><br>
*
* @param chunkPosX the chunk X position in the level (not to be confused with the chunk's BlockPos in the level)
* @param chunkPosZ the chunk Z position in the level (not to be confused with the chunk's BlockPos in the level)
* @param generatorMode how far into the world gen pipeline this method run. See {@link EDhApiDistantGeneratorMode} for additional documentation.
* @param generatorMode how far into the world gen pipeline this method should run. See {@link EDhApiDistantGeneratorMode} for additional documentation.
*
* @return See {@link IDhApiWorldGenerator#generateChunks(int, int, byte, byte, EDhApiDistantGeneratorMode, ExecutorService, Consumer) IDhApiWorldGenerator.generateChunks}
* for the list of Object's this method should return along with additional documentation.
@@ -92,4 +122,21 @@ public abstract class AbstractDhApiChunkWorldGenerator implements Closeable, IDh
*/
public abstract Object[] generateChunk(int chunkPosX, int chunkPosZ, EDhApiDistantGeneratorMode generatorMode);
/**
* This method is called to generate terrain over a given area
* from a thread defined by Distant Horizons. <br><br>
*
* @param chunkPosX the chunk X position in the level (not to be confused with the chunk's BlockPos in the level)
* @param chunkPosZ the chunk Z position in the level (not to be confused with the chunk's BlockPos in the level)
* @param generatorMode how far into the world gen pipeline this method should run. See {@link EDhApiDistantGeneratorMode} for additional documentation.
*
* @return A {@link DhApiChunk} with the generated {@link DhApiTerrainDataPoint} including air blocks.
* Note: if air blocks aren't included with the proper lighting, lower detail levels will appear as black/unlit.
*
* @see IDhApiWorldGenerator#generateApiChunks(int, int, byte, byte, EDhApiDistantGeneratorMode, ExecutorService, Consumer)
*
* @since API 3.0.0
*/
public abstract DhApiChunk generateApiChunk(int chunkPosX, int chunkPosZ, EDhApiDistantGeneratorMode generatorMode);
}
@@ -154,6 +154,7 @@ public interface IDhApiWorldGenerator extends Closeable, IDhApiOverrideable
*
* After the {@link DhApiChunk} has been generated, it should be passed into the
* resultConsumer's {@link Consumer#accept(Object)} method.
* Note: if air blocks aren't included in the with the {@link DhApiChunk} with proper lighting, lower detail levels will appear as black/unlit.
*
* @implNote the default implementation of this method throws an {@link UnsupportedOperationException},
* and must be overridden when {@link #getReturnType()} returns {@link EDhApiWorldGeneratorReturnType#API_CHUNKS}.
@@ -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);
long pos = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ);
long pos = DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ);
FullDataSourceV2 dataSource = FullDataSourceV2.createEmpty(pos);
dataSource.isEmpty = false;
@@ -302,14 +302,19 @@ public class LodDataBuilder
/** @throws ClassCastException if an API user returns the wrong object type(s) */
public static FullDataSourceV2 createFromApiChunkData(DhApiChunk dataPoints) throws ClassCastException, DataCorruptedException
public static FullDataSourceV2 createFromApiChunkData(DhApiChunk apiChunk) throws ClassCastException, DataCorruptedException
{
FullDataSourceV2 accessor = FullDataSourceV2.createEmpty(DhSectionPos.encode(new DhChunkPos(dataPoints.chunkPosX, dataPoints.chunkPosZ)));
for (int relZ = 0; relZ < LodUtil.CHUNK_WIDTH; relZ++)
// TODO
long pos = DhSectionPos.convertToDetailLevel(DhSectionPos.encodeChunkPos(apiChunk.chunkPosX, apiChunk.chunkPosZ), DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL);
int relSourceBlockX = Math.abs(apiChunk.chunkPosX % 4) * LodUtil.CHUNK_WIDTH;
int relSourceBlockZ = Math.abs(apiChunk.chunkPosZ % 4) * LodUtil.CHUNK_WIDTH;
FullDataSourceV2 dataSource = FullDataSourceV2.createEmpty(pos);
for (int relBlockZ = 0; relBlockZ < LodUtil.CHUNK_WIDTH; relBlockZ++)
{
for (int relX = 0; relX < LodUtil.CHUNK_WIDTH; relX++)
for (int relBlockX = 0; relBlockX < LodUtil.CHUNK_WIDTH; relBlockX++)
{
List<DhApiTerrainDataPoint> columnDataPoints = dataPoints.getDataPoints(relX, relZ);
List<DhApiTerrainDataPoint> columnDataPoints = apiChunk.getDataPoints(relBlockX, relBlockZ);
// this null check does 2 nice things at the same time:
@@ -323,7 +328,7 @@ public class LodDataBuilder
{
DhApiTerrainDataPoint dataPoint = columnDataPoints.get(index);
int id = accessor.mapping.addIfNotPresentAndGetId(
int id = dataSource.mapping.addIfNotPresentAndGetId(
(IBiomeWrapper) (dataPoint.biomeWrapper),
(IBlockStateWrapper) (dataPoint.blockStateWrapper)
);
@@ -331,7 +336,7 @@ public class LodDataBuilder
packedDataPoints.set(index, FullDataPointUtil.encode(
id,
dataPoint.topYBlockPos - dataPoint.bottomYBlockPos,
dataPoint.bottomYBlockPos - dataPoints.topYBlockPos,
dataPoint.bottomYBlockPos - apiChunk.topYBlockPos,
(byte) (dataPoint.blockLightLevel),
(byte) (dataPoint.skyLightLevel)
));
@@ -339,11 +344,14 @@ public class LodDataBuilder
// TODO add the ability for API users to define a different compression mode
// or add a "unkown" compression mode
accessor.setSingleColumn(packedDataPoints, relX, relZ, EDhApiWorldGenerationStep.LIGHT, EDhApiWorldCompressionMode.MERGE_SAME_BLOCKS);
dataSource.setSingleColumn(
packedDataPoints,
relBlockX + relSourceBlockX, relBlockZ + relSourceBlockZ,
EDhApiWorldGenerationStep.LIGHT, EDhApiWorldCompressionMode.MERGE_SAME_BLOCKS);
dataSource.isEmpty = false;
}
}
return accessor;
return dataSource;
}
@@ -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(DhSectionPos.encode(this.playerData.playerBlockPos));
FullDataSourceV2 newDataSource = FullDataSourceV2.createEmpty(DhSectionPos.encodeLodPos(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(DhSectionPos.encode(this.playerData.playerBlockPos)).join();
testFullDataSource = tempLevel.getFullDataProvider().getAsync(DhSectionPos.encodeLodPos(this.playerData.playerBlockPos)).join();
if (testFullDataSource == null)
{
continue;
@@ -343,7 +343,7 @@ 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(DhSectionPos.encode(granularity, DhSectionPos.getX(taskPos), DhSectionPos.getZ(taskPos)))));
newTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(DhSectionPos.encodePos(granularity, DhSectionPos.getX(taskPos), DhSectionPos.getZ(taskPos)))));
return false;
}
this.alreadyGeneratedPosHashSet.put(newTaskGroup.group.pos, Thread.currentThread().getStackTrace());
@@ -373,21 +373,21 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb
// don't log the shutdown exceptions
if (!LodUtil.isInterruptOrReject(exception))
{
LOGGER.error("Error generating data for section " + taskPos, exception);
LOGGER.error("Error generating data for pos: " + DhSectionPos.toString(taskPos), exception);
}
newTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateFail()));
}
else
{
newTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(DhSectionPos.encode(granularity, DhSectionPos.getX(taskPos), DhSectionPos.getZ(taskPos)))));
newTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(DhSectionPos.encodePos(granularity, DhSectionPos.getX(taskPos), DhSectionPos.getZ(taskPos)))));
}
boolean worked = this.inProgressGenTasksByLodPos.remove(taskPos, newTaskGroup);
LodUtil.assertTrue(worked);
LodUtil.assertTrue(worked, "Unable to find in progress generator task with position ["+DhSectionPos.toString(taskPos)+"]");
}
catch (Exception e)
{
LOGGER.error("Unexpected error completing world gen task: "+taskPos, e);
LOGGER.error("Unexpected error completing world gen task at pos: ["+DhSectionPos.toString(taskPos)+"].", e);
}
});
@@ -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 DhSectionPos.encode(lodPos.detailLevel, lodPos.x, lodPos.z);
return DhSectionPos.encodePos(lodPos.detailLevel, lodPos.x, lodPos.z);
}
@@ -81,7 +81,7 @@ public class DhSectionPos
* This class just holds utility methods for handling a packed
* {@link DhSectionPos} and shouldn't be constructed. <Br><br>
*
* Use one of the {@link DhSectionPos#encode(byte, int, int)} methods instead
* Use one of the {@link DhSectionPos#encodePos(byte, int, int)} methods instead
*/
private DhSectionPos() { }
@@ -92,7 +92,7 @@ public class DhSectionPos
* no validation is done for whether the detail level is positive
* or if the X/Z positions can be represented by available bits.
*/
public static long encode(byte detailLevel, int x, int z)
public static long encodePos(byte detailLevel, int x, int z)
{
long data = 0;
data |= detailLevel & DETAIL_LEVEL_MASK;
@@ -101,23 +101,27 @@ public class DhSectionPos
return data;
}
public static long encode(DhBlockPos pos) { return encodeBlockPos(pos.x, pos.z); }
public static long encode(DhBlockPos2D pos) { return encodeBlockPos(pos.x, pos.z); }
public static long encodeBlockPos(int blockX, int blockZ)
// TODO need changing
public static long encodeLodPos(DhBlockPos pos) { return encodeLodBlockPos(pos.x, pos.z); }
public static long encodeLodPos(DhBlockPos2D pos) { return encodeLodBlockPos(pos.x, pos.z); }
public static long encodeLodBlockPos(int blockX, int blockZ)
{
long pos = encode(LodUtil.BLOCK_DETAIL_LEVEL, blockX, blockZ);
long pos = encodePos(LodUtil.BLOCK_DETAIL_LEVEL, blockX, blockZ);
pos = convertToDetailLevel(pos, DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL);
return pos;
}
public static long encode(DhChunkPos pos) { return encodeChunkPos(pos.x, pos.z); }
public static long encodeChunkPos(int chunkX, int chunkZ)
public static long encodeLodPos(DhChunkPos pos) { return encodeLodChunkPos(pos.x, pos.z); }
public static long encodeLodChunkPos(int chunkX, int chunkZ) // TODO broken?
{
long pos = encode(LodUtil.CHUNK_DETAIL_LEVEL, chunkX, chunkZ);
long pos = encodePos(LodUtil.CHUNK_DETAIL_LEVEL, chunkX, chunkZ);
pos = convertToDetailLevel(pos, DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL);
return pos;
}
public static long encodePos(DhChunkPos pos) { return encodeChunkPos(pos.x, pos.z); }
public static long encodeChunkPos(int chunkX, int chunkZ) { return encodePos(LodUtil.CHUNK_DETAIL_LEVEL, chunkX, chunkZ); }
//============//
@@ -143,7 +147,7 @@ public class DhSectionPos
z = z * BitShiftUtil.powerOfTwo(detailLevel - newDetailLevel);
}
return encode(newDetailLevel, x, z);
return encodePos(newDetailLevel, x, z);
}
@@ -279,14 +283,14 @@ public class DhSectionPos
throw new IllegalStateException("section detail must be greater than 0");
}
return DhSectionPos.encode((byte) (detailLevel - 1),
return DhSectionPos.encodePos((byte) (detailLevel - 1),
x * 2 + (child0to3 & 1),
z * 2 + BitShiftUtil.half(child0to3 & 2));
}
/** Returns this position's child index in its parent */
public static int getChildIndexOfParent(long pos) { return (getX(pos) & 1) + BitShiftUtil.square(getZ(pos) & 1); }
public static long getParentPos(long pos) { return DhSectionPos.encode((byte) (getDetailLevel(pos) + 1), BitShiftUtil.half(getX(pos)), BitShiftUtil.half(getZ(pos))); }
public static long getParentPos(long pos) { return DhSectionPos.encodePos((byte) (getDetailLevel(pos) + 1), BitShiftUtil.half(getX(pos)), BitShiftUtil.half(getZ(pos))); }
@@ -297,7 +301,7 @@ public class DhSectionPos
throw new IllegalArgumentException("getAdjacentPos can't be UP or DOWN, direction given: ["+dir.name()+"].");
}
return DhSectionPos.encode(getDetailLevel(pos),
return DhSectionPos.encodePos(getDetailLevel(pos),
getX(pos) + dir.getNormal().x,
getZ(pos) + dir.getNormal().z);
}
@@ -309,7 +309,7 @@ public class FullDataSourceV1Repo extends AbstractDhRepo<Long, FullDataSourceV1D
return null;
}
return DhSectionPos.encode(Byte.parseByte(split[0]), Integer.parseInt(split[1]), Integer.parseInt(split[2]));
return DhSectionPos.encodePos(Byte.parseByte(split[0]), Integer.parseInt(split[1]), Integer.parseInt(split[2]));
}
}
@@ -80,7 +80,7 @@ public class FullDataSourceV2Repo extends AbstractDhRepo<Long, FullDataSourceV2D
byte sectionDetailLevel = (byte) (detailLevel + DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL);
int posX = (Integer) objectMap.get("PosX");
int posZ = (Integer) objectMap.get("PosZ");
long pos = DhSectionPos.encode(sectionDetailLevel, posX, posZ);
long pos = DhSectionPos.encodePos(sectionDetailLevel, posX, posZ);
int minY = (Integer) objectMap.get("MinY");
int dataChecksum = (Integer) objectMap.get("DataChecksum");
@@ -230,7 +230,7 @@ public class FullDataSourceV2Repo extends AbstractDhRepo<Long, FullDataSourceV2D
int posX = (Integer) resultMap.get("PosX");
int posZ = (Integer) resultMap.get("PosZ");
long pos = DhSectionPos.encode(sectionDetailLevel, posX, posZ);
long pos = DhSectionPos.encodePos(sectionDetailLevel, posX, posZ);
list.add(pos);
}
@@ -299,7 +299,7 @@ public class FullDataSourceV2Repo extends AbstractDhRepo<Long, FullDataSourceV2D
int posX = (Integer) resultMap.get("PosX");
int posZ = (Integer) resultMap.get("PosZ");
long pos = DhSectionPos.encode(sectionDetailLevel, posX, posZ);
long pos = DhSectionPos.encodePos(sectionDetailLevel, posX, posZ);
list.add(pos);
}
@@ -409,7 +409,7 @@ public class QuadTree<T>
{
if (node != null || includeNullNodes)
{
long rootPos = DhSectionPos.encode(QuadTree.this.treeMinDetailLevel, pos2D.x, pos2D.y);
long rootPos = DhSectionPos.encodePos(QuadTree.this.treeMinDetailLevel, pos2D.x, pos2D.y);
if (QuadTree.this.isSectionPosInBounds(rootPos))
{
this.iteratorPosQueue.enqueue(rootPos);
+109 -82
View File
@@ -24,6 +24,7 @@ import com.seibel.distanthorizons.core.pos.DhSectionPos;
import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.pos.DhBlockPos;
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
import com.seibel.distanthorizons.core.util.LodUtil;
import org.junit.Assert;
import org.junit.Test;
@@ -39,19 +40,19 @@ public class DhSectionPosTest
long pos;
// zero pos
pos = DhSectionPos.encode((byte) 0, 0, 0);
pos = DhSectionPos.encodePos((byte) 0, 0, 0);
assertSectionPosEqual(0, DhSectionPos.getDetailLevel(pos));
assertSectionPosEqual(0, DhSectionPos.getX(pos));
assertSectionPosEqual(0, DhSectionPos.getZ(pos));
// positive values
pos = DhSectionPos.encode((byte) 10, 4, 1);
pos = DhSectionPos.encodePos((byte) 10, 4, 1);
assertSectionPosEqual(10, DhSectionPos.getDetailLevel(pos));
assertSectionPosEqual(4, DhSectionPos.getX(pos));
assertSectionPosEqual(1, DhSectionPos.getZ(pos));
// negative position, positive detail level
pos = DhSectionPos.encode((byte) 2, -1, -4);
pos = DhSectionPos.encodePos((byte) 2, -1, -4);
assertSectionPosEqual(2, DhSectionPos.getDetailLevel(pos));
assertSectionPosEqual(-1, DhSectionPos.getX(pos));
assertSectionPosEqual(-4, DhSectionPos.getZ(pos));
@@ -63,61 +64,61 @@ public class DhSectionPosTest
@Test
public void containsPosTest()
{
long root = DhSectionPos.encode((byte) 10, 0, 0);
long child = DhSectionPos.encode((byte) 9, 1, 1);
long root = DhSectionPos.encodePos((byte) 10, 0, 0);
long child = DhSectionPos.encodePos((byte) 9, 1, 1);
Assert.assertTrue("section pos contains fail", DhSectionPos.contains(root, child));
Assert.assertFalse("section pos contains fail", DhSectionPos.contains(child, root));
root = DhSectionPos.encode((byte) 10, 1, 0);
root = DhSectionPos.encodePos((byte) 10, 1, 0);
// out of bounds
child = DhSectionPos.encode((byte) 9, 0, 0);
child = DhSectionPos.encodePos((byte) 9, 0, 0);
Assert.assertFalse("position should be out of bounds", DhSectionPos.contains(root, child));
child = DhSectionPos.encode((byte) 9, 1, 1);
child = DhSectionPos.encodePos((byte) 9, 1, 1);
Assert.assertFalse("position should be out of bounds", DhSectionPos.contains(root, child));
// in bounds
child = DhSectionPos.encode((byte) 9, 2, 0);
child = DhSectionPos.encodePos((byte) 9, 2, 0);
Assert.assertTrue("position should be in bounds", DhSectionPos.contains(root, child));
child = DhSectionPos.encode((byte) 9, 3, 1);
child = DhSectionPos.encodePos((byte) 9, 3, 1);
Assert.assertTrue("position should be in bounds", DhSectionPos.contains(root, child));
// out of bounds
child = DhSectionPos.encode((byte) 9, 2, 2);
child = DhSectionPos.encodePos((byte) 9, 2, 2);
Assert.assertFalse("position should be out of bounds", DhSectionPos.contains(root, child));
child = DhSectionPos.encode((byte) 9, 3, 3);
child = DhSectionPos.encodePos((byte) 9, 3, 3);
Assert.assertFalse("position should be out of bounds", DhSectionPos.contains(root, child));
child = DhSectionPos.encode((byte) 9, 4, 4);
child = DhSectionPos.encodePos((byte) 9, 4, 4);
Assert.assertFalse("position should be out of bounds", DhSectionPos.contains(root, child));
child = DhSectionPos.encode((byte) 9, 5, 5);
child = DhSectionPos.encodePos((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)));
Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encodePos((byte) 6, 0, 0), DhSectionPos.encodePos((byte) 0, 0, 0)));
Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encodePos((byte) 6, 0, 0), DhSectionPos.encodePos((byte) 1, 0, 0)));
Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encodePos((byte) 6, 0, 0), DhSectionPos.encodePos((byte) 2, 0, 0)));
Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encodePos((byte) 6, 0, 0), DhSectionPos.encodePos((byte) 3, 0, 0)));
Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encodePos((byte) 6, 0, 0), DhSectionPos.encodePos((byte) 4, 0, 0)));
Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encodePos((byte) 6, 0, 0), DhSectionPos.encodePos((byte) 5, 0, 0)));
Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encodePos((byte) 6, 0, 0), DhSectionPos.encodePos((byte) 6, 0, 0)));
}
@Test
public void containsAdjacentPosTest()
{
// neither should contain the other, they are single blocks that are next to each other
long left = DhSectionPos.encode((byte) 0, 4606, 0);
long right = DhSectionPos.encode((byte) 0, 4607, 0);
long left = DhSectionPos.encodePos((byte) 0, 4606, 0);
long right = DhSectionPos.encodePos((byte) 0, 4607, 0);
Assert.assertFalse(DhSectionPos.contains(left, right));
Assert.assertFalse(DhSectionPos.contains(right, left));
// 512 block wide sections that are adjacent, but not overlapping
left = DhSectionPos.encode((byte) 9, 0, 0);
right = DhSectionPos.encode((byte) 9, 1, 0);
left = DhSectionPos.encodePos((byte) 9, 0, 0);
right = DhSectionPos.encodePos((byte) 9, 1, 0);
Assert.assertFalse(DhSectionPos.contains(left, right));
Assert.assertFalse(DhSectionPos.contains(right, left));
@@ -126,19 +127,19 @@ public class DhSectionPosTest
@Test
public void parentPosTest()
{
long leaf = DhSectionPos.encode((byte) 0, 0, 0);
long leaf = DhSectionPos.encodePos((byte) 0, 0, 0);
long convert = DhSectionPos.convertToDetailLevel(leaf, (byte) 1);
long parent = DhSectionPos.getParentPos(leaf);
assertSectionPosEqual("get parent at 0,0 fail", convert, parent);
leaf = DhSectionPos.encode((byte) 0, 1, 1);
leaf = DhSectionPos.encodePos((byte) 0, 1, 1);
convert = DhSectionPos.convertToDetailLevel(leaf, (byte) 1);
parent = DhSectionPos.getParentPos(leaf);
assertSectionPosEqual("get parent at 1,1 fail", convert, parent);
leaf = DhSectionPos.encode((byte) 1, 2, 2);
leaf = DhSectionPos.encodePos((byte) 1, 2, 2);
convert = DhSectionPos.convertToDetailLevel(leaf, (byte) 2);
parent = DhSectionPos.getParentPos(leaf);
assertSectionPosEqual("parent upscale fail", convert, parent);
@@ -151,7 +152,7 @@ public class DhSectionPosTest
@Test
public void childPosTest()
{
long node = DhSectionPos.encode((byte) 1, 2302, 0);
long node = DhSectionPos.encodePos((byte) 1, 2302, 0);
long nw = DhSectionPos.getChildByIndex(node, 0);
long sw = DhSectionPos.getChildByIndex(node, 1);
long ne = DhSectionPos.getChildByIndex(node, 2);
@@ -163,18 +164,18 @@ public class DhSectionPosTest
Assert.assertNotEquals(ne, se);
// confirm each child has the correct value
assertSectionPosEqual(nw, DhSectionPos.encode((byte) 0, 4604, 0));
assertSectionPosEqual(sw, DhSectionPos.encode((byte) 0, 4605, 0));
assertSectionPosEqual(ne, DhSectionPos.encode((byte) 0, 4604, 1));
assertSectionPosEqual(se, DhSectionPos.encode((byte) 0, 4605, 1));
assertSectionPosEqual(nw, DhSectionPos.encodePos((byte) 0, 4604, 0));
assertSectionPosEqual(sw, DhSectionPos.encodePos((byte) 0, 4605, 0));
assertSectionPosEqual(ne, DhSectionPos.encodePos((byte) 0, 4604, 1));
assertSectionPosEqual(se, DhSectionPos.encodePos((byte) 0, 4605, 1));
}
@Test
public void getCenterBlock2DTest()
{
long parentNode = DhSectionPos.encode((byte) 2, 1151, 0); // width 4 blocks
long inputPos = DhSectionPos.encode((byte) 0, 4606, 0); // width 1 block
long parentNode = DhSectionPos.encodePos((byte) 2, 1151, 0); // width 4 blocks
long inputPos = DhSectionPos.encodePos((byte) 0, 4606, 0); // width 1 block
Assert.assertTrue(DhSectionPos.contains(parentNode, inputPos));
DhBlockPos2D parentCenter = DhSectionPos.getCenterBlockPos(parentNode);
@@ -191,20 +192,20 @@ public class DhSectionPosTest
// origin pos //
DhBlockPos originBlockPos = new DhBlockPos(0, 0, 0);
long originsectionPos = DhSectionPos.encode(originBlockPos);
assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originsectionPos);
long originsectionPos = DhSectionPos.encodeLodPos(originBlockPos);
assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originsectionPos);
// offset pos //
long offsetSectionPos;
DhBlockPos offsetBlockPos = new DhBlockPos(1000, 0, 42000);
offsetSectionPos = DhSectionPos.encode(offsetBlockPos);
assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 15, 656), offsetSectionPos);
offsetSectionPos = DhSectionPos.encodeLodPos(offsetBlockPos);
assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 15, 656), offsetSectionPos);
offsetBlockPos = new DhBlockPos(-987654, 0, 46);
offsetSectionPos = DhSectionPos.encode(offsetBlockPos);
assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -15433, 0), offsetSectionPos);
offsetSectionPos = DhSectionPos.encodeLodPos(offsetBlockPos);
assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -15433, 0), offsetSectionPos);
}
@@ -214,19 +215,19 @@ public class DhSectionPosTest
// origin pos //
DhBlockPos2D originBlockPos = new DhBlockPos2D(0, 0);
long originSectionPos = DhSectionPos.encode(originBlockPos);
assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originSectionPos);
long originSectionPos = DhSectionPos.encodeLodPos(originBlockPos);
assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originSectionPos);
// offset pos //
DhBlockPos2D offsetBlockPos = new DhBlockPos2D(1000, 42000);
long offsetSectionPos = DhSectionPos.encode(offsetBlockPos);
assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 15, 656), offsetSectionPos);
long offsetSectionPos = DhSectionPos.encodeLodPos(offsetBlockPos);
assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 15, 656), offsetSectionPos);
offsetBlockPos = new DhBlockPos2D(-987654, 46);
offsetSectionPos = DhSectionPos.encode(offsetBlockPos);
assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -15433, 0), offsetSectionPos);
offsetSectionPos = DhSectionPos.encodeLodPos(offsetBlockPos);
assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -15433, 0), offsetSectionPos);
}
@@ -236,19 +237,45 @@ public class DhSectionPosTest
// origin pos //
DhChunkPos originChunkPos = new DhChunkPos(0,0);
long originSectionPos = DhSectionPos.encode(originChunkPos);
assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, 0, 0), originSectionPos);
long originSectionPos = DhSectionPos.encodeLodPos(originChunkPos);
assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, 0, 0), originSectionPos);
// offset pos //
DhChunkPos offsetChunkPos = new DhChunkPos(1000, 42000);
long offsetSectionPos = DhSectionPos.encode(offsetChunkPos);
assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, 15, 656), offsetSectionPos);
long offsetSectionPos = DhSectionPos.encodeLodPos(offsetChunkPos);
assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, 15, 656), offsetSectionPos);
offsetChunkPos = new DhChunkPos(-987654, 46);
offsetSectionPos = DhSectionPos.encode(offsetChunkPos);
assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, -15433, 0), offsetSectionPos);
offsetSectionPos = DhSectionPos.encodeLodPos(offsetChunkPos);
assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, -15433, 0), offsetSectionPos);
}
@Test
public void createFromChunkPos_test()
{
// origin pos //
DhChunkPos originChunkPos = new DhChunkPos(0,0);
long originSectionPos = DhSectionPos.encodePos(originChunkPos);
assertSectionPosEqual(DhSectionPos.encodePos(LodUtil.CHUNK_DETAIL_LEVEL, 0, 0), originSectionPos);
// offset pos //
DhChunkPos offsetChunkPos = new DhChunkPos(1, 1);
long offsetSectionPos = DhSectionPos.encodePos(offsetChunkPos);
assertSectionPosEqual(DhSectionPos.encodePos(LodUtil.CHUNK_DETAIL_LEVEL, 1, 1), offsetSectionPos);
offsetChunkPos = new DhChunkPos(2, 2);
offsetSectionPos = DhSectionPos.encodePos(offsetChunkPos);
assertSectionPosEqual(DhSectionPos.encodePos(LodUtil.CHUNK_DETAIL_LEVEL, 2, 2), offsetSectionPos);
offsetChunkPos = new DhChunkPos(-3, -2);
offsetSectionPos = DhSectionPos.encodePos(offsetChunkPos);
assertSectionPosEqual(DhSectionPos.encodePos(LodUtil.CHUNK_DETAIL_LEVEL, -3, -2), offsetSectionPos);
}
@@ -257,38 +284,38 @@ public class DhSectionPosTest
{
// origin pos //
long originSectionPos = DhSectionPos.encode((byte) 0,0,0);
long originSectionPos = DhSectionPos.encodePos((byte) 0,0,0);
originSectionPos = DhSectionPos.convertToDetailLevel(originSectionPos, (byte) 1);
assertSectionPosEqual(DhSectionPos.encode((byte) 1, 0, 0), originSectionPos);
assertSectionPosEqual(DhSectionPos.encodePos((byte) 1, 0, 0), originSectionPos);
originSectionPos = DhSectionPos.convertToDetailLevel(originSectionPos, DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL);
assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originSectionPos);
assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originSectionPos);
originSectionPos = DhSectionPos.convertToDetailLevel(originSectionPos, DhSectionPos.SECTION_REGION_DETAIL_LEVEL);
assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_REGION_DETAIL_LEVEL, 0, 0), originSectionPos);
assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_REGION_DETAIL_LEVEL, 0, 0), originSectionPos);
// offset pos //
long offsetSectionPos = DhSectionPos.encode((byte) 0,-10000,5000);
long offsetSectionPos = DhSectionPos.encodePos((byte) 0,-10000,5000);
offsetSectionPos = DhSectionPos.convertToDetailLevel(offsetSectionPos, (byte) 1);
assertSectionPosEqual(DhSectionPos.encode((byte) 1, -5000, 2500), offsetSectionPos);
assertSectionPosEqual(DhSectionPos.encodePos((byte) 1, -5000, 2500), offsetSectionPos);
offsetSectionPos = DhSectionPos.convertToDetailLevel(offsetSectionPos, DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL);
assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -157, 78), offsetSectionPos);
assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -157, 78), offsetSectionPos);
offsetSectionPos = DhSectionPos.convertToDetailLevel(offsetSectionPos, DhSectionPos.SECTION_REGION_DETAIL_LEVEL);
assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_REGION_DETAIL_LEVEL, -1, 0), offsetSectionPos);
assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_REGION_DETAIL_LEVEL, -1, 0), offsetSectionPos);
}
@Test
public void getOffsetWidth()
{
long originSectionPos = DhSectionPos.encode((byte) 0,0,0);
long sectionPos = DhSectionPos.encode((byte) 0,-10000,5000);
long originSectionPos = DhSectionPos.encodePos((byte) 0,0,0);
long sectionPos = DhSectionPos.encodePos((byte) 0,-10000,5000);
@@ -332,8 +359,8 @@ public class DhSectionPosTest
@Test
public void getBlockWidth()
{
long originSectionPos = DhSectionPos.encode((byte) 0,0,0);
long sectionPos = DhSectionPos.encode((byte) 0,-10000,5000);
long originSectionPos = DhSectionPos.encodePos((byte) 0,0,0);
long sectionPos = DhSectionPos.encodePos((byte) 0,-10000,5000);
assertSectionPosEqual(1, DhSectionPos.getBlockWidth(originSectionPos));
@@ -359,8 +386,8 @@ public class DhSectionPosTest
@Test
public void getCenterBlockPosOrigin()
{
long originSectionPos = DhSectionPos.encode((byte) 0,0,0);
long sectionPos = DhSectionPos.encode((byte) 0,-10000,5000);
long originSectionPos = DhSectionPos.encodePos((byte) 0,0,0);
long sectionPos = DhSectionPos.encodePos((byte) 0,-10000,5000);
@@ -406,28 +433,28 @@ public class DhSectionPosTest
long pos;
// origin block detail
pos = DhSectionPos.encode((byte) 0,0,0);
pos = DhSectionPos.encodePos((byte) 0,0,0);
Assert.assertEquals(0, DhSectionPos.getMinCornerBlockX(pos));
Assert.assertEquals(0, DhSectionPos.getMinCornerBlockZ(pos));
// offset block detail
pos = DhSectionPos.encode((byte) 0,2,3);
pos = DhSectionPos.encodePos((byte) 0,2,3);
Assert.assertEquals(2 * DhSectionPos.getBlockWidth(pos), DhSectionPos.getMinCornerBlockX(pos));
Assert.assertEquals(3 * DhSectionPos.getBlockWidth(pos), DhSectionPos.getMinCornerBlockZ(pos));
// negative offset block detail
pos = DhSectionPos.encode((byte) 0,-1,-2);
pos = DhSectionPos.encodePos((byte) 0,-1,-2);
Assert.assertEquals(-1 * DhSectionPos.getBlockWidth(pos), DhSectionPos.getMinCornerBlockX(pos));
Assert.assertEquals(-2 * DhSectionPos.getBlockWidth(pos), DhSectionPos.getMinCornerBlockZ(pos));
// origin chunk detail
pos = DhSectionPos.encode(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL,0,0);
pos = DhSectionPos.encodePos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL,0,0);
Assert.assertEquals(0, DhSectionPos.getMinCornerBlockX(pos));
Assert.assertEquals(0, DhSectionPos.getMinCornerBlockZ(pos));
// offset chunk detail
pos = DhSectionPos.encode(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL,2,3);
pos = DhSectionPos.encodePos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL,2,3);
Assert.assertEquals(2 * DhSectionPos.getBlockWidth(pos), DhSectionPos.getMinCornerBlockX(pos));
Assert.assertEquals(3 * DhSectionPos.getBlockWidth(pos), DhSectionPos.getMinCornerBlockZ(pos));
@@ -437,13 +464,13 @@ public class DhSectionPosTest
@Test
public void getAdjacentPos()
{
long pos = DhSectionPos.encode((byte) 0, 0, 0);
long pos = DhSectionPos.encodePos((byte) 0, 0, 0);
assertSectionPosEqual(DhSectionPos.encode((byte) 0, 0, -1), DhSectionPos.getAdjacentPos(pos, EDhDirection.NORTH));
assertSectionPosEqual(DhSectionPos.encode((byte) 0, 0, 1), DhSectionPos.getAdjacentPos(pos, EDhDirection.SOUTH));
assertSectionPosEqual(DhSectionPos.encodePos((byte) 0, 0, -1), DhSectionPos.getAdjacentPos(pos, EDhDirection.NORTH));
assertSectionPosEqual(DhSectionPos.encodePos((byte) 0, 0, 1), DhSectionPos.getAdjacentPos(pos, EDhDirection.SOUTH));
assertSectionPosEqual(DhSectionPos.encode((byte) 0, 1, 0), DhSectionPos.getAdjacentPos(pos, EDhDirection.EAST));
assertSectionPosEqual(DhSectionPos.encode((byte) 0, -1, 0), DhSectionPos.getAdjacentPos(pos, EDhDirection.WEST));
assertSectionPosEqual(DhSectionPos.encodePos((byte) 0, 1, 0), DhSectionPos.getAdjacentPos(pos, EDhDirection.EAST));
assertSectionPosEqual(DhSectionPos.encodePos((byte) 0, -1, 0), DhSectionPos.getAdjacentPos(pos, EDhDirection.WEST));
// getting the adjacent position in the up and down position don't make sense
Assert.assertThrows(IllegalArgumentException.class, () -> { DhSectionPos.getAdjacentPos(pos, EDhDirection.UP); });
@@ -453,7 +480,7 @@ public class DhSectionPosTest
@Test
public void forEachChildIterator()
{
long pos = DhSectionPos.encode((byte) 1, 0, 0);
long pos = DhSectionPos.encodePos((byte) 1, 0, 0);
ArrayList<Long> childPosList = new ArrayList<>();
AtomicInteger childCount = new AtomicInteger(0);
@@ -463,10 +490,10 @@ public class DhSectionPosTest
childPosList.add(childPos);
});
Assert.assertTrue(childPosList.contains(DhSectionPos.encode((byte) 0, 0, 0)));
Assert.assertTrue(childPosList.contains(DhSectionPos.encode((byte) 0, 1, 0)));
Assert.assertTrue(childPosList.contains(DhSectionPos.encode((byte) 0, 0, 1)));
Assert.assertTrue(childPosList.contains(DhSectionPos.encode((byte) 0, 1, 1)));
Assert.assertTrue(childPosList.contains(DhSectionPos.encodePos((byte) 0, 0, 0)));
Assert.assertTrue(childPosList.contains(DhSectionPos.encodePos((byte) 0, 1, 0)));
Assert.assertTrue(childPosList.contains(DhSectionPos.encodePos((byte) 0, 0, 1)));
Assert.assertTrue(childPosList.contains(DhSectionPos.encodePos((byte) 0, 1, 1)));
}
+96 -96
View File
@@ -60,30 +60,30 @@ public class QuadTreeTest
// (pseudo) root node //
testSet(tree, DhSectionPos.encode((byte) 10, 0, 0), 0);
testSet(tree, DhSectionPos.encodePos((byte) 10, 0, 0), 0);
// first child (0,0) //
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);
testSet(tree, DhSectionPos.encodePos((byte) 9, 0, 0), 1);
testSet(tree, DhSectionPos.encodePos((byte) 9, 1, 0), 2);
testSet(tree, DhSectionPos.encodePos((byte) 9, 0, 1), 3);
testSet(tree, DhSectionPos.encodePos((byte) 9, 1, 1), 4);
// second child (0,0) (0,0) //
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);
testSet(tree, DhSectionPos.encodePos((byte) 8, 0, 0), 5);
testSet(tree, DhSectionPos.encodePos((byte) 8, 1, 0), 6);
testSet(tree, DhSectionPos.encodePos((byte) 8, 0, 1), 7);
testSet(tree, DhSectionPos.encodePos((byte) 8, 1, 1), 8);
// second child (0,0) (1,1) //
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);
testSet(tree, DhSectionPos.encodePos((byte) 8, 2, 2), 9);
testSet(tree, DhSectionPos.encodePos((byte) 8, 3, 2), 10);
testSet(tree, DhSectionPos.encodePos((byte) 8, 2, 3), 11);
testSet(tree, DhSectionPos.encodePos((byte) 8, 3, 3), 12);
// third child (0,0) (1,0) (0,0) //
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);
testSet(tree, DhSectionPos.encodePos((byte) 7, 5, 0), 9);
testSet(tree, DhSectionPos.encodePos((byte) 7, 6, 0), 10);
testSet(tree, DhSectionPos.encodePos((byte) 7, 5, 1), 11);
testSet(tree, DhSectionPos.encodePos((byte) 7, 6, 1), 12);
}
@@ -95,13 +95,13 @@ public class QuadTreeTest
// root node //
testSet(tree, DhSectionPos.encode((byte) 10, -1, -1), 0);
testSet(tree, DhSectionPos.encodePos((byte) 10, -1, -1), 0);
// first child (-1,-1) //
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);
testSet(tree, DhSectionPos.encodePos((byte) 9, -2, -1), 1);
testSet(tree, DhSectionPos.encodePos((byte) 9, -1, -1), 2);
testSet(tree, DhSectionPos.encodePos((byte) 9, -2, -2), 3);
testSet(tree, DhSectionPos.encodePos((byte) 9, -1, -2), 4);
// TODO
// // second child (-1,-1) (0,0) //
@@ -132,36 +132,36 @@ public class QuadTreeTest
// wrong detail level on purpose, if the detail level was 0 (block) this should work
long outOfBoundsPos = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2), 0);
long outOfBoundsPos = DhSectionPos.encodePos(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 = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) + 1, 0);
outOfBoundsPos = DhSectionPos.encodePos(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 = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2), 0);
outOfBoundsPos = DhSectionPos.encodePos(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 = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 1, 0);
outOfBoundsPos = DhSectionPos.encodePos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 1, 0);
testSet(tree, outOfBoundsPos, 0);
Assert.assertEquals("incorrect leaf node count", 1, tree.leafNodeCount());
outOfBoundsPos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 3, 0);
outOfBoundsPos = DhSectionPos.encodePos(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 = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 2, 0);
outOfBoundsPos = DhSectionPos.encodePos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 2, 0);
testSet(tree, outOfBoundsPos, 0);
Assert.assertEquals("incorrect leaf node count", 3, tree.leafNodeCount());
outOfBoundsPos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 4, 0);
outOfBoundsPos = DhSectionPos.encodePos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 4, 0);
testSet(tree, outOfBoundsPos, 0);
Assert.assertEquals("incorrect leaf node count", 4, tree.leafNodeCount());
@@ -174,15 +174,15 @@ public class QuadTreeTest
Assert.assertEquals("Test may need to be re-calculated for different max detail level.", 9, tree.treeMinDetailLevel);
long rootPos = DhSectionPos.encode((byte) 9, 0, -1);
long rootPos = DhSectionPos.encodePos((byte) 9, 0, -1);
testSet(tree, rootPos, 1);
// pos is in tree, but out of range
long midPos = DhSectionPos.encode((byte) 8, 0, -1);
long midPos = DhSectionPos.encodePos((byte) 8, 0, -1);
testSet(tree, midPos, 2, IndexOutOfBoundsException.class);
// pos is in tree, but out of range
long leafPos = DhSectionPos.encode((byte) 7, 0, -2);
long leafPos = DhSectionPos.encodePos((byte) 7, 0, -2);
testSet(tree, leafPos, 3, IndexOutOfBoundsException.class);
}
@@ -198,13 +198,13 @@ public class QuadTreeTest
// (pseudo) root nodes //
testSet(tree, DhSectionPos.encode((byte) 10, 0, 0), 1);
testSet(tree, DhSectionPos.encodePos((byte) 10, 0, 0), 1);
// first child (0,0) //
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);
long nw = DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0);
long ne = DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 1, 0);
long sw = DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 1);
long se = DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 1, 1);
testSet(tree, nw, 2);
testSet(tree, ne, 3);
@@ -260,12 +260,12 @@ public class QuadTreeTest
Assert.assertEquals("Tree center incorrect", DhBlockPos2D.ZERO, tree.getCenterBlockPos());
// on the negative X edge
long edgePos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, -treeParams.getWidthInBlocks() / 2, 0);
long edgePos = DhSectionPos.encodePos(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
long adjacentEdgePos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (-treeParams.getWidthInBlocks() / 2) + pseudoRootNodeWidthInBlocks, 0);
long adjacentEdgePos = DhSectionPos.encodePos(LodUtil.BLOCK_DETAIL_LEVEL, (-treeParams.getWidthInBlocks() / 2) + pseudoRootNodeWidthInBlocks, 0);
testSet(tree, adjacentEdgePos, 2);
Assert.assertEquals("incorrect leaf node count", 2, tree.leafNodeCount());
@@ -285,14 +285,14 @@ public class QuadTreeTest
// (pseudo) root nodes //
testSet(tree, DhSectionPos.encode((byte) 10, 0, 0), 1);
testSet(tree, DhSectionPos.encode((byte) 10, 1, 0), 2);
testSet(tree, DhSectionPos.encodePos((byte) 10, 0, 0), 1);
testSet(tree, DhSectionPos.encodePos((byte) 10, 1, 0), 2);
// first child (0,0) //
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);
testSet(tree, DhSectionPos.encodePos((byte) 9, 0, 0), 3);
testSet(tree, DhSectionPos.encodePos((byte) 9, 1, 0), 4);
testSet(tree, DhSectionPos.encodePos((byte) 9, 0, 1), 5);
testSet(tree, DhSectionPos.encodePos((byte) 9, 1, 1), 6);
@@ -332,19 +332,19 @@ public class QuadTreeTest
@Test
public void NewQuadTreeIterationTest()
{
QuadNode<Integer> rootNode = new QuadNode<>(DhSectionPos.encode((byte) 10, 0, 0), LodUtil.BLOCK_DETAIL_LEVEL);
QuadNode<Integer> rootNode = new QuadNode<>(DhSectionPos.encodePos((byte) 10, 0, 0), LodUtil.BLOCK_DETAIL_LEVEL);
rootNode.setValue(DhSectionPos.encode((byte) 10, 0, 0), 0);
rootNode.setValue(DhSectionPos.encodePos((byte) 10, 0, 0), 0);
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(DhSectionPos.encodePos((byte) 9, 0, 0), 1);
rootNode.setValue(DhSectionPos.encodePos((byte) 9, 1, 0), 1);
rootNode.setValue(DhSectionPos.encodePos((byte) 9, 0, 1), 1);
rootNode.setValue(DhSectionPos.encodePos((byte) 9, 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);
rootNode.setValue(DhSectionPos.encodePos((byte) 8, 0, 0), 2);
rootNode.setValue(DhSectionPos.encodePos((byte) 8, 1, 0), 2);
rootNode.setValue(DhSectionPos.encodePos((byte) 8, 0, 1), 2);
rootNode.setValue(DhSectionPos.encodePos((byte) 8, 1, 1), null);
@@ -411,7 +411,7 @@ public class QuadTreeTest
{
AbstractTestTreeParams treeParams = new TinyTestTree();
final QuadTree<Integer> tree = new QuadTree<>(treeParams.getWidthInBlocks(), treeParams.getPositiveEdgeCenterPos(), LodUtil.BLOCK_DETAIL_LEVEL);
testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 0, 0), 0);
testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 0, 0), 0);
// confirm the root node were added
int rootNodeCount = 0;
@@ -499,10 +499,10 @@ public class QuadTreeTest
Assert.assertEquals("incorrect tree width", treeParams.getWidthInBlocks(), tree.diameterInBlocks());
testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 0, 0), 0);
testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 0, 0), 0);
testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, -1, -1), -1, IndexOutOfBoundsException.class);
testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 1, 1), -1, IndexOutOfBoundsException.class);
testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, -1, -1), -1, IndexOutOfBoundsException.class);
testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 1, 1), -1, IndexOutOfBoundsException.class);
int rootNodeCount = 0;
LongIterator rootNodeIterator = tree.rootNodePosIterator();
@@ -529,18 +529,18 @@ public class QuadTreeTest
// 2x2 valid positions (overlap the tree's width)
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);
testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 0, 0), 0);
testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, -1, 0), 0);
testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 0, -1), 0);
testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, -1, -1), 0);
// invalid positions
testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, -1, 1), -1, IndexOutOfBoundsException.class);
testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 0, 1), -1, IndexOutOfBoundsException.class);
testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, -1, 1), -1, IndexOutOfBoundsException.class);
testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 0, 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);
testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 1, 0), -1, IndexOutOfBoundsException.class);
testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 1, 1), -1, IndexOutOfBoundsException.class);
testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 1, -1), -1, IndexOutOfBoundsException.class);
int rootNodeCount = 0;
@@ -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, 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);
testSet(tree, DhSectionPos.encodePos((byte) 10, 0, 0), 1);
testSet(tree, DhSectionPos.encodePos((byte) 9, 0, 0), 2);
testSet(tree, DhSectionPos.encodePos((byte) 8, 0, 0), 3);
// detail level too low
testSet(tree, DhSectionPos.encode((byte) 7, 0, 0), -1, IndexOutOfBoundsException.class);
testSet(tree, DhSectionPos.encode((byte) 6, 0, 0), -1, IndexOutOfBoundsException.class);
testSet(tree, DhSectionPos.encodePos((byte) 7, 0, 0), -1, IndexOutOfBoundsException.class);
testSet(tree, DhSectionPos.encodePos((byte) 6, 0, 0), -1, IndexOutOfBoundsException.class);
// detail level too high
testSet(tree, DhSectionPos.encode((byte) 11, 0, 0), -1, IndexOutOfBoundsException.class);
testSet(tree, DhSectionPos.encode((byte) 12, 0, 0), -1, IndexOutOfBoundsException.class);
testSet(tree, DhSectionPos.encodePos((byte) 11, 0, 0), -1, IndexOutOfBoundsException.class);
testSet(tree, DhSectionPos.encodePos((byte) 12, 0, 0), -1, IndexOutOfBoundsException.class);
}
@@ -587,7 +587,7 @@ 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, DhSectionPos.encode((byte) 10, 0, 0), 1);
testSet(tree, DhSectionPos.encodePos((byte) 10, 0, 0), 1);
@@ -678,7 +678,7 @@ public class QuadTreeTest
@Test
public void quadNodeChildPositionIndexTest()
{
QuadNode<Integer> rootNode = new QuadNode<>(DhSectionPos.encode((byte) 10, 0, 0), (byte) 0);
QuadNode<Integer> rootNode = new QuadNode<>(DhSectionPos.encodePos((byte) 10, 0, 0), (byte) 0);
LongIterator directChildPosIterator = rootNode.getChildPosIterator();
while (directChildPosIterator.hasNext())
{
@@ -708,7 +708,7 @@ public class QuadTreeTest
// center root node
long centerNodePos = DhSectionPos.encode((byte) 1, 0, 0);
long centerNodePos = DhSectionPos.encodePos((byte) 1, 0, 0);
// create node
tree.setValue(centerNodePos, 0);
@@ -727,7 +727,7 @@ public class QuadTreeTest
// edge root node
long offsetNodePos = DhSectionPos.encode((byte) 1, -17, -16);
long offsetNodePos = DhSectionPos.encodePos((byte) 1, -17, -16);
// create node
tree.setValue(offsetNodePos, 0);
@@ -772,7 +772,7 @@ public class QuadTreeTest
//
testSet(tree, DhSectionPos.encode((byte) 0, 0, 0), 1);
testSet(tree, DhSectionPos.encodePos((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<>(DhSectionPos.encode((byte) 10, 0, 0), LodUtil.BLOCK_DETAIL_LEVEL);
QuadNode<Integer> rootNode = new QuadNode<>(DhSectionPos.encodePos((byte) 10, 0, 0), LodUtil.BLOCK_DETAIL_LEVEL);
rootNode.setValue(DhSectionPos.encode((byte) 10, 0, 0), 0);
rootNode.setValue(DhSectionPos.encodePos((byte) 10, 0, 0), 0);
long midNodePos = DhSectionPos.encode((byte) 9, 0, 0);
long midNodePos = DhSectionPos.encodePos((byte) 9, 0, 0);
//rootNode.setValue(midNodePos, null); // holds detail 8
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(DhSectionPos.encodePos((byte) 9, 1, 0), 1);
rootNode.setValue(DhSectionPos.encodePos((byte) 9, 0, 1), 1);
rootNode.setValue(DhSectionPos.encodePos((byte) 9, 1, 1), 1);
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);
rootNode.setValue(DhSectionPos.encodePos((byte) 8, 0, 0), 2);
rootNode.setValue(DhSectionPos.encodePos((byte) 8, 1, 0), 2);
rootNode.setValue(DhSectionPos.encodePos((byte) 8, 0, 1), 2);
rootNode.setValue(DhSectionPos.encodePos((byte) 8, 1, 1), 2);
@@ -810,12 +810,12 @@ public class QuadTreeTest
// test removing nodes //
// remove two leaf nodes from the root
long leafPos = DhSectionPos.encode((byte) 9, 1, 1);
long leafPos = DhSectionPos.encodePos((byte) 9, 1, 1);
rootNode.setValue(leafPos, null);
Assert.assertEquals(3, rootNode.getNonNullChildCount());
Assert.assertNull("Node wasn't deleted", rootNode.getNode(leafPos));
leafPos = DhSectionPos.encode((byte) 9, 0, 1);
leafPos = DhSectionPos.encodePos((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(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);
rootNode.setValue(DhSectionPos.encodePos((byte) 8, 0, 0), null);
rootNode.setValue(DhSectionPos.encodePos((byte) 8, 0, 1), null);
rootNode.setValue(DhSectionPos.encodePos((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(DhSectionPos.encode((byte) 8, 1, 1), null);
rootNode.setValue(DhSectionPos.encodePos((byte) 8, 1, 1), null);
Assert.assertNull("Mid node not deleted.", rootNode.getNode(midNodePos));
Assert.assertEquals(3, rootNode.getNonNullChildCount());