resource: codegen biome list

This commit is contained in:
Matthias Schiffer 2024-12-31 13:51:55 +01:00
parent 7b98954c80
commit 8f408e78a0
Signed by: neocturne
GPG key ID: 16EF3F64CB201D9C
3 changed files with 197 additions and 134 deletions

View file

@ -1,137 +1,117 @@
//! Biome data
//!
//! This file is generated using resource/biomes.py, do not edit
use super::*;
use BiomeGrassColorModifier::*;
/// Standard biome specifications
pub const BIOMES: &[(&str, Biome)] = {
use BiomeGrassColorModifier::*;
// Data extracted from Minecraft code decompiled using https://github.com/Hexeption/MCP-Reborn
// We can't use floats in const functions, to temperature and downfall values
// are specified multipled by 100. The underscore is used in place of the decimal point
// of the original values.
#[allow(clippy::zero_prefixed_literal)]
&[
// Overworld
(
"badlands",
Biome::new(2_00, 0_00)
.foliage([158, 129, 77])
.grass([144, 129, 77]),
),
("bamboo_jungle", Biome::new(0_95, 0_90)),
("beach", Biome::new(0_80, 0_40)),
("birch_forest", Biome::new(0_60, 0_60)),
(
"cherry_grove",
Biome::new(0_50, 0_80)
.water([93, 183, 239])
.grass([182, 219, 97])
.foliage([182, 219, 97]),
),
("cold_ocean", Biome::new(0_50, 0_50).water([61, 87, 214])),
("dark_forest", Biome::new(0_70, 0_80).modify(DarkForest)),
(
"deep_cold_ocean",
Biome::new(0_50, 0_50).water([61, 87, 214]),
),
("deep_dark", Biome::new(0_80, 0_40)),
(
"deep_frozen_ocean",
Biome::new(0_50, 0_50).water([57, 56, 201]),
),
(
"deep_lukewarm_ocean",
Biome::new(0_50, 0_50).water([69, 173, 242]),
),
("deep_ocean", Biome::new(0_50, 0_50)),
("desert", Biome::new(2_00, 0_00)),
("dripstone_caves", Biome::new(0_80, 0_40)),
(
"eroded_badlands",
Biome::new(2_00, 0_00)
.foliage([158, 129, 77])
.grass([144, 129, 77]),
),
("flower_forest", Biome::new(0_70, 0_80)),
("forest", Biome::new(0_70, 0_80)),
("frozen_ocean", Biome::new(0_00, 0_50).water([57, 56, 201])),
("frozen_peaks", Biome::new(-0_70, 0_90)),
("frozen_river", Biome::new(0_00, 0_50).water([57, 56, 201])),
("grove", Biome::new(-0_20, 0_80)),
("ice_spikes", Biome::new(0_00, 0_50)),
("jagged_peaks", Biome::new(-0_70, 0_90)),
("jungle", Biome::new(0_95, 0_90)),
(
"lukewarm_ocean",
Biome::new(0_50, 0_50).water([69, 173, 242]),
),
("lush_caves", Biome::new(0_50, 0_50)),
(
"mangrove_swamp",
Biome::new(0_80, 0_90)
.water([58, 122, 106])
.foliage([141, 177, 39])
.modify(Swamp),
),
("meadow", Biome::new(0_50, 0_80).water([14, 78, 207])),
("mushroom_fields", Biome::new(0_90, 1_00)),
("ocean", Biome::new(0_50, 0_50)),
("old_growth_birch_forest", Biome::new(0_60, 0_60)),
("old_growth_pine_taiga", Biome::new(0_30, 0_80)),
("old_growth_spruce_taiga", Biome::new(0_25, 0_80)),
(
"pale_garden",
Biome::new(0_70, 0_80)
.water([118, 136, 157])
.foliage([135, 141, 118])
.grass([119, 130, 114]),
),
("plains", Biome::new(0_80, 0_40)),
("river", Biome::new(0_50, 0_50)),
("savanna", Biome::new(2_00, 0_00)),
("savanna_plateau", Biome::new(2_00, 0_00)),
("snowy_beach", Biome::new(0_05, 0_30).water([61, 87, 214])),
("snowy_plains", Biome::new(0_00, 0_50)),
("snowy_slopes", Biome::new(-0_30, 0_90)),
("snowy_taiga", Biome::new(-0_50, 0_40).water([61, 87, 214])),
("sparse_jungle", Biome::new(0_95, 0_80)),
("stony_peaks", Biome::new(1_00, 0_30)),
("stony_shore", Biome::new(0_20, 0_30)),
("sunflower_plains", Biome::new(0_80, 0_40)),
(
"swamp",
Biome::new(0_80, 0_90)
.water([97, 123, 100])
.foliage([106, 112, 57])
.modify(Swamp),
),
("taiga", Biome::new(0_25, 0_80)),
("the_void", Biome::new(0_50, 0_50)),
("warm_ocean", Biome::new(0_50, 0_50).water([67, 213, 238])),
("windswept_forest", Biome::new(0_20, 0_30)),
("windswept_gravelly_hills", Biome::new(0_20, 0_30)),
("windswept_hills", Biome::new(0_20, 0_30)),
("windswept_savanna", Biome::new(2_00, 0_00)),
(
"wooded_badlands",
Biome::new(2_00, 0_00)
.foliage([158, 129, 77])
.grass([144, 129, 77]),
),
// Nether
("basalt_deltas", Biome::new(2_00, 0_00)),
("crimson_forest", Biome::new(2_00, 0_00)),
("nether_wastes", Biome::new(2_00, 0_00)),
("soul_sand_valley", Biome::new(2_00, 0_00)),
("warped_forest", Biome::new(2_00, 0_00)),
// End
("end_barrens", Biome::new(0_50, 0_50)),
("end_highlands", Biome::new(0_50, 0_50)),
("end_midlands", Biome::new(0_50, 0_50)),
("small_end_islands", Biome::new(0_50, 0_50)),
("the_end", Biome::new(0_50, 0_50)),
]
};
/// List if known biomes and their properties
pub const BIOMES: &[(&str, Biome)] = &[
(
"badlands",
Biome::new(200, 0)
.foliage([158, 129, 77])
.grass([144, 129, 77]),
),
("bamboo_jungle", Biome::new(95, 90)),
("basalt_deltas", Biome::new(200, 0)),
("beach", Biome::new(80, 40)),
("birch_forest", Biome::new(60, 60)),
(
"cherry_grove",
Biome::new(50, 80)
.foliage([182, 219, 97])
.grass([182, 219, 97])
.water([93, 183, 239]),
),
("cold_ocean", Biome::new(50, 50).water([61, 87, 214])),
("crimson_forest", Biome::new(200, 0)),
("dark_forest", Biome::new(70, 80).modify(DarkForest)),
("deep_cold_ocean", Biome::new(50, 50).water([61, 87, 214])),
("deep_dark", Biome::new(80, 40)),
("deep_frozen_ocean", Biome::new(50, 50).water([57, 56, 201])),
(
"deep_lukewarm_ocean",
Biome::new(50, 50).water([69, 173, 242]),
),
("deep_ocean", Biome::new(50, 50)),
("desert", Biome::new(200, 0)),
("dripstone_caves", Biome::new(80, 40)),
("end_barrens", Biome::new(50, 50)),
("end_highlands", Biome::new(50, 50)),
("end_midlands", Biome::new(50, 50)),
(
"eroded_badlands",
Biome::new(200, 0)
.foliage([158, 129, 77])
.grass([144, 129, 77]),
),
("flower_forest", Biome::new(70, 80)),
("forest", Biome::new(70, 80)),
("frozen_ocean", Biome::new(0, 50).water([57, 56, 201])),
("frozen_peaks", Biome::new(-70, 90)),
("frozen_river", Biome::new(0, 50).water([57, 56, 201])),
("grove", Biome::new(-20, 80)),
("ice_spikes", Biome::new(0, 50)),
("jagged_peaks", Biome::new(-70, 90)),
("jungle", Biome::new(95, 90)),
("lukewarm_ocean", Biome::new(50, 50).water([69, 173, 242])),
("lush_caves", Biome::new(50, 50)),
(
"mangrove_swamp",
Biome::new(80, 90)
.foliage([141, 177, 39])
.modify(Swamp)
.water([58, 122, 106]),
),
("meadow", Biome::new(50, 80).water([14, 78, 207])),
("mushroom_fields", Biome::new(90, 100)),
("nether_wastes", Biome::new(200, 0)),
("ocean", Biome::new(50, 50)),
("old_growth_birch_forest", Biome::new(60, 60)),
("old_growth_pine_taiga", Biome::new(30, 80)),
("old_growth_spruce_taiga", Biome::new(25, 80)),
(
"pale_garden",
Biome::new(70, 80)
.foliage([135, 141, 118])
.grass([119, 130, 114])
.water([118, 136, 157]),
),
("plains", Biome::new(80, 40)),
("river", Biome::new(50, 50)),
("savanna", Biome::new(200, 0)),
("savanna_plateau", Biome::new(200, 0)),
("small_end_islands", Biome::new(50, 50)),
("snowy_beach", Biome::new(5, 30).water([61, 87, 214])),
("snowy_plains", Biome::new(0, 50)),
("snowy_slopes", Biome::new(-30, 90)),
("snowy_taiga", Biome::new(-50, 40).water([61, 87, 214])),
("soul_sand_valley", Biome::new(200, 0)),
("sparse_jungle", Biome::new(95, 80)),
("stony_peaks", Biome::new(100, 30)),
("stony_shore", Biome::new(20, 30)),
("sunflower_plains", Biome::new(80, 40)),
(
"swamp",
Biome::new(80, 90)
.foliage([106, 112, 57])
.modify(Swamp)
.water([97, 123, 100]),
),
("taiga", Biome::new(25, 80)),
("the_end", Biome::new(50, 50)),
("the_void", Biome::new(50, 50)),
("warm_ocean", Biome::new(50, 50).water([67, 213, 238])),
("warped_forest", Biome::new(200, 0)),
("windswept_forest", Biome::new(20, 30)),
("windswept_gravelly_hills", Biome::new(20, 30)),
("windswept_hills", Biome::new(20, 30)),
("windswept_savanna", Biome::new(200, 0)),
(
"wooded_badlands",
Biome::new(200, 0)
.foliage([158, 129, 77])
.grass([144, 129, 77]),
),
];

View file

@ -11,13 +11,15 @@ work.
- `extract.py`: Takes the block type information from `blocks.json` and texture data
from an unpacked Minecraft JAR, storing the result in `colors.json`
- `generate.py`: Generates `block_types.rs` from `colors.json`
- `biomes.py`: Generates `biomes.rs` from biome JSON files of an unpacked
Minecraft JAR
- `sign_textures.py`: Generates all needed sign graphics from Minecraft assets
In addition to these scripts, the JSON processor *jq* is a useful tool to work
with MinedMap's resource metadata.
## How to add support for block IDs of a new Minecraft version
## How to add support for block IDs and biomes of a new Minecraft version
1. Download the Minecraft version you want to support as well as the previous
version currently supported by MinedMap. You can use the Minecraft launcher
@ -69,6 +71,17 @@ with MinedMap's resource metadata.
cargo fmt --all
```
8. Update the source code for new biome data:
```sh
./biomes.py data/new ../crates/resource/src/biomes.rs
cargo fmt --all
```
After regenerating, check if only new biomes were added. If entries
got removed, biomes may have been renamed or merged, requiring updates
to the alias list in `crates/resource/src/legacy_biomes.rs`.
After the update, the new version should be tested with old savegames (both
before and after migration by the new version) as well as newly generated
worlds. Use creative mode to add the new block types to your test world.

70
resource/biomes.py Executable file
View file

@ -0,0 +1,70 @@
#!/usr/bin/env python3
import json
import os
import sys
if len(sys.argv) != 3:
sys.exit('Usage: biomes.py <data directory> <biomes.rs>')
biomes = {}
for file in os.scandir(os.path.join(sys.argv[1], 'data/minecraft/worldgen/biome')):
(name, ext) = os.path.splitext(file.name)
if ext != '.json':
continue
with open(file) as f:
data = json.load(f)
biomes[name] = {
'downfall': data['downfall'],
'temperature': data['temperature'],
'foliage_color': data['effects'].get('foliage_color'),
'grass_color': data['effects'].get('grass_color'),
'grass_color_modifier': data['effects'].get('grass_color_modifier'),
'water_color': data['effects'].get('water_color'),
}
def color(v):
return f'[{v>>16}, {(v>>8)&0xff}, {v&0xff}]'
# Converts the snake_case grass color modifier to CamelCase
def modify(v):
return ''.join([s.capitalize() for s in v.split('_')])
def gen_biome(name, info, f):
temp = round(100*info['temperature'])
downfall = round(100*info['downfall'])
foliage_color = info['foliage_color']
grass_color = info['grass_color']
grass_color_modifier = info['grass_color_modifier']
water_color = info['water_color']
print(f'\t("{name}", Biome::new({temp}, {downfall})', file=f)
if foliage_color is not None:
print(f'\t\t.foliage({color(foliage_color)})', file=f)
if grass_color is not None:
print(f'\t\t.grass({color(grass_color)})', file=f)
if grass_color_modifier is not None:
print(f'\t\t.modify({modify(grass_color_modifier)})', file=f)
if water_color is not None and water_color != 0x3f76e4:
print(f'\t\t.water({color(water_color)})', file=f)
print('\t),', file=f)
with open(sys.argv[2], 'w') as f:
print('//! Biome data', file=f);
print('//!', file=f);
print('//! This file is generated using resource/biomes.py, do not edit', file=f);
print('', file=f)
print('use super::*;', file=f)
print('use BiomeGrassColorModifier::*;', file=f)
print('', file=f)
print('/// List if known biomes and their properties', file=f);
print('pub const BIOMES: &[(&str, Biome)] = &[', file=f)
for name in sorted(biomes):
gen_biome(name, biomes[name], f)
print('];', file=f)