Start adding new DhSectionPos and unit tests

This commit is contained in:
James Seibel
2024-05-15 18:48:25 -05:00
parent 6e717a383d
commit cd5ff8ce35
2 changed files with 715 additions and 173 deletions
@@ -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 <https://www.gnu.org/licenses/>.
*/
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. <br><br>
*
* A section contains 64 x 64 LOD columns at a given quality.
* The Section detail level is different from the LOD detail level.
* For the specifics of how they compare can be viewed in the constants {@link #SECTION_BLOCK_DETAIL_LEVEL},
* {@link #SECTION_CHUNK_DETAIL_LEVEL}, and {@link #SECTION_REGION_DETAIL_LEVEL}).<br><br>
*
* <strong>Why does the smallest render section represent 2x2 MC chunks (section detail level 6)? </strong> <br>
* A section defines what unit the quad tree works in, because of that we don't want that unit to be too big or too small. <br>
* <strong>Too small</strong>, and we'll have 1,000s of sections running around, all needing individual files and render buffers.<br>
* <strong>Too big</strong>, and the LOD dropoff will be very noticeable.<br>
* With those thoughts in mind we decided on a smallest section size of 32 data points square (IE 2x2 chunks).
*
* @author Leetom
*/
public class 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. <Br><br>
*
* 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: <br>
* 0 -> 1 <br>
* 1 -> 2 <br>
* 2 -> 4 <br>
* 3 -> 8 <br>
* 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. <br><br>
*
* Relative child positions returned for each index: <br>
* 0 = (0,0) - North West <br>
* 1 = (1,0) - South West <br>
* 2 = (0,1) - North East <br>
* 3 = (1,1) - South East <br>
*
* @param child0to3 must be an int between 0 and 3
*/
public 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);
}
}
+304 -173
View File
@@ -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<Long> 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));
}
}