Skip to content

Instantly share code, notes, and snippets.

@CorgiTaco
Created November 7, 2020 07:56
Show Gist options
  • Save CorgiTaco/393bfa62b6579befc1da8bbcb27c0d8d to your computer and use it in GitHub Desktop.
Save CorgiTaco/393bfa62b6579befc1da8bbcb27c0d8d to your computer and use it in GitHub Desktop.
package io.github.opencubicchunks.cubicchunks.chunk.heightmap;
import net.minecraft.util.BitStorage;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess;
import java.util.function.Predicate;
public class CCHeightmap {
private static final Predicate<BlockState> NOT_AIR = (blockState) -> !blockState.isAir();
private static final Predicate<BlockState> MATERIAL_MOTION_BLOCKING = (blockState) -> blockState.getMaterial().blocksMotion();
private final BitStorage data;
private final Predicate<BlockState> isOpaque;
private final ChunkAccess chunk;
public static final int BLOCK_COLUMNS_PER_COLUMN = 16 * 16; //Always needs to be a power of 2.
int scale;
private boolean isDirty = false;
public CCHeightmap(int scale) {
this.isOpaque = null;
this.chunk = null;
this.scale = scale;
this.data = new BitStorage((4 + scale) + 1, BLOCK_COLUMNS_PER_COLUMN); // If the highest bit is 1, the value is null.
}
public BitStorage getData() {
return data;
}
public void setDirty() {
isDirty = true;
}
public int getScale() {
return scale;
}
public static class NodeTree<T> {
private final List<T> nodes; //Internal node array
private final int nodeChildCount; //number of children this node has
private CCHeightmap ccHeightmap;
private boolean nodesInitialised = false;
/**
* @param nodeChildCount the number of children for this node
*/
private NodeTree(int nodeChildCount) {
this.nodeChildCount = nodeChildCount;
nodes = new ArrayList<>(nodeChildCount);
}
public void setCcHeightmap(CCHeightmap ccHeightmap) {
this.ccHeightmap = ccHeightmap;
}
public CCHeightmap getCcHeightmap() {
return ccHeightmap;
}
/**
* @param nodeChildCount The number of children per node
* @param depth how deep to initialise the tree
* @return the full node tree created.
*
* A tree of depth 1 would have a return type of NodeTree<T>
* A tree of depth 2 would have a return type of NodeTree<NodeTree<T>>
* etc
*/
public static <T> NodeTree<T> createTree(int nodeChildCount, int depth) {
if(depth < 1) {
NodeTree<T> nodeTree = new NodeTree<>(nodeChildCount);
nodeTree.initialiseNodesIfNot();
return nodeTree;
}
NodeTree<T> tree = new NodeTree<>(nodeChildCount);
unsafeAddTreeToNode(tree, depth);
return tree;
}
public void initialiseNodesIfNot() {
if(!nodesInitialised) {
for (int i = 0; i < nodeChildCount; i++) {
nodes.add(null);
}
}
}
public void nullNodes() {
initialiseNodesIfNot();
for (int i = 0; i < nodeChildCount; i++) {
nodes.set(i, null);
}
}
public static <T> void unsafeAddTreeToNode(NodeTree tree, int depth) {
depth--;
for(int i = tree.nodes.size(); i < tree.nodeChildCount; i++) {
NodeTree node = new NodeTree<>(tree.nodeChildCount);
if(depth > 1) {
unsafeAddTreeToNode(node, depth);
node.nodesInitialised = true;
} else {
node.initialiseNodesIfNot();
}
tree.nodes.add(i, node);
}
}
public T getNode(int i) {
initialiseNodesIfNot();
return nodes.get(i);
}
public void setNode(int i, T val) {
initialiseNodesIfNot();
nodes.set(i, val);
}
public T getNodeUnchecked(int i) {
return nodes.get(i);
}
public void setNodeUnchecked(int i, T val) {
nodes.set(i, val);
}
static Random random = new Random(1);
public static void main(String[] args) {
NodeTree<NodeTree<CCHeightmap>> root = NodeTree.createTree(2, 3);
root.setCcHeightmap(new CCHeightmap(2));
root.getCcHeightmap().setDirty();
NodeTree<CCHeightmap> parent = root.getNode(0);
parent.setCcHeightmap(new CCHeightmap(1));
parent.getCcHeightmap().setDirty();
NodeTree<CCHeightmap> parent2 = root.getNode(1);
parent2.setCcHeightmap(new CCHeightmap(1));
parent2.getCcHeightmap().setDirty();
parent.setNode(0, initializeRandomCCHeightMap(0));
parent.setNode(1, initializeRandomCCHeightMap(0));
parent2.setNode(0, initializeRandomCCHeightMap(0));
parent2.setNode(1, initializeRandomCCHeightMap(0));
System.out.println("ROOT SCALE: " + root.getCcHeightmap().getScale());
System.out.println("Root Child 0 Scale: " + root.getNode(0).getCcHeightmap().getScale());
System.out.println("Root Child 0 Child 0 Scale: " + parent.getNode(0).getScale());
System.out.println("Root Child 0 Child 1 Scale: " + parent.getNode(1).getScale());
System.out.println("\n");
System.out.println("Root Child 1 Scale: " + root.getNode(1).getCcHeightmap().getScale());
System.out.println("Root Child 1 Child 0 Scale: " + parent2.getNode(0).getScale());
System.out.println("Root Child 1 Child 1 Scale: " + parent2.getNode(1).getScale());
}
public static CCHeightmap initializeRandomCCHeightMap(int scale) {
CCHeightmap ccHeightmap = new CCHeightmap(scale);
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
ccHeightmap.getData().set(x * 16 + z, random.nextInt());
}
}
return ccHeightmap;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment