diff --git a/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/chunk/LevelCube.java b/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/chunk/LevelCube.java index 7ade6b47..da937775 100644 --- a/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/chunk/LevelCube.java +++ b/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/chunk/LevelCube.java @@ -225,21 +225,43 @@ public LevelCube(Level level, ProtoCube protoCube, @Nullable Consumer this.setAllStarts(protoCube.getAllCubeStructureStarts()); this.setAllReferences(protoCube.getAllReferences()); - this.heightmaps.putAll(protoCube.getCubeHeightmaps()); + // copy protoCube's heightmaps + ChunkPos pos = this.cubePos.asChunkPos(); + HeightmapStorage storage = ((CubicServerLevel) this.level).getHeightmapStorage(); - SurfaceTrackerLeaf[] protoCubeLightHeightmaps = protoCube.getLightHeightmaps(); - for (int localZ = 0; localZ < CubeAccess.DIAMETER_IN_SECTIONS; localZ++) { - for (int localX = 0; localX < CubeAccess.DIAMETER_IN_SECTIONS; localX++) { - int i = localX + localZ * CubeAccess.DIAMETER_IN_SECTIONS; + // initialize the heightmap map + for (Heightmap.Types type : Heightmap.Types.values()) { + this.heightmaps.put(type, new SurfaceTrackerLeaf[DIAMETER_IN_SECTIONS*DIAMETER_IN_SECTIONS]); + } - this.lightHeightmaps[i] = protoCubeLightHeightmaps[i]; - if (this.lightHeightmaps[i] == null) { - System.out.println("Got a null light heightmap while upgrading from CubePrimer at " + this.cubePos); - } else { - this.lightHeightmaps[i].loadCube(localX, localZ, ((CubicServerLevel) this.level).getHeightmapStorage(), this); + for (int sectionX = 0; sectionX < CubeAccess.DIAMETER_IN_SECTIONS; sectionX++) { + for (int sectionZ = 0; sectionZ < CubeAccess.DIAMETER_IN_SECTIONS; sectionZ++) { + + LevelChunk chunk = this.level.getChunk(pos.x + sectionX, pos.z + sectionZ); + int heightmapIndex = sectionX + sectionZ * DIAMETER_IN_SECTIONS; + + // promote the ProtoCube's vanilla heightmaps for this chunk + for (Map.Entry entry : chunk.getHeightmaps()) { + SurfaceTrackerWrapper wrapper = (SurfaceTrackerWrapper) entry.getValue(); + + SurfaceTrackerLeaf[] protoLeaves = protoCube.getCubeHeightmaps().get(entry.getKey()); + SurfaceTrackerLeaf protoLeaf = protoLeaves != null ? protoLeaves[heightmapIndex] : null; + + SurfaceTrackerLeaf levelLeaf = wrapper.loadCube(storage, this, protoLeaf); + this.heightmaps.get(entry.getKey())[heightmapIndex] = levelLeaf; } + + // promote the ProtoCube's light heightmap for this chunk + SurfaceTrackerWrapper lightWrapper = (SurfaceTrackerWrapper) ((LightHeightmapGetter) chunk).getLightHeightmap(); + SurfaceTrackerLeaf lightLevelLeaf = lightWrapper.loadCube(storage, this, null); + + if (lightLevelLeaf == null) + System.out.println("!"); + + this.lightHeightmaps[heightmapIndex] = lightLevelLeaf; } } + this.setCubeLight(protoCube.hasCubeLight()); this.dirty = true; } @@ -248,18 +270,6 @@ public LevelCube(Level level, ProtoCube protoCube, @Nullable Consumer return this.heightmaps; } - @Override public void sectionLoaded(@Nonnull SurfaceTrackerLeaf surfaceTrackerLeaf, int localSectionX, int localSectionZ) { - int idx = localSectionX + localSectionZ * DIAMETER_IN_SECTIONS; - - if (surfaceTrackerLeaf.getRawType() == -1) { //light - this.lightHeightmaps[idx] = surfaceTrackerLeaf; - } else { // normal heightmap - this.heightmaps.computeIfAbsent(surfaceTrackerLeaf.getType(), - type -> new SurfaceTrackerLeaf[DIAMETER_IN_SECTIONS * DIAMETER_IN_SECTIONS] - )[idx] = surfaceTrackerLeaf; - } - } - @Override public void unloadNode(@Nonnull HeightmapStorage storage) { for (SurfaceTrackerLeaf[] heightmapLeaves : this.heightmaps.values()) { @@ -308,6 +318,17 @@ public int getHighestLight(int x, int z) { int zSection = blockToCubeLocalSection(z); int idx = xSection + zSection * DIAMETER_IN_SECTIONS; + + SurfaceTrackerLeaf leaf = this.lightHeightmaps[idx]; + try { + Thread.sleep(1); + } catch (InterruptedException ex) { + throw new RuntimeException(); + } + SurfaceTrackerLeaf leaf2 = this.lightHeightmaps[idx]; + if (leaf == null) + System.out.println("!"); + SurfaceTrackerLeaf sectionAbove = this.lightHeightmaps[idx].getSectionAbove(); int dy = CubeAccess.DIAMETER_IN_BLOCKS - 1; @@ -1090,29 +1111,11 @@ public void unpackTicks() { } public void postLoad() { + if (this.postLoad != null) { this.postLoad.accept(this); this.postLoad = null; } - // TODO heightmap stuff should probably be elsewhere rather than here. - ChunkPos pos = this.cubePos.asChunkPos(); - HeightmapStorage storage = ((CubicServerLevel) this.level).getHeightmapStorage(); - for (int x = 0; x < CubeAccess.DIAMETER_IN_SECTIONS; x++) { - for (int z = 0; z < CubeAccess.DIAMETER_IN_SECTIONS; z++) { - - // This force-loads the column, but it shouldn't matter if column-cube load order is working properly. - LevelChunk chunk = this.level.getChunk(pos.x + x, pos.z + z); - ((ColumnCubeMapGetter) chunk).getCubeMap().markLoaded(this.cubePos.getY()); - for (Map.Entry entry : chunk.getHeightmaps()) { - Heightmap heightmap = entry.getValue(); - SurfaceTrackerWrapper tracker = (SurfaceTrackerWrapper) heightmap; - tracker.loadCube(storage, this); - } - - // TODO probably don't want to do this if the cube was already loaded as a CubePrimer - ((LightHeightmapGetter) chunk).getServerLightHeightmap().loadCube(storage, this); - } - } } public void invalidateAllBlockEntities() { diff --git a/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/chunk/ProtoCube.java b/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/chunk/ProtoCube.java index a9d3597e..49402888 100644 --- a/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/chunk/ProtoCube.java +++ b/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/chunk/ProtoCube.java @@ -224,7 +224,13 @@ public void onEnteringFeaturesStatus() { } } - lightHeightmap.loadCube(((CubicServerLevel) this.levelHeightAccessor).getHeightmapStorage(), this); + SurfaceTrackerLeaf lightLeaf = lightHeightmap.loadCube(((CubicServerLevel) this.levelHeightAccessor).getHeightmapStorage(), this, null); + int heightmapIndex = dx + dz * DIAMETER_IN_SECTIONS; + + if (lightLeaf == null) + System.out.println("!"); + + this.lightHeightmaps[heightmapIndex] = lightLeaf; for (int z = 0; z < SECTION_DIAMETER; z++) { for (int x = 0; x < SECTION_DIAMETER; x++) { @@ -240,19 +246,6 @@ public void onEnteringFeaturesStatus() { } } - @Override - public void sectionLoaded(@Nonnull SurfaceTrackerLeaf surfaceTrackerLeaf, int localSectionX, int localSectionZ) { - int idx = localSectionX + localSectionZ * DIAMETER_IN_SECTIONS; - - if (surfaceTrackerLeaf.getRawType() == -1) { //light - this.lightHeightmaps[idx] = surfaceTrackerLeaf; - } else { // normal heightmap - this.heightmaps.computeIfAbsent(surfaceTrackerLeaf.getType(), - type -> new SurfaceTrackerLeaf[DIAMETER_IN_SECTIONS * DIAMETER_IN_SECTIONS] - )[idx] = surfaceTrackerLeaf; - } - } - @Override public void unloadNode(@Nonnull HeightmapStorage storage) { for (SurfaceTrackerLeaf[] heightmapLeaves : this.heightmaps.values()) { @@ -368,11 +361,9 @@ private SurfaceTrackerLeaf[] getHeightmapSections(Heightmap.Types type) { for (int dx = 0; dx < CubeAccess.DIAMETER_IN_SECTIONS; dx++) { for (int dz = 0; dz < CubeAccess.DIAMETER_IN_SECTIONS; dz++) { int idx = dx + dz * CubeAccess.DIAMETER_IN_SECTIONS; - SurfaceTrackerLeaf leaf = new SurfaceTrackerLeaf(cubePos.getY(), null, (byte) type.ordinal()); - leaf.loadCube(dx, dz, ((CubicServerLevel) ((ServerLevelAccessor) this.levelHeightAccessor).getLevel()).getHeightmapStorage(), this); + SurfaceTrackerLeaf leaf = new SurfaceTrackerLeaf(this, null, (byte) type.ordinal()); // On creation of a new node for a cube, both the node and its parents must be marked dirty leaf.setAllDirty(); - leaf.markAncestorsDirty(); surfaceTrackerLeaves[idx] = leaf; } } @@ -539,6 +530,10 @@ public int getHighestLight(int x, int z) { int zSection = blockToCubeLocalSection(z); int idx = xSection + zSection * DIAMETER_IN_SECTIONS; + + if (this.lightHeightmaps[idx] == null) + System.out.println("!"); + SurfaceTrackerLeaf sectionAbove = this.lightHeightmaps[idx].getSectionAbove(); int dy = CubeAccess.DIAMETER_IN_BLOCKS - 1; diff --git a/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/levelgen/heightmap/HeightmapNode.java b/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/levelgen/heightmap/HeightmapNode.java index e14753ec..8e6282cc 100644 --- a/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/levelgen/heightmap/HeightmapNode.java +++ b/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/levelgen/heightmap/HeightmapNode.java @@ -6,10 +6,6 @@ public interface HeightmapNode { - default void sectionLoaded(@Nonnull SurfaceTrackerLeaf surfaceTrackerLeaf, int localSectionX, int localSectionZ) { - throw new IllegalStateException("Should not be reached"); - } - void unloadNode(@Nonnull HeightmapStorage storage); int getHighest(int x, int z, byte heightmapType); diff --git a/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/levelgen/heightmap/surfacetrackertree/SurfaceTrackerBranch.java b/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/levelgen/heightmap/surfacetrackertree/SurfaceTrackerBranch.java index 536a82bb..02c12b98 100644 --- a/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/levelgen/heightmap/surfacetrackertree/SurfaceTrackerBranch.java +++ b/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/levelgen/heightmap/surfacetrackertree/SurfaceTrackerBranch.java @@ -43,7 +43,7 @@ protected int updateHeight(int x, int z, int idx) { } } - @Override public void loadCube(int localSectionX, int localSectionZ, HeightmapStorage storage, HeightmapNode newNode) { + public SurfaceTrackerLeaf loadCube(HeightmapStorage storage, HeightmapNode newNode, @Nullable SurfaceTrackerLeaf protoLeaf) { int newScale = scale - 1; // Attempt to load all children from storage @@ -56,18 +56,48 @@ protected int updateHeight(int x, int z, int idx) { int idx = indexOfRawHeightNode(newNode.getNodeY(), scale, scaledY); int newScaledY = indexToScaledY(idx, scale, scaledY); - if (children[idx] == null) { - // If the child containing new node has not been loaded from storage, create it - // Scale 1 nodes create leaf node children - if (newScale == 0) { - children[idx] = new SurfaceTrackerLeaf(newScaledY, this, this.heightmapType); - } else { + + // child is a leaf + if (newScale == 0) { + + assert protoLeaf == null || children[idx] == null : "!"; + + SurfaceTrackerLeaf newLeaf; + + // converting an existing node + if (children[idx] != null) { + newLeaf = new SurfaceTrackerLeaf(newNode, this, (SurfaceTrackerLeaf) children[idx]); + } + // attaching an external leaf + else if (protoLeaf != null) { + newLeaf = new SurfaceTrackerLeaf(newNode, this, protoLeaf); + } + // creating a new leaf + else { + newLeaf = new SurfaceTrackerLeaf(newNode, this, this.heightmapType); + } + + children[idx] = newLeaf; + newLeaf.markAncestorsDirty(); + + onChildLoaded(); + + return newLeaf; + } + + // child is a branch + else { + + // lazily create new branches + if (children[idx] == null) { children[idx] = new SurfaceTrackerBranch(newScale, newScaledY, this, this.heightmapType); } + + return ((SurfaceTrackerBranch) children[idx]).loadCube(storage, newNode, protoLeaf); } - children[idx].loadCube(localSectionX, localSectionZ, storage, newNode); } + @Override protected void unload(HeightmapStorage storage) { for (SurfaceTrackerNode child : this.children) { assert child == null : "Heightmap branch being unloaded while holding a child?!"; diff --git a/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/levelgen/heightmap/surfacetrackertree/SurfaceTrackerLeaf.java b/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/levelgen/heightmap/surfacetrackertree/SurfaceTrackerLeaf.java index d8157639..279ca8e7 100644 --- a/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/levelgen/heightmap/surfacetrackertree/SurfaceTrackerLeaf.java +++ b/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/levelgen/heightmap/surfacetrackertree/SurfaceTrackerLeaf.java @@ -11,12 +11,22 @@ import io.github.opencubicchunks.cubicchunks.world.level.levelgen.heightmap.HeightmapStorage; public class SurfaceTrackerLeaf extends SurfaceTrackerNode { - protected HeightmapNode node; - public SurfaceTrackerLeaf(int y, @Nullable SurfaceTrackerBranch parent, byte heightmapType) { - super(0, y, parent, heightmapType); + protected final HeightmapNode node; + + public SurfaceTrackerLeaf(HeightmapNode node, @Nullable SurfaceTrackerBranch parent, byte heightmapType) { + super(0, node.getNodeY(), parent, heightmapType); + + this.node = node; + } + + public SurfaceTrackerLeaf(HeightmapNode node, @Nullable SurfaceTrackerBranch parent, SurfaceTrackerLeaf protoLeaf) { + super(0, node.getNodeY(), parent, protoLeaf.heightmapType, protoLeaf.heights, protoLeaf.dirtyPositions); + + this.node = node; } + @Override protected int updateHeight(int x, int z, int idx) { synchronized(this) { @@ -29,27 +39,6 @@ protected int updateHeight(int x, int z, int idx) { } } - @Override - public synchronized void loadCube(int localSectionX, int localSectionZ, HeightmapStorage storage, @Nonnull HeightmapNode newNode) { - boolean isBeingInitialized = this.node == null; - - this.node = newNode; - newNode.sectionLoaded(this, localSectionX, localSectionZ); - - // Parent might be null for proto-cube leaf nodes - // If we are inserting a new node (it's parent is null), the parents must be updated. - // The parent can already be set for LevelCubes, their heights are inherited from their ProtoCubes - // and do not need to be updated - if (this.parent != null) { - this.markAncestorsDirty(); - if (isBeingInitialized) { - // If this is the first node inserted into this leaf, we inform the parent node. - // Both ProtoCube and LevelCube will call loadCube, this avoids invalid reference counting - this.parent.onChildLoaded(); - } - } - } - @Override protected void unload(@Nonnull HeightmapStorage storage) { assert this.node == null : "Heightmap leaf being unloaded while holding a cube?!"; @@ -68,7 +57,7 @@ public void cubeUnloaded(int localSectionX, int localSectionZ, HeightmapStorage // On unloading the node, the leaf must have no dirty positions updateDirtyHeights(localSectionX, localSectionZ); - this.node = null; +// TODO: this.node = null; // Parent can be null for a protocube that hasn't been added to the global heightmap if (parent != null) { @@ -149,9 +138,4 @@ public SurfaceTrackerLeaf getSectionAbove() { // TODO this can be optimized - don't need to go to the root every time, just the lowest node that is a parent of both this node and the node above. return this.getRoot().getMinScaleNode(scaledY + 1); } - - @VisibleForTesting - public void setNode(@Nullable HeightmapNode node) { - this.node = node; - } } diff --git a/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/levelgen/heightmap/surfacetrackertree/SurfaceTrackerNode.java b/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/levelgen/heightmap/surfacetrackertree/SurfaceTrackerNode.java index 11c10745..1c62a3e3 100644 --- a/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/levelgen/heightmap/surfacetrackertree/SurfaceTrackerNode.java +++ b/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/levelgen/heightmap/surfacetrackertree/SurfaceTrackerNode.java @@ -40,16 +40,22 @@ public abstract class SurfaceTrackerNode { protected final byte heightmapType; public SurfaceTrackerNode(int scale, int scaledY, @Nullable SurfaceTrackerBranch parent, byte heightmapType) { -// super((ChunkAccess) node, types); - // +1 in bit size to make room for null values - this.heights = new BitStorage(BASE_SIZE_BITS + 1 + scale * NODE_COUNT_BITS, WIDTH_BLOCKS * WIDTH_BLOCKS); - this.dirtyPositions = new long[WIDTH_BLOCKS * WIDTH_BLOCKS / Long.SIZE]; + this(scale, scaledY, parent, heightmapType, + new BitStorage(BASE_SIZE_BITS + 1 + scale * NODE_COUNT_BITS, WIDTH_BLOCKS * WIDTH_BLOCKS), + new long[WIDTH_BLOCKS * WIDTH_BLOCKS / Long.SIZE] + ); + } + + protected SurfaceTrackerNode(int scale, int scaledY, @Nullable SurfaceTrackerBranch parent, byte heightmapType, BitStorage heights, long[] dirtyPositions) { + this.heights = heights; + this.dirtyPositions = dirtyPositions; this.parent = parent; this.scaledY = scaledY; this.scale = (byte) scale; this.heightmapType = heightmapType; } + /** * Get the height for a given position. Recomputes the height if the column is marked dirty in this section. * x and z are GLOBAL coordinates (cube local is also fine, but section/chunk local is WRONG). @@ -68,8 +74,6 @@ public int getHeight(int x, int z) { */ protected abstract int updateHeight(int x, int z, int idx); - public abstract void loadCube(int localSectionX, int localSectionZ, HeightmapStorage storage, HeightmapNode newNode); - /** * Tells a node to unload itself, nulling its parent, and passing itself to the provided storage */ diff --git a/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/levelgen/heightmap/surfacetrackertree/SurfaceTrackerSectionStorage.java b/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/levelgen/heightmap/surfacetrackertree/SurfaceTrackerSectionStorage.java index 022a6da7..0da2da76 100644 --- a/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/levelgen/heightmap/surfacetrackertree/SurfaceTrackerSectionStorage.java +++ b/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/levelgen/heightmap/surfacetrackertree/SurfaceTrackerSectionStorage.java @@ -15,7 +15,7 @@ public void unloadNode(SurfaceTrackerNode surfaceTrackerNode) { saved.put(new PackedTypeScaleScaledY(surfaceTrackerNode.heightmapType, surfaceTrackerNode.scale, surfaceTrackerNode.scaledY), surfaceTrackerNode); if (surfaceTrackerNode.scale == 0) { - ((SurfaceTrackerLeaf) surfaceTrackerNode).node = null; +// TODO: ((SurfaceTrackerLeaf) surfaceTrackerNode).node = null; } else { Arrays.fill(((SurfaceTrackerBranch) surfaceTrackerNode).children, null); } diff --git a/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/levelgen/heightmap/surfacetrackertree/SurfaceTrackerWrapper.java b/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/levelgen/heightmap/surfacetrackertree/SurfaceTrackerWrapper.java index 18dc8727..bdf30f73 100644 --- a/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/levelgen/heightmap/surfacetrackertree/SurfaceTrackerWrapper.java +++ b/src/main/java/io/github/opencubicchunks/cubicchunks/world/level/levelgen/heightmap/surfacetrackertree/SurfaceTrackerWrapper.java @@ -76,8 +76,8 @@ public long[] getRawData() { return data.getRaw(); } - public synchronized void loadCube(HeightmapStorage storage, HeightmapNode node) { - this.surfaceTracker.loadCube(blockToCubeLocalSection(dx), blockToCubeLocalSection(dz), storage, node); + public synchronized SurfaceTrackerLeaf loadCube(HeightmapStorage storage, HeightmapNode node, @Nullable SurfaceTrackerLeaf protoLeaf) { + return this.surfaceTracker.loadCube(storage, node, protoLeaf); } @Nullable diff --git a/src/test/java/io/github/opencubicchunks/cubicchunks/levelgen/heightmap/SurfaceTrackerBranchTest.java b/src/test/java/io/github/opencubicchunks/cubicchunks/levelgen/heightmap/SurfaceTrackerBranchTest.java index ea9d58bd..c4d04531 100644 --- a/src/test/java/io/github/opencubicchunks/cubicchunks/levelgen/heightmap/SurfaceTrackerBranchTest.java +++ b/src/test/java/io/github/opencubicchunks/cubicchunks/levelgen/heightmap/SurfaceTrackerBranchTest.java @@ -37,7 +37,7 @@ public void testValidScaleBounds() { public void testLeafInsertionIntoRoot() { NullHeightmapStorage storage = new NullHeightmapStorage(); SurfaceTrackerBranch root = new SurfaceTrackerBranch(SurfaceTrackerNode.MAX_SCALE, 0, null, (byte) 0); - root.loadCube(0, 0, storage, new TestHeightmapNode(0)); + root.loadCube(storage, new TestHeightmapNode(0), null); SurfaceTrackerLeaf leaf = root.getMinScaleNode(0); assertNotNull(leaf, "Appropriate leaf was null after loading node into root"); diff --git a/src/test/java/io/github/opencubicchunks/cubicchunks/levelgen/heightmap/SurfaceTrackerLeafTest.java b/src/test/java/io/github/opencubicchunks/cubicchunks/levelgen/heightmap/SurfaceTrackerLeafTest.java index 0d2737e0..ce8e4f4c 100644 --- a/src/test/java/io/github/opencubicchunks/cubicchunks/levelgen/heightmap/SurfaceTrackerLeafTest.java +++ b/src/test/java/io/github/opencubicchunks/cubicchunks/levelgen/heightmap/SurfaceTrackerLeafTest.java @@ -30,9 +30,10 @@ public class SurfaceTrackerLeafTest { */ @Test public void testCubeLoadUnload() { - SurfaceTrackerLeaf leaf = new SurfaceTrackerLeaf(0, null, (byte) 0); - leaf.loadCube(0, 0, null, new TestHeightmapNode(0)); + TestHeightmapNode testNode = new TestHeightmapNode(0); + SurfaceTrackerLeaf leaf = new SurfaceTrackerLeaf(testNode, null, (byte) 0); + assertNotNull(leaf.getNode(), "Leaf had null HeightmapNode after being loaded"); leaf.cubeUnloaded(0, 0, null); @@ -48,7 +49,7 @@ public void testLeafUnload() { //Set up leaf and node with parent SurfaceTrackerBranch parent = new SurfaceTrackerBranch(SurfaceTrackerNode.MAX_SCALE, 0, null, (byte) 0); - parent.loadCube(0, 0, storage, new TestHeightmapNode(0)); + parent.loadCube(storage, new TestHeightmapNode(0), null); SurfaceTrackerLeaf leaf = parent.getMinScaleNode(0); //Unload the node @@ -63,11 +64,9 @@ public void testLeafUnload() { */ @Test public void testNoValidHeights() { - NullHeightmapStorage storage = new NullHeightmapStorage(); - SurfaceTrackerLeaf leaf = new SurfaceTrackerLeaf(0, null, (byte) 0); TestHeightmapNode testNode = new TestHeightmapNode(0); - leaf.loadCube(0, 0, storage, testNode); + SurfaceTrackerLeaf leaf = new SurfaceTrackerLeaf(testNode, null, (byte) 0); Consumer setHeight = block -> testNode.setBlock(block.x(), block.y() & (SurfaceTrackerLeaf.SCALE_0_NODE_HEIGHT - 1), block.z(), block.isOpaque()); @@ -92,11 +91,8 @@ public void testNoValidHeights() { public void testBasicFunctionality() { ReferenceHeightmap reference = new ReferenceHeightmap(0); - NullHeightmapStorage storage = new NullHeightmapStorage(); - - SurfaceTrackerLeaf leaf = new SurfaceTrackerLeaf(0, null, (byte) 0); TestHeightmapNode testNode = new TestHeightmapNode(0); - leaf.loadCube(0, 0, storage, testNode); + SurfaceTrackerLeaf leaf = new SurfaceTrackerLeaf(testNode, null, (byte) 0); Consumer setHeight = block -> { reference.set(block.y(), block.isOpaque()); @@ -135,11 +131,8 @@ public void testBasicFunctionality() { public void testManyPositions(int nodeY) { ReferenceHeightmap reference = new ReferenceHeightmap(nodeY); - NullHeightmapStorage storage = new NullHeightmapStorage(); - - SurfaceTrackerLeaf leaf = new SurfaceTrackerLeaf(nodeY, null, (byte) 0); TestHeightmapNode testNode = new TestHeightmapNode(nodeY); - leaf.loadCube(0, 0, storage, testNode); + SurfaceTrackerLeaf leaf = new SurfaceTrackerLeaf(testNode, null, (byte) 0); Consumer setHeight = block -> { reference.set(block.y(), block.isOpaque()); @@ -177,11 +170,8 @@ public void testManyPositions(int nodeY) { public void testSeededRandom() { ReferenceHeightmap reference = new ReferenceHeightmap(0); - NullHeightmapStorage storage = new NullHeightmapStorage(); - - SurfaceTrackerLeaf leaf = new SurfaceTrackerLeaf(0, null, (byte) 0); TestHeightmapNode testNode = new TestHeightmapNode(0); - leaf.loadCube(0, 0, storage, testNode); + SurfaceTrackerLeaf leaf = new SurfaceTrackerLeaf(testNode, null, (byte) 0); Consumer setHeight = block -> { reference.set(block.y(), block.isOpaque()); @@ -208,10 +198,9 @@ public void testSeededRandom() { */ @Test public void testBounds() { - NullHeightmapStorage storage = new NullHeightmapStorage(); - SurfaceTrackerLeaf leaf = new SurfaceTrackerLeaf(0, null, (byte) 0); - leaf.loadCube(0, 0, storage, new TestHeightmapNode(0)); + TestHeightmapNode node = new TestHeightmapNode(0); + SurfaceTrackerLeaf leaf = new SurfaceTrackerLeaf(node, null, (byte) 0); Consumer setHeight = block -> { leaf.onSetBlock(block.x(), block.y(), block.z(), type -> block.isOpaque()); diff --git a/src/test/java/io/github/opencubicchunks/cubicchunks/levelgen/heightmap/SurfaceTrackerNodesTest.java b/src/test/java/io/github/opencubicchunks/cubicchunks/levelgen/heightmap/SurfaceTrackerNodesTest.java index 5f225423..5f8984ca 100644 --- a/src/test/java/io/github/opencubicchunks/cubicchunks/levelgen/heightmap/SurfaceTrackerNodesTest.java +++ b/src/test/java/io/github/opencubicchunks/cubicchunks/levelgen/heightmap/SurfaceTrackerNodesTest.java @@ -51,14 +51,14 @@ public void sanityTest() { ReferenceHeightmap reference = new ReferenceHeightmap(2048); TestHeightmapNode node0 = new TestHeightmapNode(0); - SurfaceTrackerNode[] roots = new SurfaceTrackerNode[CubeAccess.DIAMETER_IN_SECTIONS * CubeAccess.DIAMETER_IN_SECTIONS]; + SurfaceTrackerBranch[] roots = new SurfaceTrackerBranch[CubeAccess.DIAMETER_IN_SECTIONS * CubeAccess.DIAMETER_IN_SECTIONS]; for (int i = 0; i < roots.length; i++) { roots[i] = new SurfaceTrackerBranch(SurfaceTrackerNode.MAX_SCALE, 0, null, (byte) 0); } for (int localSectionX = 0; localSectionX < CubeAccess.DIAMETER_IN_SECTIONS; localSectionX++) { for (int localSectionZ = 0; localSectionZ < CubeAccess.DIAMETER_IN_SECTIONS; localSectionZ++) { - roots[localSectionX + CubeAccess.DIAMETER_IN_SECTIONS * localSectionZ].loadCube(localSectionX, localSectionZ, storage, node0); + roots[localSectionX + CubeAccess.DIAMETER_IN_SECTIONS * localSectionZ].loadCube(storage, node0, null); } } @@ -95,14 +95,14 @@ public void testNoValidHeights() { ReferenceHeightmap reference = new ReferenceHeightmap(2048); TestHeightmapNode node0 = new TestHeightmapNode(0); - SurfaceTrackerNode[] roots = new SurfaceTrackerNode[CubeAccess.DIAMETER_IN_SECTIONS * CubeAccess.DIAMETER_IN_SECTIONS]; + SurfaceTrackerBranch[] roots = new SurfaceTrackerBranch[CubeAccess.DIAMETER_IN_SECTIONS * CubeAccess.DIAMETER_IN_SECTIONS]; for (int i = 0; i < roots.length; i++) { - roots[i] = new SurfaceTrackerBranch(SurfaceTrackerNode.MAX_SCALE, 0, null, (byte) 0); + roots[i] = new SurfaceTrackerBranch(SurfaceTrackerBranch.MAX_SCALE, 0, null, (byte) 0); } for (int localSectionX = 0; localSectionX < CubeAccess.DIAMETER_IN_SECTIONS; localSectionX++) { for (int localSectionZ = 0; localSectionZ < CubeAccess.DIAMETER_IN_SECTIONS; localSectionZ++) { - roots[localSectionX + CubeAccess.DIAMETER_IN_SECTIONS * localSectionZ].loadCube(localSectionX, localSectionZ, storage, node0); + roots[localSectionX + CubeAccess.DIAMETER_IN_SECTIONS * localSectionZ].loadCube(storage, node0, null); } } @@ -139,7 +139,7 @@ public void seededRandom() { ReferenceHeightmap reference = new ReferenceHeightmap(maxCoordinate); Map nodes = new HashMap<>(); - SurfaceTrackerNode[] roots = new SurfaceTrackerNode[CubeAccess.DIAMETER_IN_SECTIONS * CubeAccess.DIAMETER_IN_SECTIONS]; + SurfaceTrackerBranch[] roots = new SurfaceTrackerBranch[CubeAccess.DIAMETER_IN_SECTIONS * CubeAccess.DIAMETER_IN_SECTIONS]; for (int i = 0; i < roots.length; i++) { roots[i] = new SurfaceTrackerBranch(SurfaceTrackerNode.MAX_SCALE, 0, null, (byte) 0); } @@ -150,7 +150,7 @@ public void seededRandom() { TestHeightmapNode node = new TestHeightmapNode(y); for (int localSectionX = 0; localSectionX < CubeAccess.DIAMETER_IN_SECTIONS; localSectionX++) { for (int localSectionZ = 0; localSectionZ < CubeAccess.DIAMETER_IN_SECTIONS; localSectionZ++) { - roots[localSectionX + CubeAccess.DIAMETER_IN_SECTIONS * localSectionZ].loadCube(localSectionX, localSectionZ, storage, node); + roots[localSectionX + CubeAccess.DIAMETER_IN_SECTIONS * localSectionZ].loadCube(storage, node,null); } } return node; @@ -179,7 +179,7 @@ public void simpleUnloadTree1() { TestHeightmapStorage storage = new TestHeightmapStorage(); Map nodes = new HashMap<>(); - SurfaceTrackerNode[] roots = new SurfaceTrackerNode[CubeAccess.DIAMETER_IN_SECTIONS * CubeAccess.DIAMETER_IN_SECTIONS]; + SurfaceTrackerBranch[] roots = new SurfaceTrackerBranch[CubeAccess.DIAMETER_IN_SECTIONS * CubeAccess.DIAMETER_IN_SECTIONS]; for (int i = 0; i < roots.length; i++) { roots[i] = new SurfaceTrackerBranch(SurfaceTrackerNode.MAX_SCALE, 0, null, (byte) 0); } @@ -188,7 +188,7 @@ public void simpleUnloadTree1() { TestHeightmapNode node = new TestHeightmapNode(yPos); for (int localSectionX = 0; localSectionX < CubeAccess.DIAMETER_IN_SECTIONS; localSectionX++) { for (int localSectionZ = 0; localSectionZ < CubeAccess.DIAMETER_IN_SECTIONS; localSectionZ++) { - roots[localSectionX + CubeAccess.DIAMETER_IN_SECTIONS * localSectionZ].loadCube(localSectionX, localSectionZ, storage, node); + roots[localSectionX + CubeAccess.DIAMETER_IN_SECTIONS * localSectionZ].loadCube(storage, node, null); } } return node; @@ -217,7 +217,7 @@ public void simpleUnloadTree2() { TestHeightmapStorage storage = new TestHeightmapStorage(); Map nodes = new HashMap<>(); - SurfaceTrackerNode[] roots = new SurfaceTrackerNode[CubeAccess.DIAMETER_IN_SECTIONS * CubeAccess.DIAMETER_IN_SECTIONS]; + SurfaceTrackerBranch[] roots = new SurfaceTrackerBranch[CubeAccess.DIAMETER_IN_SECTIONS * CubeAccess.DIAMETER_IN_SECTIONS]; for (int i = 0; i < roots.length; i++) { roots[i] = new SurfaceTrackerBranch(SurfaceTrackerNode.MAX_SCALE, 0, null, (byte) 0); } @@ -226,7 +226,7 @@ public void simpleUnloadTree2() { TestHeightmapNode node = new TestHeightmapNode(yPos); for (int localSectionX = 0; localSectionX < CubeAccess.DIAMETER_IN_SECTIONS; localSectionX++) { for (int localSectionZ = 0; localSectionZ < CubeAccess.DIAMETER_IN_SECTIONS; localSectionZ++) { - roots[localSectionX + CubeAccess.DIAMETER_IN_SECTIONS * localSectionZ].loadCube(localSectionX, localSectionZ, storage, node); + roots[localSectionX + CubeAccess.DIAMETER_IN_SECTIONS * localSectionZ].loadCube(storage, node, null); } } return node; @@ -271,7 +271,7 @@ public void seededRandomUnloadTree() { TestHeightmapStorage storage = new TestHeightmapStorage(); Map nodes = new HashMap<>(); - SurfaceTrackerNode[] roots = new SurfaceTrackerNode[CubeAccess.DIAMETER_IN_SECTIONS * CubeAccess.DIAMETER_IN_SECTIONS]; + SurfaceTrackerBranch[] roots = new SurfaceTrackerBranch[CubeAccess.DIAMETER_IN_SECTIONS * CubeAccess.DIAMETER_IN_SECTIONS]; for (int i = 0; i < roots.length; i++) { roots[i] = new SurfaceTrackerBranch(SurfaceTrackerNode.MAX_SCALE, 0, null, (byte) 0); } @@ -280,7 +280,7 @@ public void seededRandomUnloadTree() { TestHeightmapNode node = new TestHeightmapNode(yPos); for (int localSectionX = 0; localSectionX < CubeAccess.DIAMETER_IN_SECTIONS; localSectionX++) { for (int localSectionZ = 0; localSectionZ < CubeAccess.DIAMETER_IN_SECTIONS; localSectionZ++) { - roots[localSectionX + CubeAccess.DIAMETER_IN_SECTIONS * localSectionZ].loadCube(localSectionX, localSectionZ, storage, node); + roots[localSectionX + CubeAccess.DIAMETER_IN_SECTIONS * localSectionZ].loadCube(storage, node, null); } } return node; @@ -325,11 +325,11 @@ public void testUnloadReload() { TestHeightmapStorage storage = new TestHeightmapStorage(); Map nodes = new HashMap<>(); - SurfaceTrackerNode root = new SurfaceTrackerBranch(SurfaceTrackerNode.MAX_SCALE, 0, null, (byte) 0); + SurfaceTrackerBranch root = new SurfaceTrackerBranch(SurfaceTrackerNode.MAX_SCALE, 0, null, (byte) 0); Function loadNode = y -> nodes.computeIfAbsent(y, yPos -> { TestHeightmapNode node = new TestHeightmapNode(yPos); - root.loadCube(0, 0, storage, node); + root.loadCube(storage, node,null); return node; }); Function unloadNode = y -> { @@ -349,7 +349,7 @@ public void testUnloadReload() { unloadNode.apply(0); - root.loadCube(0, 0, storage, cubeNode); + root.loadCube(storage, cubeNode, null); SurfaceTrackerLeaf reloadedNode = root.getMinScaleNode(0); @@ -421,12 +421,13 @@ private static void verifyAllNodesInRequiredSet(SurfaceTrackerBranch branch, Lon */ static class NullHeightmapStorage implements HeightmapStorage { @Override public void unloadNode(SurfaceTrackerNode node) { - if (node.getScale() == 0) { - ((SurfaceTrackerLeaf) node).setNode(null); - } else { - Arrays.fill(((SurfaceTrackerBranch) node).getChildren(), null); - } - node.setParent(null); + throw new RuntimeException("Not implemented"); +// if (node.getScale() == 0) { +// ((SurfaceTrackerLeaf) node).setNode(null); +// } else { +// Arrays.fill(((SurfaceTrackerBranch) node).getChildren(), null); +// } +// node.setParent(null); } @Nullable @Override public SurfaceTrackerNode loadNode(SurfaceTrackerBranch parent, byte heightmapType, int scale, int scaledY) { @@ -441,14 +442,15 @@ static class TestHeightmapStorage implements HeightmapStorage { Object2ReferenceMap saved = new Object2ReferenceOpenHashMap<>(); @Override public void unloadNode(SurfaceTrackerNode node) { - if (node.getScale() == 0) { - ((SurfaceTrackerLeaf) node).setNode(null); - } else { - Arrays.fill(((SurfaceTrackerBranch) node).getChildren(), null); - } - node.setParent(null); - - saved.put(new PackedTypeScaleScaledY(node.getRawType(), node.getScale(), node.getScaledY()), node); + throw new RuntimeException("Not implemented"); +// if (node.getScale() == 0) { +// ((SurfaceTrackerLeaf) node).setNode(null); +// } else { +// Arrays.fill(((SurfaceTrackerBranch) node).getChildren(), null); +// } +// node.setParent(null); +// +// saved.put(new PackedTypeScaleScaledY(node.getRawType(), node.getScale(), node.getScaledY()), node); } @Override public SurfaceTrackerNode loadNode(SurfaceTrackerBranch parent, byte heightmapType, int scale, int scaledY) { SurfaceTrackerNode removed = saved.remove(new PackedTypeScaleScaledY(heightmapType, scale, scaledY)); @@ -486,10 +488,6 @@ void setBlock(int x, int localY, int z, boolean isOpaque) { section.onSetBlock(x, (this.y << SurfaceTrackerNode.SCALE_0_NODE_BITS) + localY, z, heightmapType -> isOpaque); } - @Override public void sectionLoaded(@Nonnull SurfaceTrackerLeaf leaf, int localSectionX, int localSectionZ) { - this.sections[localSectionX + localSectionZ * CubeAccess.DIAMETER_IN_SECTIONS] = leaf; - } - @Override public void unloadNode(@Nonnull HeightmapStorage storage) { SurfaceTrackerLeaf[] nodes = this.sections; for (int localSectionZ = 0; localSectionZ < CubeAccess.DIAMETER_IN_SECTIONS; localSectionZ++) {