Biomes
Reading Biomes
Section titled “Reading Biomes”Current Player Biome
Section titled “Current Player Biome”The simplest way to get a player’s current biome:
Player player = store.getComponent(ref, Player.getComponentType());WorldMapTracker tracker = player.getWorldMapTracker();
String biomeName = tracker.getCurrentBiomeName(); // e.g. "Forest"
// zone info is a record, not a plain stringWorldMapTracker.ZoneDiscoveryInfo zone = tracker.getCurrentZone();String zoneName = zone != null ? zone.zoneName() : null;The tracker updates approximately once per second. Biome and zone names are strings derived from JSON filenames.
Biome at a Position
Section titled “Biome at a Position”To query the biome at an arbitrary position, access the chunk generator directly:
IWorldGen gen = world.getChunkStore().getGenerator();if (gen instanceof ChunkGenerator chunkGen) { int seed = (int) world.getWorldConfig().getSeed(); ZoneBiomeResult result = chunkGen.getZoneBiomeResultAt(seed, x, z); Biome biome = result.getBiome(); String name = biome.getName(); int mapColor = biome.getMapColor();}This computes the biome from the world seed and position — it does not read stored data. The result is the same every time for the same coordinates.
Zone and Biome Hierarchy
Section titled “Zone and Biome Hierarchy”World generation uses a Zone > Biome hierarchy:
- Zones are large regions (similar to Minecraft biome groups). Each zone has its own set of biomes.
- Tile biomes are the primary biomes within a zone, selected by cell noise with weighted probabilities.
- Custom biomes are sub-biomes that conditionally overlay tile biomes when noise conditions are met (e.g., a “River” replacing parts of “Plains”).
Biomes blend at boundaries using an interpolation radius (0-5 blocks), producing smooth transitions in terrain height and tint color.
Biome IDs
Section titled “Biome IDs”Biomes are identified by:
- String name — derived from the JSON filename (e.g.,
Tile.Forest.json->"Forest") - Integer ID — auto-assigned sequentially at load time (0-32767), not persistent across restarts
There is no global biome registry or enum — biomes exist within the context of their zone.
Biome Tinting
Section titled “Biome Tinting”Biomes define tint colors that affect block appearance (foliage, grass). Each block type has per-face tint percentages:
| JSON Field | Default | Description |
|---|---|---|
BiomeTint | 0 | Sets all faces at once (0-100) |
BiomeTintUp | 0 | Top face override |
BiomeTintDown | 0 | Bottom face override |
BiomeTintNorth | 0 | North face override |
BiomeTintSouth | 0 | South face override |
BiomeTintWest | 0 | West face override |
BiomeTintEast | 0 | East face override |
A value of 100 means fully tinted by the biome color (grass blocks), 0 means unaffected (stone). Tint colors are computed during chunk generation and sent to the client as part of chunk data.
Adding Custom Biomes
Section titled “Adding Custom Biomes”Biomes are defined as JSON files within zone directories. The filename prefix determines the type:
Tile.MyBiome.json— a primary tile biomeCustom.MyBiome.json— a sub-biome that overlays tile biomes
Tile Biome Fields
Section titled “Tile Biome Fields”| Field | Type | Description |
|---|---|---|
Weight | double | Selection probability (default: 1.0) |
SizeModifier | double | Cell size multiplier, squared internally (default: 1.0) |
TerrainHeightThreshold | object | Height threshold function |
Covers | object | Surface cover blocks (grass, flowers) |
Layers | object | Vertical material layers (soil, fill) |
Prefabs | object | Structures that generate in this biome |
Tint | object | Noise-based biome tint color mapping |
Environment | object | Environment ID mapping (water color, lighting) |
Water | object | Water level, block type, fluid type |
Interpolation | object | Boundary blending config with DefaultRadius (0-5, default: 5) and optional per-biome overrides |
MapColor | String | Hex RGB color for the world map (e.g. "0x2D5A1E") |
HeightmapNoise | object | Custom heightmap noise function |
Fade | object | Transition fading at zone borders |
Custom Biome Fields
Section titled “Custom Biome Fields”Custom biomes inherit all tile biome fields and add:
| Field | Type | Description |
|---|---|---|
CustomBiomeGenerator.NoiseMask | object | Noise function + Threshold for placement |
CustomBiomeGenerator.BiomeMask | String[] | Parent biome names this can replace |
CustomBiomeGenerator.Priority | int | Higher priority = checked first |
HytaleGenerator Biomes
Section titled “HytaleGenerator Biomes”The HytaleGenerator plugin has a separate asset-based biome system. Biome assets are loaded from HytaleGenerator/Biomes/ via an AssetStore, supporting the standard asset pack structure with inheritance.
Limitations
Section titled “Limitations”- No
setBiome()— biomes are computed from seed + position, not stored per-block. You cannot change the biome at a location at runtime. - No biome events — only DiscoverZoneEvent.Display fires when a player enters a new zone for the first time (cancellable). There is no event for biome changes.
- No global biome registry — biomes are scoped to their zone. Integer IDs are ephemeral and reassigned on each server start.
- 2D only — biome selection is based on (x, z) coordinates. There are no 3D biomes (unlike Minecraft 1.18+), though environment IDs can vary by height for cave sub-biomes.