239 lines
5.6 KiB
Markdown
239 lines
5.6 KiB
Markdown
---
|
|
title: Climate & Biomes
|
|
type: docs
|
|
weight: 3
|
|
---
|
|
|
|
The climate and biome system determines biome distribution across the world based on temperature, humidity, and other factors.
|
|
|
|
**Package:** `com.hypixel.hytale.server.worldgen.climate`
|
|
|
|
## Climate System
|
|
|
|
The `ClimateGenerator` creates climate maps:
|
|
|
|
```java
|
|
public class ClimateGenerator {
|
|
// Get temperature at position
|
|
public float getTemperature(int x, int z);
|
|
|
|
// Get humidity at position
|
|
public float getHumidity(int x, int z);
|
|
|
|
// Get altitude factor
|
|
public float getAltitude(int x, int y, int z);
|
|
|
|
// Get climate data
|
|
public ClimateData getClimate(int x, int z);
|
|
}
|
|
```
|
|
|
|
## ClimateData
|
|
|
|
```java
|
|
public class ClimateData {
|
|
private float temperature; // -1.0 (cold) to 1.0 (hot)
|
|
private float humidity; // 0.0 (dry) to 1.0 (wet)
|
|
private float altitude; // Normalized height
|
|
private float continentality; // Distance from ocean
|
|
|
|
public Biome getBiome();
|
|
}
|
|
```
|
|
|
|
## Biome Selection
|
|
|
|
Biomes are selected based on climate parameters:
|
|
|
|
```java
|
|
public class BiomeSelector {
|
|
private Map<BiomeCondition, Biome> biomeMap;
|
|
|
|
public Biome selectBiome(ClimateData climate) {
|
|
for (Map.Entry<BiomeCondition, Biome> entry : biomeMap.entrySet()) {
|
|
if (entry.getKey().matches(climate)) {
|
|
return entry.getValue();
|
|
}
|
|
}
|
|
return defaultBiome;
|
|
}
|
|
}
|
|
|
|
public class BiomeCondition {
|
|
private Range temperatureRange;
|
|
private Range humidityRange;
|
|
private Range altitudeRange;
|
|
|
|
public boolean matches(ClimateData climate) {
|
|
return temperatureRange.contains(climate.temperature)
|
|
&& humidityRange.contains(climate.humidity)
|
|
&& altitudeRange.contains(climate.altitude);
|
|
}
|
|
}
|
|
```
|
|
|
|
## Biome Definition
|
|
|
|
```yaml
|
|
# biomes/forest.yaml
|
|
Type: Biome
|
|
Id: forest
|
|
DisplayName: "Forest"
|
|
Climate:
|
|
Temperature: [0.3, 0.7]
|
|
Humidity: [0.4, 0.8]
|
|
Terrain:
|
|
SurfaceBlock: grass
|
|
SubsurfaceBlock: dirt
|
|
StoneBlock: stone
|
|
Features:
|
|
- Type: Tree
|
|
Density: 0.3
|
|
Variants: [oak, birch]
|
|
- Type: Grass
|
|
Density: 0.8
|
|
- Type: Flower
|
|
Density: 0.1
|
|
Mobs:
|
|
- Type: deer
|
|
SpawnWeight: 10
|
|
- Type: rabbit
|
|
SpawnWeight: 20
|
|
AmbientSounds:
|
|
- birds
|
|
- wind_leaves
|
|
```
|
|
|
|
## Temperature Zones
|
|
|
|
```java
|
|
public enum TemperatureZone {
|
|
FROZEN(-1.0f, -0.5f), // Ice, snow
|
|
COLD(-0.5f, 0.0f), // Taiga, tundra
|
|
TEMPERATE(0.0f, 0.5f), // Forest, plains
|
|
WARM(0.5f, 0.8f), // Savanna, jungle
|
|
HOT(0.8f, 1.0f); // Desert, volcanic
|
|
|
|
private float min;
|
|
private float max;
|
|
}
|
|
```
|
|
|
|
## Humidity Zones
|
|
|
|
```java
|
|
public enum HumidityZone {
|
|
ARID(0.0f, 0.2f), // Desert
|
|
DRY(0.2f, 0.4f), // Savanna, steppe
|
|
MODERATE(0.4f, 0.6f), // Plains, forest
|
|
HUMID(0.6f, 0.8f), // Jungle, swamp
|
|
WET(0.8f, 1.0f); // Rainforest, marsh
|
|
}
|
|
```
|
|
|
|
## Biome Blending
|
|
|
|
Smooth transitions between biomes:
|
|
|
|
```java
|
|
public class BiomeBlender {
|
|
private int blendRadius;
|
|
|
|
public BiomeBlendData blend(int x, int z) {
|
|
Map<Biome, Float> weights = new HashMap<>();
|
|
|
|
// Sample surrounding biomes
|
|
for (int dx = -blendRadius; dx <= blendRadius; dx++) {
|
|
for (int dz = -blendRadius; dz <= blendRadius; dz++) {
|
|
Biome biome = getBiome(x + dx, z + dz);
|
|
float distance = (float) Math.sqrt(dx * dx + dz * dz);
|
|
float weight = 1.0f / (1.0f + distance);
|
|
weights.merge(biome, weight, Float::sum);
|
|
}
|
|
}
|
|
|
|
return new BiomeBlendData(weights);
|
|
}
|
|
}
|
|
```
|
|
|
|
## Climate Noise
|
|
|
|
```java
|
|
public class ClimateNoiseGenerator {
|
|
private SimplexNoise temperatureNoise;
|
|
private SimplexNoise humidityNoise;
|
|
|
|
public ClimateNoiseGenerator(long seed) {
|
|
temperatureNoise = new SimplexNoise(seed);
|
|
humidityNoise = new SimplexNoise(seed + 1);
|
|
}
|
|
|
|
public float getTemperature(int x, int z) {
|
|
// Large scale temperature variation
|
|
float base = temperatureNoise.noise2D(x * 0.001f, z * 0.001f);
|
|
// Small scale variation
|
|
float detail = temperatureNoise.noise2D(x * 0.01f, z * 0.01f) * 0.2f;
|
|
return base + detail;
|
|
}
|
|
|
|
public float getHumidity(int x, int z) {
|
|
return humidityNoise.noise2D(x * 0.002f, z * 0.002f);
|
|
}
|
|
}
|
|
```
|
|
|
|
## Altitude Effects
|
|
|
|
```java
|
|
public class AltitudeClimateModifier {
|
|
// Temperature decreases with altitude
|
|
public float modifyTemperature(float baseTemp, int altitude) {
|
|
float altitudeFactor = altitude / 256.0f;
|
|
return baseTemp - (altitudeFactor * 0.5f);
|
|
}
|
|
|
|
// Humidity varies with altitude
|
|
public float modifyHumidity(float baseHumidity, int altitude) {
|
|
if (altitude < 64) {
|
|
return baseHumidity * 1.2f; // More humid at low altitudes
|
|
} else if (altitude > 128) {
|
|
return baseHumidity * 0.6f; // Drier at high altitudes
|
|
}
|
|
return baseHumidity;
|
|
}
|
|
}
|
|
```
|
|
|
|
## Configuration
|
|
|
|
```yaml
|
|
# worldgen/climate_config.yaml
|
|
Climate:
|
|
NoiseScale: 0.001
|
|
TemperatureRange: [-1.0, 1.0]
|
|
HumidityRange: [0.0, 1.0]
|
|
BlendRadius: 8
|
|
AltitudeEffect: true
|
|
Biomes:
|
|
- Id: forest
|
|
Temperature: [0.3, 0.7]
|
|
Humidity: [0.4, 0.8]
|
|
- Id: desert
|
|
Temperature: [0.7, 1.0]
|
|
Humidity: [0.0, 0.3]
|
|
- Id: tundra
|
|
Temperature: [-1.0, -0.3]
|
|
Humidity: [0.2, 0.6]
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
{{< callout type="info" >}}
|
|
**Climate Guidelines:**
|
|
- Use smooth noise for natural climate transitions
|
|
- Consider altitude when determining biomes
|
|
- Blend biomes for seamless transitions
|
|
- Test biome distribution across large areas
|
|
{{< /callout >}}
|