Cave Generation
Hytale’s cave generation system creates complex underground networks using a node-based approach with various shapes, prefabs, and procedural logic. Caves are composed of connected nodes that can be chambers, tunnels, or prefab-based structures.
Core Architecture
Section titled “Core Architecture”The main container for a complete cave system:
import com.hypixel.hytale.server.worldgen.cave.Cave;import com.hypixel.hytale.server.worldgen.cave.CaveType;import com.hypixel.hytale.server.worldgen.cave.element.CaveNode;
public class Cave { // Get cave configuration public CaveType getCaveType();
// Get world bounds of entire cave public WorldBounds getBounds();
// Get total node count public long getNodeCount();
// Add node to cave (called during generation) public void addNode(CaveNode element);
// Check if chunk contains cave nodes public boolean contains(long chunkIndex);
// Get nodes affecting a chunk public CaveNode[] getCaveNodes(long chunkIndex);
// Finalize cave structure public void compile();}Cave Structure:
- Caves consist of
CaveNodeobjects connected in a tree structure - Each node has a shape (ellipsoid, pipe, cylinder, etc.)
- Nodes are organized by chunk for efficient lookup
compile()must be called after all nodes are added
CaveType
Section titled “CaveType”Defines the characteristics and generation rules for a cave system:
import com.hypixel.hytale.server.worldgen.cave.CaveType;import com.hypixel.hytale.server.worldgen.cave.CaveNodeType;import com.hypixel.hytale.procedurallib.logic.point.IPointGenerator;
public class CaveType { // Identity public String getName();
// Entry configuration public CaveNodeType getEntryNode(); public int getModifiedStartHeight(int seed, int x, int y, int z, Random random); public float getStartPitch(Random random); public float getStartYaw(Random random); public int getStartDepth(Random random);
// Point generation public IPointGenerator getEntryPointGenerator();
// Conditions and masks public Int2FlagsCondition getBiomeMask(); public BlockMaskCondition getBlockMask(); public boolean isEntryThreshold(int seed, int x, int z); public boolean isHeightThreshold(int seed, int x, int y, int z);
// Height-based scaling public float getHeightRadiusFactor(int seed, double x, double z, int y); public ICoordinateCondition getHeightCondition();
// Fluid configuration public FluidLevel getFluidLevel();
// Environment and behavior public int getEnvironment(); public boolean isSurfaceLimited(); public boolean isSubmerge(); public double getMaximumSize();}Key Properties:
entryNodeType- Initial node type when cave generation startsyaw/pitch/depth- Random ranges for cave orientation and depthpointGenerator- Determines cave entry point locationsbiomeMask- Controls which biomes can have this cave typeblockMask- Determines valid blocks for cave entryheightFactors- Scales cave radius based on depthfluidLevel- Lava or water filling configurationsurfaceLimited- Whether cave connects to surfacesubmerge- Whether cave can generate underwatermaximumSize- Maximum extent of cave system
CaveNodeType
Section titled “CaveNodeType”Defines a node template in the cave tree:
import com.hypixel.hytale.server.worldgen.cave.CaveNodeType;import com.hypixel.hytale.server.worldgen.cave.shape.CaveNodeShapeEnum;import com.hypixel.hytale.common.map.IWeightedMap;
public class CaveNodeType { // Identity public String getName();
// Shape generation public CaveNodeShape generateCaveNodeShape( Random random, CaveType caveType, CaveNode parentNode, CaveNodeChildEntry childEntry, Vector3d origin, float yaw, float pitch );
// Node properties public CavePrefabContainer getPrefabContainer(); public BlockFluidEntry getFilling(Random random); public CaveNodeCoverEntry[] getCovers(); public int getPriority(); public int getEnvironment(); public boolean hasEnvironment();
// Child configuration public CaveNodeChildEntry[] getChildren(); public void setChildren(CaveNodeChildEntry[] children); public IDoubleRange getChildrenCountBounds();
// Height constraints public ICoordinateCondition getHeightCondition();}Node Configuration:
name- Identifier for debuggingprefabContainer- Structures to place in this nodefillings- Block types for cave interior (air, water, lava)shapeGenerator- Function to create the node’s geometrycovers- Floor and ceiling decorationspriority- Rendering/carving order (higher = later)children- Possible child node types and their connection ruleschildrenCountBounds- Limits on child node count
CaveNode
Section titled “CaveNode”A single node instance in a cave:
import com.hypixel.hytale.server.worldgen.cave.element.CaveNode;import com.hypixel.hytale.server.worldgen.cave.shape.CaveNodeShape;
public class CaveNode implements CaveElement { // Node configuration public CaveNodeType getCaveNodeType(); public CaveNodeShape getShape(); public int getSeedOffset();
// Orientation public float getYaw(); public float getPitch();
// Position public Vector3d getEnd(); public IWorldBounds getBounds();
// Prefabs within node public CavePrefab[] getCavePrefabs(); public void addPrefab(CavePrefab prefab);
// Height queries public int getFloorPosition(int seed, double x, double z); public int getCeilingPosition(int seed, double x, double z);
// Chunk iteration public void forEachChunk(LongConsumer consumer);
// Finalize node public void compile();}Cave Shapes
Section titled “Cave Shapes”CaveNodeShape Interface
Section titled “CaveNodeShape Interface”All cave shapes implement this interface:
import com.hypixel.hytale.server.worldgen.cave.shape.CaveNodeShape;
public interface CaveNodeShape { // Node endpoints public Vector3d getStart(); public Vector3d getEnd();
// Get anchor point for child nodes public Vector3d getAnchor(Vector3d result, double x, double y, double z);
// Bounds for chunk iteration public IWorldBounds getBounds();
// Block replacement test public boolean shouldReplace(int seed, double x, double z, int y);
// Height queries public double getFloorPosition(int seed, double x, double z); public double getCeilingPosition(int seed, double x, double z);
// Populate chunk with cave blocks public void populateChunk(int seed, ChunkGeneratorExecution execution, Cave cave, CaveNode node, Random random);
// Whether shape has geometry (default: true) default boolean hasGeometry();}Available Shape Types
Section titled “Available Shape Types”import com.hypixel.hytale.server.worldgen.cave.shape.CaveNodeShapeEnum;
public enum CaveNodeShapeEnum { PIPE, // Tubular passages CYLINDER, // Cylindrical chambers PREFAB, // Prefab-based structures EMPTY_LINE, // Connection without geometry ELLIPSOID, // Spherical/ellipsoidal caverns DISTORTED; // Noise-distorted shapes}Shape Implementations
Section titled “Shape Implementations”EllipsoidCaveNodeShape
Section titled “EllipsoidCaveNodeShape”Spherical or ellipsoidal chambers:
import com.hypixel.hytale.server.worldgen.cave.shape.EllipsoidCaveNodeShape;
// Creates spherical caverns// Defined by center point and radius// Can be elongated along axes for ellipsoidal shapesPipeCaveNodeShape
Section titled “PipeCaveNodeShape”Tubular passages connecting points:
import com.hypixel.hytale.server.worldgen.cave.shape.PipeCaveNodeShape;
// Creates tube-shaped passages// Connects start and end points// Radius can vary along lengthCylinderCaveNodeShape
Section titled “CylinderCaveNodeShape”Cylindrical chambers:
import com.hypixel.hytale.server.worldgen.cave.shape.CylinderCaveNodeShape;
// Creates vertical or oriented cylinders// Defined by axis and radiusPrefabCaveNodeShape
Section titled “PrefabCaveNodeShape”Prefab-based cave structures:
import com.hypixel.hytale.server.worldgen.cave.shape.PrefabCaveNodeShape;
// Uses prefab structure as cave shape// Can be rotatedpublic PrefabRotation getPrefabRotation();EmptyLineCaveNodeShape
Section titled “EmptyLineCaveNodeShape”Connection without geometry:
import com.hypixel.hytale.server.worldgen.cave.shape.EmptyLineCaveNodeShape;
// Connects nodes without carving blocks// Used for logic connections// hasGeometry() returns falseTetrahedronCaveNodeShape
Section titled “TetrahedronCaveNodeShape”Tetrahedral chambers:
import com.hypixel.hytale.server.worldgen.cave.shape.TetrahedronCaveNodeShape;
// Creates tetrahedral caverns// Four triangular facesDistorted Shapes
Section titled “Distorted Shapes”Shapes with procedural noise distortion for organic appearance:
import com.hypixel.hytale.server.worldgen.cave.shape.distorted.*;
// Base distorted shape typespublic class DistortedEllipsoidShape extends AbstractDistortedBody;public class DistortedCylinderShape extends AbstractDistortedBody;public class DistortedPipeShape extends AbstractDistortedExtrusion;
// Distortion configurationpublic class ShapeDistortion { // Applies noise-based distortion to shape surface}Distorted Shape Features:
- Apply noise functions to deform basic shapes
- Create organic, natural-looking caves
- Different distortion patterns for variety
Cave Generation Process
Section titled “Cave Generation Process”CaveGenerator
Section titled “CaveGenerator”Handles the generation of cave systems:
import com.hypixel.hytale.server.worldgen.cave.CaveGenerator;
public class CaveGenerator { // Get available cave types public CaveType[] getCaveTypes();
// Generate a complete cave public Cave generate(int seed, ChunkGenerator chunkGenerator, CaveType caveType, int x, int y, int z);
// Protected methods for customization: protected Cave newCave(CaveType caveType);
protected void startCave(int seed, ChunkGenerator chunkGenerator, Cave cave, Vector3d origin, Random random);
protected void continueNode(int seed, ChunkGenerator chunkGenerator, Cave cave, CaveNode parent, int depth, Random random);
protected int getChildrenCount(CaveNodeType type, Random random);
protected CaveNodeChildEntry[] getChildEntriesRandomized( CaveNodeType type, Random random);
protected void generatePrefabs(int seed, ChunkGenerator chunkGenerator, CaveNode parent, CaveNode node);}Generation Algorithm
Section titled “Generation Algorithm”The cave generator follows this process:
-
Start Cave:
- Determine entry height (may be fixed or variable)
- Get initial yaw, pitch, and depth from
CaveType - Create entry node using
entryNodeType - Check biome mask for entry and exit points
-
Continue Node:
- For each child entry in current node:
- Check if child should generate (chance-based)
- Select child type from weighted map
- Calculate child origin from parent anchor
- Calculate child yaw/pitch from parent orientation
- Generate child shape
- Check height and biome conditions
- Add child node to cave if valid
- Recursively continue child node (decremented depth)
- For each child entry in current node:
-
Generate Prefabs:
- Iterate through prefab container entries
- For each entry:
- Determine iteration count
- Find random positions within node bounds
- Check biome, height, and noise conditions
- Place prefab if conditions met
-
Compile:
- Sort nodes by priority for proper rendering order
- Organize nodes by chunk for efficient lookup
- Finalize all prefab placements
Biome Masking
Section titled “Biome Masking”Caves use biome masks with flag-based results:
import com.hypixel.hytale.server.worldgen.cave.CaveBiomeMaskFlags;import com.hypixel.hytale.server.worldgen.util.condition.flag.Int2FlagsCondition;
// Biome mask returns flagsInt2FlagsCondition biomeMask = caveType.getBiomeMask();int flags = biomeMask.eval(biomeId);
// Check flagspublic static boolean canGenerate(int flags); // Can start generationpublic static boolean canPopulate(int flags); // Can add to cavepublic static boolean canContinue(int flags); // Can continue branching
// Default maskspublic static final Int2FlagsCondition DEFAULT_ALLOW; // All flags setpublic static final Int2FlagsCondition DEFAULT_DENY; // No flags setFlag System:
- Bit flags allow fine-grained control
canGenerate- Basic permission to generate cavecanPopulate- Permission to add geometry (can generate without geometry)canContinue- Permission to branch and create children- Allows caves to “pass through” biomes without carving
Cave Prefabs
Section titled “Cave Prefabs”CavePrefab
Section titled “CavePrefab”Structures placed within cave nodes:
import com.hypixel.hytale.server.worldgen.cave.element.CavePrefab;
public class CavePrefab implements CaveElement { // Prefab configuration public WorldGenPrefabSupplier getPrefab(); public PrefabRotation getRotation();
// Conditions public IIntCondition getBiomeMask(); public BlockMaskCondition getConfiguration();
// Position public int getX(); public int getY(); public int getZ(); public IWorldBounds getBounds();}CavePrefabContainer
Section titled “CavePrefabContainer”Manages prefab placement rules:
import com.hypixel.hytale.server.worldgen.cave.prefab.CavePrefabContainer;
public class CavePrefabContainer { public CavePrefabEntry[] getEntries();}
// Each entry contains:public class CavePrefabEntry { // Weighted selection of prefabs public IWeightedMap<WorldGenPrefabSupplier> getPrefabs(); public WorldGenPrefabSupplier getPrefab(double random);
// Placement configuration public CavePrefabConfig getConfig();}
// Configuration for prefab placementpublic class CavePrefabConfig { // Rotation options public PrefabRotation getRotation(Random random);
// Placement rules public int getIterations(double random); public int getHeight(int seed, int x, int z, CaveNode caveNode); public double getDisplacement(int seed, int x, int z, CaveNode caveNode);
// Conditions public boolean isMatchingNoiseDensity(int seed, int x, int z); public boolean isMatchingHeight(int seed, int x, int y, int z, Random random); public boolean isMatchingBiome(Biome biome);
// Masks public IIntCondition getBiomeMask(); public BlockMaskCondition getBlockMask();}CavePrefabPlacement
Section titled “CavePrefabPlacement”Determines vertical placement strategy:
import com.hypixel.hytale.server.worldgen.cave.CavePrefabPlacement;
// Placement modes for prefabs within caves// Controls how Y coordinate is determined from cave nodeCave Node Children
Section titled “Cave Node Children”CaveNodeChildEntry
Section titled “CaveNodeChildEntry”Defines how child nodes connect to parent:
// Located in CaveNodeType.CaveNodeChildEntry
public class CaveNodeChildEntry { // Child type selection public IWeightedMap<CaveNodeType> getTypes();
// Connection geometry public Vector3d getAnchor(); // Relative position in parent public Vector3d getOffset(); // Additional offset public PrefabRotation getRotation(Random random);
// Orientation public OrientationModifier getPitchModifier(); public OrientationModifier getYawModifier(); public CaveYawMode getYawMode();
// Generation limits public double getChance(); // 0-1 probability public IDoubleRange getRepeat(); // How many to generate public IDoubleRange getChildrenLimit(); // Max depth for children}Yaw Modes
Section titled “Yaw Modes”import com.hypixel.hytale.server.worldgen.cave.CaveYawMode;
// How child yaw relates to parent yaw// Combined with parent rotation for proper orientationpublic CaveYawMode getYawMode();OrientationModifier
Section titled “OrientationModifier”@FunctionalInterfacepublic interface OrientationModifier { float calc(float parentValue, Random random);}
// Modifies parent pitch/yaw for child// Can add randomness or apply transformationsCave Node Covers
Section titled “Cave Node Covers”Decorative layers on cave floors and ceilings:
// Located in CaveNodeType.CaveNodeCoverEntry
public class CaveNodeCoverEntry { // Get cover entry public Entry get(Random random);
// Conditions public ICoordinateRndCondition getHeightCondition(); public ICoordinateCondition getMapCondition(); public ICoordinateCondition getDensityCondition(); public IBlockFluidCondition getParentCondition();
// Type (floor or ceiling) public CaveNodeCoverType getType();}
public enum CaveNodeCoverType { FLOOR(-1), // Places below cave CEILING(1); // Places above cave}
// Cover entrypublic class Entry { public BlockFluidEntry getEntry(); // Block to place public int getOffset(); // Vertical offset}Fluid Levels
Section titled “Fluid Levels”Caves can be filled with fluids:
// Located in CaveType.FluidLevel
public class FluidLevel { public static final FluidLevel EMPTY; // No fluid
public BlockFluidEntry getBlockEntry(); // Fluid block type public int getHeight(); // Fill height}Custom Cave Implementation
Section titled “Custom Cave Implementation”Creating a Custom CaveType
Section titled “Creating a Custom CaveType”import com.hypixel.hytale.server.worldgen.cave.CaveType;
CaveType customCave = new CaveType( "MyCustomCave", // name entryNodeType, // Entry node configuration yawRange, // Random yaw range pitchRange, // Random pitch range depthRange, // Cave depth range heightFactors, // Height-based scaling pointGenerator, // Entry point distribution biomeMask, // Valid biomes blockMask, // Valid entry blocks mapCondition, // 2D entry condition heightCondition, // 3D height condition fixedEntryHeight, // Optional: fixed height fixedEntryHeightNoise, // Optional: height noise fluidLevel, // Fluid configuration environment, // Environment ID false, // surfaceLimited false, // submerge 1000.0 // maximumSize);Creating a Custom CaveNodeType
Section titled “Creating a Custom CaveNodeType”import com.hypixel.hytale.server.worldgen.cave.CaveNodeType;
CaveNodeType nodeType = new CaveNodeType( "MyNode", // name prefabContainer, // Optional: prefabs in node fillingsMap, // Block fillings (weighted) shapeGenerator, // Shape generator function heightCondition, // Height constraints childrenCountBounds, // Optional: child limit covers, // Floor/ceiling decorations 100, // priority environment // environment ID);
// Set children after creation (for circular references)nodeType.setChildren(childEntries);Creating a Custom Shape Generator
Section titled “Creating a Custom Shape Generator”import com.hypixel.hytale.server.worldgen.cave.shape.CaveNodeShapeEnum;
CaveNodeShapeEnum.CaveNodeShapeGenerator shapeGen = (random, caveType, parent, childEntry, origin, yaw, pitch) -> { // Generate and return custom CaveNodeShape return new MyCustomShape(origin, yaw, pitch, /* ... */); };Best Practices
Section titled “Best Practices”Cave Design
Section titled “Cave Design”- Balance depth and complexity - Deeper caves = more nodes = more CPU time
- Use appropriate shapes - Match shape to cave type (tunnels vs caverns)
- Test biome masks - Ensure caves generate in intended biomes
- Set reasonable priorities - Control carving order for overlapping features
- Consider fluid levels - Water/lava adds visual interest but affects gameplay
Performance
Section titled “Performance”- Limit maximum size - Large caves affect many chunks
- Control child count - Exponential growth with depth
- Optimize prefab placement - Reduce iteration counts
- Use chunk bounds efficiently - Minimize chunk overlap
- Profile generation time - Monitor expensive operations
Integration
Section titled “Integration”- Coordinate with biomes - Use biome masks appropriately
- Respect zone boundaries - Consider zone-specific cave types
- Match environment IDs - Consistent with biome/zone environment
- Test height constraints - Ensure caves generate at intended depths
- Verify block masks - Caves should start in solid terrain
Debugging
Section titled “Debugging”- Use descriptive names - Easier to identify in logs
- Test with fixed seeds - Reproducible generation
- Visualize bounds - Check cave extent calculations
- Monitor node counts - Detect runaway generation
- Validate prefab placement - Ensure conditions work as expected