diff --git a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java
new file mode 100644
index 000000000..0c269ae4b
--- /dev/null
+++ b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java
@@ -0,0 +1,411 @@
+/*
+ * This file is part of the Distant Horizons mod
+ * licensed under the GNU LGPL v3 License.
+ *
+ * Copyright (C) 2020-2023 James Seibel
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.seibel.distanthorizons.core.pos;
+
+import com.seibel.distanthorizons.core.enums.EDhDirection;
+import com.seibel.distanthorizons.core.util.LodUtil;
+import com.seibel.distanthorizons.coreapi.util.BitShiftUtil;
+
+/**
+ * The position object used to define LOD objects in the quad trees.
+ *
+ * A section contains 64 x 64 LOD columns at a given quality.
+ * The Section detail level is different from the LOD detail level.
+ * For the specifics of how they compare can be viewed in the constants {@link #SECTION_BLOCK_DETAIL_LEVEL},
+ * {@link #SECTION_CHUNK_DETAIL_LEVEL}, and {@link #SECTION_REGION_DETAIL_LEVEL}).
+ *
+ * Why does the smallest render section represent 2x2 MC chunks (section detail level 6)?
+ * A section defines what unit the quad tree works in, because of that we don't want that unit to be too big or too small.
+ * Too small, and we'll have 1,000s of sections running around, all needing individual files and render buffers.
+ * Too big, and the LOD dropoff will be very noticeable.
+ * With those thoughts in mind we decided on a smallest section size of 32 data points square (IE 2x2 chunks).
+ *
+ * @author Leetom
+ */
+public class DhSectionPos
+{
+ /**
+ * The lowest detail level a Section position can hold.
+ * This section DetailLevel holds 64 x 64 Block level (detail level 0) LODs.
+ */
+ public static final byte SECTION_MINIMUM_DETAIL_LEVEL = 6;
+
+ public static final byte SECTION_BLOCK_DETAIL_LEVEL = SECTION_MINIMUM_DETAIL_LEVEL + LodUtil.BLOCK_DETAIL_LEVEL;
+ public static final byte SECTION_CHUNK_DETAIL_LEVEL = SECTION_MINIMUM_DETAIL_LEVEL + LodUtil.CHUNK_DETAIL_LEVEL;
+ public static final byte SECTION_REGION_DETAIL_LEVEL = SECTION_MINIMUM_DETAIL_LEVEL + LodUtil.REGION_DETAIL_LEVEL;
+
+
+
+ public static final int DETAIL_LEVEL_WIDTH = 8;
+ public static final int X_POS_WIDTH = 28;
+ public static final int Z_POS_WIDTH = 28;
+ public static final int X_POS_MISSING_WIDTH = 32 - 28;
+ public static final int Z_POS_MISSING_WIDTH = 32 - 28;
+
+
+ public static final int DETAIL_LEVEL_OFFSET = 0;
+ public static final int POS_X_OFFSET = DETAIL_LEVEL_OFFSET + DETAIL_LEVEL_WIDTH;
+ /** indicates the Y position where the LOD starts relative to the level's minimum height */
+ public static final int POS_Z_OFFSET = POS_X_OFFSET + X_POS_WIDTH;
+
+ public static final long DETAIL_LEVEL_MASK = Byte.MAX_VALUE;
+ public static final int POS_X_MASK = (int) Math.pow(2, X_POS_WIDTH) - 1;
+ public static final int POS_Z_MASK = (int) Math.pow(2, Z_POS_WIDTH) - 1;
+
+
+
+ //==============//
+ // constructors //
+ //==============//
+
+ /**
+ * This class just holds utility methods for handling a packed
+ * {@link DhSectionPos} and shouldn't be constructed.
+ *
+ * Use one of the {@link DhSectionPos#encode(byte, int, int)} methods instead
+ */
+ private DhSectionPos() { }
+
+
+
+ /**
+ * Note:
+ * 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)
+ {
+ long data = 0;
+ data |= detailLevel & DETAIL_LEVEL_MASK;
+ data |= (long) (x & POS_X_MASK) << POS_X_OFFSET;
+ data |= (long) (z & POS_Z_MASK) << POS_Z_OFFSET;
+ 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)
+ {
+ long pos = encode(LodUtil.BLOCK_DETAIL_LEVEL, blockX, blockZ);
+ pos = convertToDetailLevel(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, pos);
+ return pos;
+ }
+
+ public static long encode(DhChunkPos pos) { return encodeChunkPos(pos.x, pos.z); }
+ public static long encodeChunkPos(int chunkX, int chunkZ)
+ {
+ long pos = encode(LodUtil.CHUNK_DETAIL_LEVEL, chunkX, chunkZ);
+ pos = convertToDetailLevel(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, pos);
+ return pos;
+ }
+
+
+
+ //============//
+ // converters //
+ //============//
+
+ /** uses the absolute detail level aka detail levels like {@link LodUtil#CHUNK_DETAIL_LEVEL} instead of the dhSectionPos detailLevels. */
+ public static long convertToDetailLevel(byte newDetailLevel, long pos)
+ {
+ byte detailLevel = getDetailLevel(pos);
+ int x = getX(pos);
+ int z = getZ(pos);
+
+ // logic originally taken from DhLodPos
+ if (newDetailLevel >= detailLevel)
+ {
+ x = Math.floorDiv(x, BitShiftUtil.powerOfTwo(newDetailLevel - detailLevel));
+ z = Math.floorDiv(z, BitShiftUtil.powerOfTwo(newDetailLevel - detailLevel));
+ }
+ else
+ {
+ x = x * BitShiftUtil.powerOfTwo(detailLevel - newDetailLevel);
+ z = z * BitShiftUtil.powerOfTwo(detailLevel - newDetailLevel);
+ }
+
+ return encode(newDetailLevel, x, z);
+ }
+
+
+
+ //==================//
+ // property getters //
+ //==================//
+
+ public static byte getDetailLevel(long pos) { return (byte) ((pos >> DETAIL_LEVEL_OFFSET) & DETAIL_LEVEL_MASK); }
+ public static int getX(long pos)
+ {
+ // unpack the position
+ int x = (int) ((pos >> POS_X_OFFSET) & POS_X_MASK);
+ // add the missing 2's compliment most-significant bits (if not done negative numbers will parse incorrectly)
+ x = (x << X_POS_MISSING_WIDTH) >> X_POS_MISSING_WIDTH;
+ return x;
+ }
+ public static int getZ(long pos)
+ {
+ int Z = (int) ((pos >> POS_Z_OFFSET) & POS_Z_MASK);
+ Z = (Z << Z_POS_MISSING_WIDTH) >> Z_POS_MISSING_WIDTH;
+ return Z;
+ }
+
+
+
+ //=========//
+ // getters //
+ //=========//
+
+ /** @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;
+ 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;
+ return DhSectionPos.getCenterBlockPosZ(pos) - halfBlockWidth;
+ }
+
+ /**
+ * A detail level of X lower than this section's detail level will return:
+ * 0 -> 1
+ * 1 -> 2
+ * 2 -> 4
+ * 3 -> 8
+ * etc.
+ *
+ * @return how many {@link DhSectionPos}'s at the given detail level it would take to span the width of this section.
+ */
+ public static int getWidthCountForLowerDetailedSection(byte returnDetailLevel, long pos)
+ {
+ byte detailLevel = getDetailLevel(pos);
+
+ LodUtil.assertTrue(returnDetailLevel <= detailLevel, "returnDetailLevel must be less than sectionDetail");
+ byte offset = (byte) (detailLevel - returnDetailLevel);
+ return BitShiftUtil.powerOfTwo(offset);
+ }
+
+ /** @return how wide this section is in blocks */
+ public static int getBlockWidth(long pos) { return BitShiftUtil.powerOfTwo(getDetailLevel(pos)); }
+
+
+ public static DhBlockPos2D getCenterBlockPos(long pos) { return new DhBlockPos2D(getCenterBlockPosX(pos), getCenterBlockPosZ(pos)); }
+
+ public static int getCenterBlockPosX(long pos) { return getCenterBlockPosXOrZ(true, pos); }
+ public static int getCenterBlockPosZ(long pos) { return getCenterBlockPosXOrZ(false, pos); }
+ private static int getCenterBlockPosXOrZ(boolean returnX, long pos)
+ {
+ byte detailLevel = getDetailLevel(pos);
+ int x = getX(pos);
+ int z = getZ(pos);
+
+
+ int centerBlockPos = returnX ? x : z;
+
+ if (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 (detailLevel != 1)
+ {
+ positionOffset = BitShiftUtil.powerOfTwo(detailLevel - 1);
+ }
+
+ return (centerBlockPos * BitShiftUtil.powerOfTwo(detailLevel)) + positionOffset;
+ }
+
+ public static int getManhattanBlockDistance(DhBlockPos2D blockPos, long pos)
+ {
+ return Math.abs(getCenterBlockPosX(pos) - blockPos.x)
+ + Math.abs(getCenterBlockPosZ(pos) - blockPos.z);
+ }
+
+
+
+ //==================//
+ // parent child pos //
+ //==================//
+
+ /**
+ * Returns a position 1 detail level lower.
+ *
+ * Relative child positions returned for each index:
+ * 0 = (0,0) - North West
+ * 1 = (1,0) - South West
+ * 2 = (0,1) - North East
+ * 3 = (1,1) - South East
+ *
+ * @param child0to3 must be an int between 0 and 3
+ */
+ public static long getChildByIndex(int child0to3, long pos) throws IllegalArgumentException, IllegalStateException
+ {
+ byte detailLevel = getDetailLevel(pos);
+ int x = getX(pos);
+ int z = getZ(pos);
+
+ if (child0to3 < 0 || child0to3 > 3)
+ {
+ throw new IllegalArgumentException("child0to3 must be between 0 and 3");
+ }
+ if (detailLevel <= 0)
+ {
+ throw new IllegalStateException("section detail must be greater than 0");
+ }
+
+ return DhSectionPos.encode((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 getAdjacentPos(EDhDirection dir, long pos) throws IllegalArgumentException
+ {
+ if (dir == EDhDirection.UP || dir == EDhDirection.DOWN)
+ {
+ throw new IllegalArgumentException("getAdjacentPos can't be UP or DOWN, direction given: ["+dir.name()+"].");
+ }
+
+ return DhSectionPos.encode(getDetailLevel(pos),
+ getX(pos) + dir.getNormal().x,
+ getZ(pos) + dir.getNormal().z);
+ }
+
+ //public DhLodPos getSectionBBoxPos() { return new DhLodPos(this.detailLevel, this.x, this.z); }
+
+
+
+ //=============//
+ // comparisons //
+ //=============//
+
+ public static boolean contains(long aPos, long bPos)
+ {
+ int aMinX = getMinCornerBlockX(aPos);
+ int aMinZ = getMinCornerBlockZ(aPos);
+
+ int bMinX = getMinCornerBlockX(bPos);
+ int bMinZ = getMinCornerBlockZ(bPos);
+
+ int aBlockWidth = getBlockWidth(aPos) - 1; // minus 1 to account for zero based positional indexing
+ int aMaxX = aMinX + aBlockWidth;
+ int aMaxZ = aMinZ + aBlockWidth;
+
+ return aMinX <= bMinX && bMinX <= aMaxX &&
+ aMinZ <= bMinZ && bMinZ <= aMaxZ;
+ }
+
+
+
+ //===========//
+ // iterators //
+ //===========//
+
+ /** Applies the given consumer to all 4 of this position's children. */
+ public static void forEachChild(IPrimitiveLongConsumer callback, long pos) throws IllegalArgumentException, IllegalStateException
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ callback.accept(getChildByIndex(i, pos));
+ }
+ }
+
+ /** Applies the given consumer to all children of the position at the given section detail level. */
+ public static void forEachChildDownToDetailLevel(byte minSectionDetailLevel, ICancelablePrimitiveLongConsumer callback, long pos) throws IllegalArgumentException, IllegalStateException
+ {
+ boolean stop = callback.accept(pos);
+ if (stop || minSectionDetailLevel == getDetailLevel(pos))
+ {
+ return;
+ }
+
+ for (int i = 0; i < 4; i++)
+ {
+ forEachChildDownToDetailLevel(minSectionDetailLevel, callback, getChildByIndex(i, pos));
+ }
+ }
+
+ /** 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
+ {
+ if (sectionDetailLevel == getDetailLevel(pos))
+ {
+ callback.accept(pos);
+ return;
+ }
+
+ for (int i = 0; i < 4; i++)
+ {
+ forEachChildAtDetailLevel(sectionDetailLevel, callback, getChildByIndex(i, pos));
+ }
+ }
+
+ /** 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)
+ {
+ callback.accept(pos);
+ if (maxSectionDetailLevel == getDetailLevel(pos))
+ {
+ return;
+ }
+
+ forEachPosUpToDetailLevel(maxSectionDetailLevel, callback, getParentPos(pos));
+ }
+
+
+
+ //==============//
+ // Base methods //
+ //==============//
+
+ public static String toString(long pos) { return getDetailLevel(pos) + "*" + getX(pos) + "," + getZ(pos); }
+
+
+
+ //================//
+ // 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
+ {
+ /** @return true if this method should cancel further consumers. */
+ boolean accept(long value);
+ }
+
+}
diff --git a/core/src/test/java/tests/DhSectionPosTest.java b/core/src/test/java/tests/DhSectionPosTest.java
index 23bd48819..89f459b7b 100644
--- a/core/src/test/java/tests/DhSectionPosTest.java
+++ b/core/src/test/java/tests/DhSectionPosTest.java
@@ -19,99 +19,134 @@
package tests;
-import com.seibel.distanthorizons.core.pos.*;
+import com.seibel.distanthorizons.core.enums.EDhDirection;
+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 org.junit.Assert;
import org.junit.Test;
+import java.util.ArrayList;
+import java.util.concurrent.atomic.AtomicInteger;
+
public class DhSectionPosTest
{
+
@Test
- public void ContainsPosTest()
+ public void basicEncodeDecodeTest()
{
- OldDhSectionPos root = new OldDhSectionPos((byte) 10, 0, 0);
- OldDhSectionPos child = new OldDhSectionPos((byte) 9, 1, 1);
+ long pos;
- Assert.assertTrue("section pos contains fail", root.contains(child));
- Assert.assertFalse("section pos contains fail", child.contains(root));
+ // zero pos
+ pos = DhSectionPos.encode((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);
+ 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);
+ assertSectionPosEqual(2, DhSectionPos.getDetailLevel(pos));
+ assertSectionPosEqual(-1, DhSectionPos.getX(pos));
+ assertSectionPosEqual(-4, DhSectionPos.getZ(pos));
+
+ }
+
+
+
+ @Test
+ public void containsPosTest()
+ {
+ long root = DhSectionPos.encode((byte) 10, 0, 0);
+ long child = DhSectionPos.encode((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 = new OldDhSectionPos((byte) 10, 1, 0);
+ root = DhSectionPos.encode((byte) 10, 1, 0);
// out of bounds
- child = new OldDhSectionPos((byte) 9, 0, 0);
- Assert.assertFalse("position should be out of bounds", root.contains(child));
- child = new OldDhSectionPos((byte) 9, 1, 1);
- Assert.assertFalse("position should be out of bounds", root.contains(child));
+ child = DhSectionPos.encode((byte) 9, 0, 0);
+ Assert.assertFalse("position should be out of bounds", DhSectionPos.contains(root, child));
+ child = DhSectionPos.encode((byte) 9, 1, 1);
+ Assert.assertFalse("position should be out of bounds", DhSectionPos.contains(root, child));
// in bounds
- child = new OldDhSectionPos((byte) 9, 2, 0);
- Assert.assertTrue("position should be in bounds", root.contains(child));
- child = new OldDhSectionPos((byte) 9, 3, 1);
- Assert.assertTrue("position should be in bounds", root.contains(child));
+ child = DhSectionPos.encode((byte) 9, 2, 0);
+ Assert.assertTrue("position should be in bounds", DhSectionPos.contains(root, child));
+ child = DhSectionPos.encode((byte) 9, 3, 1);
+ Assert.assertTrue("position should be in bounds", DhSectionPos.contains(root, child));
// out of bounds
- child = new OldDhSectionPos((byte) 9, 2, 2);
- Assert.assertFalse("position should be out of bounds", root.contains(child));
- child = new OldDhSectionPos((byte) 9, 3, 3);
- Assert.assertFalse("position should be out of bounds", root.contains(child));
+ child = DhSectionPos.encode((byte) 9, 2, 2);
+ Assert.assertFalse("position should be out of bounds", DhSectionPos.contains(root, child));
+ child = DhSectionPos.encode((byte) 9, 3, 3);
+ Assert.assertFalse("position should be out of bounds", DhSectionPos.contains(root, child));
- child = new OldDhSectionPos((byte) 9, 4, 4);
- Assert.assertFalse("position should be out of bounds", root.contains(child));
- child = new OldDhSectionPos((byte) 9, 5, 5);
- Assert.assertFalse("position should be out of bounds", root.contains(child));
+ child = DhSectionPos.encode((byte) 9, 4, 4);
+ 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));
}
@Test
- public void ContainsAdjacentPosTest()
+ public void containsAdjacentPosTest()
{
// neither should contain the other, they are single blocks that are next to each other
- OldDhSectionPos left = new OldDhSectionPos((byte) 0, 4606, 0);
- OldDhSectionPos right = new OldDhSectionPos((byte) 0, 4607, 0);
- Assert.assertFalse(left.contains(right));
- Assert.assertFalse(right.contains(left));
-
-
+ long left = DhSectionPos.encode((byte) 0, 4606, 0);
+ long right = DhSectionPos.encode((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 = new OldDhSectionPos((byte) 9, 0, 0);
- right = new OldDhSectionPos((byte) 9, 1, 0);
- Assert.assertFalse(left.contains(right));
- Assert.assertFalse(right.contains(left));
-
+ left = DhSectionPos.encode((byte) 9, 0, 0);
+ right = DhSectionPos.encode((byte) 9, 1, 0);
+ Assert.assertFalse(DhSectionPos.contains(left, right));
+ Assert.assertFalse(DhSectionPos.contains(right, left));
+
}
@Test
- public void ParentPosTest()
+ public void parentPosTest()
{
- OldDhSectionPos leaf = new OldDhSectionPos((byte) 0, 0, 0);
- OldDhSectionPos convert = leaf.convertNewToDetailLevel((byte) 1);
- OldDhSectionPos parent = leaf.getParentPos();
- Assert.assertEquals("get parent at 0,0 fail", convert, parent);
-
-
- leaf = new OldDhSectionPos((byte) 0, 1, 1);
- convert = leaf.convertNewToDetailLevel((byte) 1);
- parent = leaf.getParentPos();
- Assert.assertEquals("get parent at 1,1 fail", convert, parent);
-
-
- leaf = new OldDhSectionPos((byte) 1, 2, 2);
- convert = leaf.convertNewToDetailLevel((byte) 2);
- parent = leaf.getParentPos();
- Assert.assertEquals("parent upscale fail", convert, parent);
- convert = leaf.convertNewToDetailLevel((byte) 0);
- OldDhSectionPos childIndex = leaf.getChildByIndex(0);
- Assert.assertEquals("child detail fail", convert, childIndex);
-
+ long leaf = DhSectionPos.encode((byte) 0, 0, 0);
+ long convert = DhSectionPos.convertToDetailLevel((byte) 1, leaf);
+ long parent = DhSectionPos.getParentPos(leaf);
+ assertSectionPosEqual("get parent at 0,0 fail", convert, parent);
+
+
+ leaf = DhSectionPos.encode((byte) 0, 1, 1);
+ convert = DhSectionPos.convertToDetailLevel((byte) 1, leaf);
+ parent = DhSectionPos.getParentPos(leaf);
+ assertSectionPosEqual("get parent at 1,1 fail", convert, parent);
+
+
+ leaf = DhSectionPos.encode((byte) 1, 2, 2);
+ convert = DhSectionPos.convertToDetailLevel((byte) 2, leaf);
+ parent = DhSectionPos.getParentPos(leaf);
+ assertSectionPosEqual("parent upscale fail", convert, parent);
+ convert = DhSectionPos.convertToDetailLevel((byte) 0, leaf);
+ long childIndex = DhSectionPos.getChildByIndex(0, leaf);
+ assertSectionPosEqual("child detail fail", convert, childIndex);
+
}
@Test
- public void ChildPosTest()
+ public void childPosTest()
{
- OldDhSectionPos node = new OldDhSectionPos((byte) 1, 2302, 0);
- OldDhSectionPos nw = node.getChildByIndex(0);
- OldDhSectionPos sw = node.getChildByIndex(1);
- OldDhSectionPos ne = node.getChildByIndex(2);
- OldDhSectionPos se = node.getChildByIndex(3);
+ long node = DhSectionPos.encode((byte) 1, 2302, 0);
+ long nw = DhSectionPos.getChildByIndex(0, node);
+ long sw = DhSectionPos.getChildByIndex(1, node);
+ long ne = DhSectionPos.getChildByIndex(2, node);
+ long se = DhSectionPos.getChildByIndex(3, node);
// confirm no children have the same values
Assert.assertNotEquals(nw, sw);
@@ -119,244 +154,340 @@ public class DhSectionPosTest
Assert.assertNotEquals(ne, se);
// confirm each child has the correct value
- Assert.assertEquals(nw, new OldDhSectionPos((byte) 0, 4604, 0));
- Assert.assertEquals(sw, new OldDhSectionPos((byte) 0, 4605, 0));
- Assert.assertEquals(ne, new OldDhSectionPos((byte) 0, 4604, 1));
- Assert.assertEquals(se, new OldDhSectionPos((byte) 0, 4605, 1));
+ 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));
}
@Test
- public void GetCenterTest()
+ public void getCenterBlockTest()
{
- OldDhSectionPos node = new OldDhSectionPos((byte) 1, 2303, 0);
- DhBlockPos2D centerBlockPos = node.getCenterBlockPos();
+ long node = DhSectionPos.encode((byte) 1, 2303, 0);
+ DhBlockPos2D centerBlockPos = DhSectionPos.getCenterBlockPos(node);
DhBlockPos2D expectedCenterNode = new DhBlockPos2D(4606, 0);
- Assert.assertEquals("", expectedCenterNode, centerBlockPos);
-
-
-
- node = new OldDhSectionPos((byte) 10, 0, 0); // 1024 blocks wide
- centerBlockPos = node.getCenterBlockPos();
+ 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);
+ Assert.assertEquals(expectedCenterNode, centerBlockPos);
}
@Test
- public void GetCenter2Test()
+ public void getCenterBlock2DTest()
{
- OldDhSectionPos parentNode = new OldDhSectionPos((byte) 2, 1151, 0); // width 4 blocks
- OldDhSectionPos inputPos = new OldDhSectionPos((byte) 0, 4606, 0); // width 1 block
- Assert.assertTrue(parentNode.contains(inputPos));
-
- DhBlockPos2D parentCenter = parentNode.getCenterBlockPos();
- DhBlockPos2D inputCenter = inputPos.getCenterBlockPos();
+ long parentNode = DhSectionPos.encode((byte) 2, 1151, 0); // width 4 blocks
+ long inputPos = DhSectionPos.encode((byte) 0, 4606, 0); // width 1 block
+ Assert.assertTrue(DhSectionPos.contains(parentNode, inputPos));
+
+ DhBlockPos2D parentCenter = DhSectionPos.getCenterBlockPos(parentNode);
+ DhBlockPos2D inputCenter = DhSectionPos.getCenterBlockPos(inputPos);
Assert.assertEquals(new DhBlockPos2D(4606, 2), parentCenter);
Assert.assertEquals(new DhBlockPos2D(4606, 0), inputCenter);
-
+
}
@Test
- public void CreateFromBlockPos()
+ public void createFromBlockPos()
{
// origin pos //
DhBlockPos originBlockPos = new DhBlockPos(0, 0, 0);
- OldDhSectionPos originSectionPos = new OldDhSectionPos(originBlockPos);
- Assert.assertEquals(new OldDhSectionPos(OldDhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originSectionPos);
+ long originsectionPos = DhSectionPos.encode(originBlockPos);
+ assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originsectionPos);
// offset pos //
+ long offsetSectionPos;
DhBlockPos offsetBlockPos = new DhBlockPos(1000, 0, 42000);
- OldDhSectionPos offsetSectionPos = new OldDhSectionPos(offsetBlockPos);
- Assert.assertEquals(new OldDhSectionPos(OldDhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 15, 656), offsetSectionPos);
+ offsetSectionPos = DhSectionPos.encode(offsetBlockPos);
+ assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 15, 656), offsetSectionPos);
offsetBlockPos = new DhBlockPos(-987654, 0, 46);
- offsetSectionPos = new OldDhSectionPos(offsetBlockPos);
- Assert.assertEquals(new OldDhSectionPos(OldDhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -15433, 0), offsetSectionPos);
+ offsetSectionPos = DhSectionPos.encode(offsetBlockPos);
+ assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -15433, 0), offsetSectionPos);
}
@Test
- public void CreateFromBlockPos2D()
+ public void createFromBlockPos2D()
{
// origin pos //
DhBlockPos2D originBlockPos = new DhBlockPos2D(0, 0);
- OldDhSectionPos originSectionPos = new OldDhSectionPos(originBlockPos);
- Assert.assertEquals(new OldDhSectionPos(OldDhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originSectionPos);
+ long originSectionPos = DhSectionPos.encode(originBlockPos);
+ assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originSectionPos);
// offset pos //
DhBlockPos2D offsetBlockPos = new DhBlockPos2D(1000, 42000);
- OldDhSectionPos offsetSectionPos = new OldDhSectionPos(offsetBlockPos);
- Assert.assertEquals(new OldDhSectionPos(OldDhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 15, 656), offsetSectionPos);
+ long offsetSectionPos = DhSectionPos.encode(offsetBlockPos);
+ assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 15, 656), offsetSectionPos);
offsetBlockPos = new DhBlockPos2D(-987654, 46);
- offsetSectionPos = new OldDhSectionPos(offsetBlockPos);
- Assert.assertEquals(new OldDhSectionPos(OldDhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -15433, 0), offsetSectionPos);
+ offsetSectionPos = DhSectionPos.encode(offsetBlockPos);
+ assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -15433, 0), offsetSectionPos);
}
@Test
- public void CreateFromChunkPos()
+ public void createFromChunkPos()
{
// origin pos //
DhChunkPos originChunkPos = new DhChunkPos(0,0);
- OldDhSectionPos originSectionPos = new OldDhSectionPos(originChunkPos);
- Assert.assertEquals(new OldDhSectionPos(OldDhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, 0, 0), originSectionPos);
+ long originSectionPos = DhSectionPos.encode(originChunkPos);
+ assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, 0, 0), originSectionPos);
// offset pos //
DhChunkPos offsetChunkPos = new DhChunkPos(1000, 42000);
- OldDhSectionPos offsetSectionPos = new OldDhSectionPos(offsetChunkPos);
- Assert.assertEquals(new OldDhSectionPos(OldDhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, 15, 656), offsetSectionPos);
+ long offsetSectionPos = DhSectionPos.encode(offsetChunkPos);
+ assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, 15, 656), offsetSectionPos);
offsetChunkPos = new DhChunkPos(-987654, 46);
- offsetSectionPos = new OldDhSectionPos(offsetChunkPos);
- Assert.assertEquals(new OldDhSectionPos(OldDhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, -15433, 0), offsetSectionPos);
+ offsetSectionPos = DhSectionPos.encode(offsetChunkPos);
+ assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, -15433, 0), offsetSectionPos);
}
@Test
- public void ConvertToDetailLevel()
+ public void convertToDetailLevel()
{
// origin pos //
- OldDhSectionPos originSectionPos = new OldDhSectionPos((byte) 0,0,0);
+ long originSectionPos = DhSectionPos.encode((byte) 0,0,0);
- originSectionPos = originSectionPos.convertNewToDetailLevel((byte) 1);
- Assert.assertEquals(new OldDhSectionPos((byte) 1, 0, 0), originSectionPos);
+ originSectionPos = DhSectionPos.convertToDetailLevel((byte) 1, originSectionPos);
+ assertSectionPosEqual(DhSectionPos.encode((byte) 1, 0, 0), originSectionPos);
- originSectionPos = originSectionPos.convertNewToDetailLevel(OldDhSectionPos.SECTION_BLOCK_DETAIL_LEVEL);
- Assert.assertEquals(new OldDhSectionPos(OldDhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originSectionPos);
+ originSectionPos = DhSectionPos.convertToDetailLevel(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, originSectionPos);
+ assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originSectionPos);
- originSectionPos = originSectionPos.convertNewToDetailLevel(OldDhSectionPos.SECTION_REGION_DETAIL_LEVEL);
- Assert.assertEquals(new OldDhSectionPos(OldDhSectionPos.SECTION_REGION_DETAIL_LEVEL, 0, 0), originSectionPos);
+ originSectionPos = DhSectionPos.convertToDetailLevel(DhSectionPos.SECTION_REGION_DETAIL_LEVEL, originSectionPos);
+ assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_REGION_DETAIL_LEVEL, 0, 0), originSectionPos);
// offset pos //
- OldDhSectionPos sectionPos = new OldDhSectionPos((byte) 0,-10000,5000);
+ long offsetSectionPos = DhSectionPos.encode((byte) 0,-10000,5000);
- sectionPos = sectionPos.convertNewToDetailLevel((byte) 1);
- Assert.assertEquals(new OldDhSectionPos((byte) 1, -5000, 2500), sectionPos);
+ offsetSectionPos = DhSectionPos.convertToDetailLevel((byte) 1, offsetSectionPos);
+ assertSectionPosEqual(DhSectionPos.encode((byte) 1, -5000, 2500), offsetSectionPos);
- sectionPos = sectionPos.convertNewToDetailLevel(OldDhSectionPos.SECTION_BLOCK_DETAIL_LEVEL);
- Assert.assertEquals(new OldDhSectionPos(OldDhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -157, 78), sectionPos);
+ offsetSectionPos = DhSectionPos.convertToDetailLevel(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, offsetSectionPos);
+ assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -157, 78), offsetSectionPos);
- sectionPos = sectionPos.convertNewToDetailLevel(OldDhSectionPos.SECTION_REGION_DETAIL_LEVEL);
- Assert.assertEquals(new OldDhSectionPos(OldDhSectionPos.SECTION_REGION_DETAIL_LEVEL, -1, 0), sectionPos);
+ offsetSectionPos = DhSectionPos.convertToDetailLevel(DhSectionPos.SECTION_REGION_DETAIL_LEVEL, offsetSectionPos);
+ assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_REGION_DETAIL_LEVEL, -1, 0), offsetSectionPos);
}
@Test
- public void GetOffsetWidth()
+ public void getOffsetWidth()
{
- OldDhSectionPos originSectionPos = new OldDhSectionPos((byte) 0,0,0);
- OldDhSectionPos sectionPos = new OldDhSectionPos((byte) 0,-10000,5000);
+ long originSectionPos = DhSectionPos.encode((byte) 0,0,0);
+ long sectionPos = DhSectionPos.encode((byte) 0,-10000,5000);
// 1 -> 0
byte returnDetailLevel = 0;
- originSectionPos = originSectionPos.convertNewToDetailLevel((byte) 1);
- Assert.assertEquals(2, originSectionPos.getWidthCountForLowerDetailedSection(returnDetailLevel));
+ originSectionPos = DhSectionPos.convertToDetailLevel((byte) 1, originSectionPos);
+ assertSectionPosEqual(2, DhSectionPos.getWidthCountForLowerDetailedSection(returnDetailLevel, originSectionPos));
- sectionPos = sectionPos.convertNewToDetailLevel((byte) 1);
- Assert.assertEquals(2, sectionPos.getWidthCountForLowerDetailedSection(returnDetailLevel));
+ sectionPos = DhSectionPos.convertToDetailLevel((byte) 1, sectionPos);
+ assertSectionPosEqual(2, DhSectionPos.getWidthCountForLowerDetailedSection(returnDetailLevel, sectionPos));
// 2 -> 1
returnDetailLevel = 1;
- originSectionPos = originSectionPos.convertNewToDetailLevel((byte) 2);
- Assert.assertEquals(2, originSectionPos.getWidthCountForLowerDetailedSection(returnDetailLevel));
+ originSectionPos = DhSectionPos.convertToDetailLevel((byte) 2, originSectionPos);
+ assertSectionPosEqual(2, DhSectionPos.getWidthCountForLowerDetailedSection(returnDetailLevel, originSectionPos));
- sectionPos = sectionPos.convertNewToDetailLevel((byte) 2);
- Assert.assertEquals(2, sectionPos.getWidthCountForLowerDetailedSection(returnDetailLevel));
+ sectionPos = DhSectionPos.convertToDetailLevel((byte) 2, sectionPos);
+ assertSectionPosEqual(2, DhSectionPos.getWidthCountForLowerDetailedSection(returnDetailLevel, sectionPos));
// Block -> 0
returnDetailLevel = 0;
- originSectionPos = originSectionPos.convertNewToDetailLevel(OldDhSectionPos.SECTION_BLOCK_DETAIL_LEVEL);
- Assert.assertEquals(64, originSectionPos.getWidthCountForLowerDetailedSection(returnDetailLevel));
+ originSectionPos = DhSectionPos.convertToDetailLevel(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, originSectionPos);
+ assertSectionPosEqual(64, DhSectionPos.getWidthCountForLowerDetailedSection(returnDetailLevel, originSectionPos));
- sectionPos = sectionPos.convertNewToDetailLevel(OldDhSectionPos.SECTION_BLOCK_DETAIL_LEVEL);
- Assert.assertEquals(64, sectionPos.getWidthCountForLowerDetailedSection(returnDetailLevel));
+ sectionPos = DhSectionPos.convertToDetailLevel(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPos);
+ assertSectionPosEqual(64, DhSectionPos.getWidthCountForLowerDetailedSection(returnDetailLevel, sectionPos));
// Region -> 3
returnDetailLevel = 3;
- originSectionPos = originSectionPos.convertNewToDetailLevel(OldDhSectionPos.SECTION_REGION_DETAIL_LEVEL);
- Assert.assertEquals(4096, originSectionPos.getWidthCountForLowerDetailedSection(returnDetailLevel));
+ originSectionPos = DhSectionPos.convertToDetailLevel(DhSectionPos.SECTION_REGION_DETAIL_LEVEL, originSectionPos);
+ assertSectionPosEqual(4096, DhSectionPos.getWidthCountForLowerDetailedSection(returnDetailLevel, originSectionPos));
- sectionPos = sectionPos.convertNewToDetailLevel(OldDhSectionPos.SECTION_REGION_DETAIL_LEVEL);
- Assert.assertEquals(4096, sectionPos.getWidthCountForLowerDetailedSection(returnDetailLevel));
+ sectionPos = DhSectionPos.convertToDetailLevel(DhSectionPos.SECTION_REGION_DETAIL_LEVEL, sectionPos);
+ assertSectionPosEqual(4096, DhSectionPos.getWidthCountForLowerDetailedSection(returnDetailLevel, sectionPos));
}
@Test
- public void GetBlockWidth()
+ public void getBlockWidth()
{
- OldDhSectionPos originSectionPos = new OldDhSectionPos((byte) 0,0,0);
- OldDhSectionPos sectionPos = new OldDhSectionPos((byte) 0,-10000,5000);
+ long originSectionPos = DhSectionPos.encode((byte) 0,0,0);
+ long sectionPos = DhSectionPos.encode((byte) 0,-10000,5000);
- Assert.assertEquals(1, originSectionPos.getBlockWidth());
- Assert.assertEquals(1, sectionPos.getBlockWidth());
+ assertSectionPosEqual(1, DhSectionPos.getBlockWidth(originSectionPos));
+ assertSectionPosEqual(1, DhSectionPos.getBlockWidth(sectionPos));
- originSectionPos = originSectionPos.convertNewToDetailLevel((byte) 1);
- Assert.assertEquals(2, originSectionPos.getBlockWidth());
- sectionPos = sectionPos.convertNewToDetailLevel((byte) 1);
- Assert.assertEquals(2, sectionPos.getBlockWidth());
+ originSectionPos = DhSectionPos.convertToDetailLevel((byte) 1, originSectionPos);
+ assertSectionPosEqual(2, DhSectionPos.getBlockWidth(originSectionPos));
+ sectionPos = DhSectionPos.convertToDetailLevel((byte) 1, sectionPos);
+ assertSectionPosEqual(2, DhSectionPos.getBlockWidth(sectionPos));
- originSectionPos = originSectionPos.convertNewToDetailLevel(OldDhSectionPos.SECTION_BLOCK_DETAIL_LEVEL);
- Assert.assertEquals(64, originSectionPos.getBlockWidth());
- sectionPos = sectionPos.convertNewToDetailLevel(OldDhSectionPos.SECTION_BLOCK_DETAIL_LEVEL);
- Assert.assertEquals(64, sectionPos.getBlockWidth());
+ originSectionPos = DhSectionPos.convertToDetailLevel(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, originSectionPos);
+ assertSectionPosEqual(64, DhSectionPos.getBlockWidth(originSectionPos));
+ sectionPos = DhSectionPos.convertToDetailLevel(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPos);
+ assertSectionPosEqual(64, DhSectionPos.getBlockWidth(sectionPos));
- originSectionPos = originSectionPos.convertNewToDetailLevel(OldDhSectionPos.SECTION_REGION_DETAIL_LEVEL);
- Assert.assertEquals(32768, originSectionPos.getBlockWidth());
- sectionPos = sectionPos.convertNewToDetailLevel(OldDhSectionPos.SECTION_REGION_DETAIL_LEVEL);
- Assert.assertEquals(32768, sectionPos.getBlockWidth());
+ originSectionPos = DhSectionPos.convertToDetailLevel(DhSectionPos.SECTION_REGION_DETAIL_LEVEL, originSectionPos);
+ assertSectionPosEqual(32768, DhSectionPos.getBlockWidth(originSectionPos));
+ sectionPos = DhSectionPos.convertToDetailLevel(DhSectionPos.SECTION_REGION_DETAIL_LEVEL, sectionPos);
+ assertSectionPosEqual(32768, DhSectionPos.getBlockWidth(sectionPos));
}
@Test
- public void GetCenterBlockPos()
+ public void getCenterBlockPos()
{
- OldDhSectionPos originSectionPos = new OldDhSectionPos((byte) 0,0,0);
- OldDhSectionPos sectionPos = new OldDhSectionPos((byte) 0,-10000,5000);
+ long originSectionPos = DhSectionPos.encode((byte) 0,0,0);
+ long sectionPos = DhSectionPos.encode((byte) 0,-10000,5000);
- Assert.assertEquals(new DhBlockPos2D(0, 0), originSectionPos.getCenterBlockPos());
- Assert.assertEquals(new DhBlockPos2D(-10000, 5000), sectionPos.getCenterBlockPos());
+ Assert.assertEquals(new DhBlockPos2D(0, 0), DhSectionPos.getCenterBlockPos(originSectionPos));
+ Assert.assertEquals(new DhBlockPos2D(-10000, 5000), DhSectionPos.getCenterBlockPos(sectionPos));
- originSectionPos = originSectionPos.convertNewToDetailLevel((byte) 1);
- Assert.assertEquals(new DhBlockPos2D(0, 0), originSectionPos.getCenterBlockPos());
- sectionPos = sectionPos.convertNewToDetailLevel((byte) 1);
- Assert.assertEquals(new DhBlockPos2D(-10000, 5000), sectionPos.getCenterBlockPos());
+ originSectionPos = 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));
- originSectionPos = originSectionPos.convertNewToDetailLevel(OldDhSectionPos.SECTION_BLOCK_DETAIL_LEVEL);
- Assert.assertEquals(new DhBlockPos2D(32, 32), originSectionPos.getCenterBlockPos());
- sectionPos = sectionPos.convertNewToDetailLevel(OldDhSectionPos.SECTION_BLOCK_DETAIL_LEVEL);
- Assert.assertEquals(new DhBlockPos2D(-10016, 5024), sectionPos.getCenterBlockPos());
+ 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));
+
+
+ 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
+ public void getMinCornerBlockPos()
+ {
+ long pos;
+
+ // origin block detail
+ pos = DhSectionPos.encode((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);
+ 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);
+ Assert.assertEquals(-1 * DhSectionPos.getBlockWidth(pos), DhSectionPos.getMinCornerBlockX(pos));
+ Assert.assertEquals(-2 * DhSectionPos.getBlockWidth(pos), DhSectionPos.getMinCornerBlockZ(pos));
- originSectionPos = originSectionPos.convertNewToDetailLevel(OldDhSectionPos.SECTION_REGION_DETAIL_LEVEL);
- Assert.assertEquals(new DhBlockPos2D(16384, 16384), originSectionPos.getCenterBlockPos());
- sectionPos = sectionPos.convertNewToDetailLevel(OldDhSectionPos.SECTION_REGION_DETAIL_LEVEL);
- Assert.assertEquals(new DhBlockPos2D(-16384, 16384), sectionPos.getCenterBlockPos());
+ // origin chunk detail
+ pos = DhSectionPos.encode(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);
+ Assert.assertEquals(2 * DhSectionPos.getBlockWidth(pos), DhSectionPos.getMinCornerBlockX(pos));
+ Assert.assertEquals(3 * DhSectionPos.getBlockWidth(pos), DhSectionPos.getMinCornerBlockZ(pos));
+
}
+ @Test
+ public void getAdjacentPos()
+ {
+ long pos = DhSectionPos.encode((byte) 0, 0, 0);
+
+ assertSectionPosEqual(DhSectionPos.encode((byte) 0, 0, -1), DhSectionPos.getAdjacentPos(EDhDirection.NORTH, pos));
+ assertSectionPosEqual(DhSectionPos.encode((byte) 0, 0, 1), DhSectionPos.getAdjacentPos(EDhDirection.SOUTH, pos));
+
+ assertSectionPosEqual(DhSectionPos.encode((byte) 0, 1, 0), DhSectionPos.getAdjacentPos(EDhDirection.EAST, pos));
+ assertSectionPosEqual(DhSectionPos.encode((byte) 0, -1, 0), DhSectionPos.getAdjacentPos(EDhDirection.WEST, pos));
+
+ // getting the adjacent position in the up and down position don't make sense
+ Assert.assertThrows(IllegalArgumentException.class, () -> { DhSectionPos.getAdjacentPos(EDhDirection.UP, pos); });
+ Assert.assertThrows(IllegalArgumentException.class, () -> { DhSectionPos.getAdjacentPos(EDhDirection.DOWN, pos); });
+ }
+
+ @Test
+ public void forEachChildIterator()
+ {
+ long pos = DhSectionPos.encode((byte) 1, 0, 0);
+
+ ArrayList childPosList = new ArrayList<>();
+ AtomicInteger childCount = new AtomicInteger(0);
+ DhSectionPos.forEachChild((childPos) ->
+ {
+ childCount.incrementAndGet();
+ childPosList.add(childPos);
+ }, pos);
+
+ 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)));
+
+ }
+
+
+
+
+ //================//
+ // helper methods //
+ //================//
+
+ public static void assertSectionPosEqual(long expected, long actual) { assertSectionPosEqual("", expected, actual); }
+ public static void assertSectionPosEqual(String messagePrefix, long expected, long actual)
+ {
+ if (!messagePrefix.endsWith(" "))
+ {
+ messagePrefix += " ";
+ }
+
+ String expectedString = DhSectionPos.toString(expected);
+ String actualString = DhSectionPos.toString(actual);
+ String mismatchSuffix = "expected: ["+expectedString+"] actual: ["+actualString+"].";
+
+ Assert.assertEquals(messagePrefix+"Detail level mismatch, "+mismatchSuffix, DhSectionPos.getDetailLevel(expected), DhSectionPos.getDetailLevel(actual));
+ Assert.assertEquals(messagePrefix+"X Pos mismatch, "+mismatchSuffix, DhSectionPos.getX(expected), DhSectionPos.getX(actual));
+ Assert.assertEquals(messagePrefix+"Z Pos mismatch, "+mismatchSuffix, DhSectionPos.getZ(expected), DhSectionPos.getZ(actual));
+ }
+
+
}