feat: add bedrock biome mappings

This commit is contained in:
Alexander Medvedev 2026-07-08 17:30:55 +02:00
parent c82bf52aec
commit 339d9dde5b
6 changed files with 383 additions and 4 deletions

View File

@ -16,3 +16,6 @@ This directory contains a number of different data files used to help support co
- adapted from `GeyserMC/mappings` `items.json`.
- Strips everything except the `bedrock_data` field (making it the value of each corresponding top-level key), omitting any `0` values.
- Most of `items.json` is automatically generated, but that value appears to be manually maintained by the Geyser team. We separate that out for our own use, while keeping the rest generated.
- `biomes.json`
- downloaded from [GeyserMC/mappings](https://github.com/GeyserMC/mappings)
- Maps Java Edition biome identifiers to their corresponding Bedrock Edition biome ID. Used in code generation to translate Java biomes to Bedrock counterparts.

197
assets/bedrock/biomes.json Normal file
View File

@ -0,0 +1,197 @@
{
"minecraft:badlands": {
"bedrock_id": 37
},
"minecraft:bamboo_jungle": {
"bedrock_id": 48
},
"minecraft:basalt_deltas": {
"bedrock_id": 181
},
"minecraft:beach": {
"bedrock_id": 16
},
"minecraft:birch_forest": {
"bedrock_id": 27
},
"minecraft:cherry_grove": {
"bedrock_id": 192
},
"minecraft:cold_ocean": {
"bedrock_id": 44
},
"minecraft:crimson_forest": {
"bedrock_id": 179
},
"minecraft:dark_forest": {
"bedrock_id": 29
},
"minecraft:deep_cold_ocean": {
"bedrock_id": 45
},
"minecraft:deep_dark": {
"bedrock_id": 190
},
"minecraft:deep_frozen_ocean": {
"bedrock_id": 47
},
"minecraft:deep_lukewarm_ocean": {
"bedrock_id": 43
},
"minecraft:deep_ocean": {
"bedrock_id": 24
},
"minecraft:desert": {
"bedrock_id": 2
},
"minecraft:dripstone_caves": {
"bedrock_id": 188
},
"minecraft:end_barrens": {
"bedrock_id": 9
},
"minecraft:end_highlands": {
"bedrock_id": 9
},
"minecraft:end_midlands": {
"bedrock_id": 9
},
"minecraft:eroded_badlands": {
"bedrock_id": 165
},
"minecraft:flower_forest": {
"bedrock_id": 132
},
"minecraft:forest": {
"bedrock_id": 4
},
"minecraft:frozen_ocean": {
"bedrock_id": 46
},
"minecraft:frozen_peaks": {
"bedrock_id": 183
},
"minecraft:frozen_river": {
"bedrock_id": 11
},
"minecraft:grove": {
"bedrock_id": 185
},
"minecraft:ice_spikes": {
"bedrock_id": 140
},
"minecraft:jagged_peaks": {
"bedrock_id": 182
},
"minecraft:jungle": {
"bedrock_id": 21
},
"minecraft:lukewarm_ocean": {
"bedrock_id": 42
},
"minecraft:lush_caves": {
"bedrock_id": 187
},
"minecraft:mangrove_swamp": {
"bedrock_id": 191
},
"minecraft:meadow": {
"bedrock_id": 186
},
"minecraft:mushroom_fields": {
"bedrock_id": 14
},
"minecraft:nether_wastes": {
"bedrock_id": 8
},
"minecraft:ocean": {
"bedrock_id": 0
},
"minecraft:old_growth_birch_forest": {
"bedrock_id": 155
},
"minecraft:old_growth_pine_taiga": {
"bedrock_id": 32
},
"minecraft:old_growth_spruce_taiga": {
"bedrock_id": 160
},
"minecraft:pale_garden": {
"bedrock_id": 193
},
"minecraft:plains": {
"bedrock_id": 1
},
"minecraft:river": {
"bedrock_id": 7
},
"minecraft:savanna": {
"bedrock_id": 35
},
"minecraft:savanna_plateau": {
"bedrock_id": 36
},
"minecraft:small_end_islands": {
"bedrock_id": 9
},
"minecraft:snowy_beach": {
"bedrock_id": 26
},
"minecraft:snowy_plains": {
"bedrock_id": 12
},
"minecraft:snowy_slopes": {
"bedrock_id": 184
},
"minecraft:snowy_taiga": {
"bedrock_id": 30
},
"minecraft:soul_sand_valley": {
"bedrock_id": 178
},
"minecraft:sparse_jungle": {
"bedrock_id": 23
},
"minecraft:stony_peaks": {
"bedrock_id": 189
},
"minecraft:stony_shore": {
"bedrock_id": 25
},
"minecraft:sunflower_plains": {
"bedrock_id": 129
},
"minecraft:swamp": {
"bedrock_id": 6
},
"minecraft:taiga": {
"bedrock_id": 5
},
"minecraft:the_end": {
"bedrock_id": 9
},
"minecraft:the_void": {
"bedrock_id": 7
},
"minecraft:warm_ocean": {
"bedrock_id": 40
},
"minecraft:warped_forest": {
"bedrock_id": 180
},
"minecraft:windswept_forest": {
"bedrock_id": 34
},
"minecraft:windswept_gravelly_hills": {
"bedrock_id": 131
},
"minecraft:windswept_hills": {
"bedrock_id": 3
},
"minecraft:windswept_savanna": {
"bedrock_id": 163
},
"minecraft:wooded_badlands": {
"bedrock_id": 38
}
}

View File

@ -7,6 +7,11 @@ use quote::{format_ident, quote};
use serde::Deserialize;
use syn::LitInt;
#[derive(Deserialize)]
struct GeyserBiomeMapping {
bedrock_id: u8,
}
/// Raw deserialization shape for a single biome entry from `biome.json`.
#[derive(Deserialize)]
pub struct Biome {
@ -214,12 +219,21 @@ pub fn build() -> TokenStream {
let biome_trees: MultiNoiseBiomeSuppliers =
serde_json::from_str(&fs::read_to_string("../assets/multi_noise_biome_tree.json").unwrap())
.expect("Failed to parse multi_noise_biome_tree.json");
let bedrock_biomes: BTreeMap<String, GeyserBiomeMapping> =
serde_json::from_str(&fs::read_to_string("../assets/bedrock/biomes.json").unwrap())
.expect("Failed to parse biomes.json");
let mut variants = TokenStream::new();
let mut name_to_type = TokenStream::new();
let mut id_to_type = TokenStream::new();
for (name, biome) in biomes {
let full_name = format!("minecraft:{name}");
let be_network_id = bedrock_biomes
.get(&full_name)
.map(|mapping| mapping.bedrock_id)
.unwrap_or(1);
// let full_name = format!("minecraft:{name}");
let format_name = format_ident!("{}", name.to_shouty_snake_case());
let has_precipitation = biome.has_precipitation;
@ -327,6 +341,7 @@ pub fn build() -> TokenStream {
pub const #format_name: Biome = Biome {
id: #index,
registry_id: #name,
be_network_id: #be_network_id,
weather: Weather::new(
#has_precipitation,
#temperature,
@ -361,6 +376,7 @@ pub fn build() -> TokenStream {
pub struct Biome {
pub id: u8,
pub registry_id: &'static str,
pub be_network_id: u8,
pub weather: Weather,
// carvers: &'static [&str],
pub features: &'static [&'static [crate::placed_feature::PlacedFeature]],

View File

@ -13,6 +13,7 @@ use std::{
pub struct Biome {
pub id: u8,
pub registry_id: &'static str,
pub be_network_id: u8,
pub weather: Weather,
pub features: &'static [&'static [crate::placed_feature::PlacedFeature]],
pub creature_spawn_probability: f32,
@ -85,6 +86,7 @@ impl Biome {
pub const BADLANDS: Biome = Biome {
id: 0,
registry_id: "badlands",
be_network_id: 37u8,
weather: Weather::new(false, 2f32, TemperatureModifier::None, 0f32),
features: &[
&[],
@ -241,6 +243,7 @@ impl Biome {
pub const BAMBOO_JUNGLE: Biome = Biome {
id: 1,
registry_id: "bamboo_jungle",
be_network_id: 48u8,
weather: Weather::new(true, 0.95f32, TemperatureModifier::None, 0.9f32),
features: &[
&[],
@ -413,6 +416,7 @@ impl Biome {
pub const BASALT_DELTAS: Biome = Biome {
id: 2,
registry_id: "basalt_deltas",
be_network_id: 181u8,
weather: Weather::new(false, 2f32, TemperatureModifier::None, 0f32),
features: &[
&[],
@ -475,6 +479,7 @@ impl Biome {
pub const BEACH: Biome = Biome {
id: 3,
registry_id: "beach",
be_network_id: 16u8,
weather: Weather::new(true, 0.8f32, TemperatureModifier::None, 0.4f32),
features: &[
&[],
@ -606,6 +611,7 @@ impl Biome {
pub const BIRCH_FOREST: Biome = Biome {
id: 4,
registry_id: "birch_forest",
be_network_id: 27u8,
weather: Weather::new(true, 0.6f32, TemperatureModifier::None, 0.6f32),
features: &[
&[],
@ -758,6 +764,7 @@ impl Biome {
pub const CHERRY_GROVE: Biome = Biome {
id: 5,
registry_id: "cherry_grove",
be_network_id: 192u8,
weather: Weather::new(true, 0.5f32, TemperatureModifier::None, 0.8f32),
features: &[
&[],
@ -899,6 +906,7 @@ impl Biome {
pub const COLD_OCEAN: Biome = Biome {
id: 6,
registry_id: "cold_ocean",
be_network_id: 44u8,
weather: Weather::new(true, 0.5f32, TemperatureModifier::None, 0.5f32),
features: &[
&[],
@ -1056,6 +1064,7 @@ impl Biome {
pub const CRIMSON_FOREST: Biome = Biome {
id: 7,
registry_id: "crimson_forest",
be_network_id: 179u8,
weather: Weather::new(false, 2f32, TemperatureModifier::None, 0f32),
features: &[
&[],
@ -1125,6 +1134,7 @@ impl Biome {
pub const DARK_FOREST: Biome = Biome {
id: 8,
registry_id: "dark_forest",
be_network_id: 29u8,
weather: Weather::new(true, 0.7f32, TemperatureModifier::None, 0.8f32),
features: &[
&[],
@ -1276,6 +1286,7 @@ impl Biome {
pub const DEEP_COLD_OCEAN: Biome = Biome {
id: 9,
registry_id: "deep_cold_ocean",
be_network_id: 45u8,
weather: Weather::new(true, 0.5f32, TemperatureModifier::None, 0.5f32),
features: &[
&[],
@ -1433,6 +1444,7 @@ impl Biome {
pub const DEEP_DARK: Biome = Biome {
id: 10,
registry_id: "deep_dark",
be_network_id: 190u8,
weather: Weather::new(true, 0.8f32, TemperatureModifier::None, 0.4f32),
features: &[
&[],
@ -1508,6 +1520,7 @@ impl Biome {
pub const DEEP_FROZEN_OCEAN: Biome = Biome {
id: 11,
registry_id: "deep_frozen_ocean",
be_network_id: 47u8,
weather: Weather::new(true, 0.5f32, TemperatureModifier::Frozen, 0.5f32),
features: &[
&[],
@ -1664,6 +1677,7 @@ impl Biome {
pub const DEEP_LUKEWARM_OCEAN: Biome = Biome {
id: 12,
registry_id: "deep_lukewarm_ocean",
be_network_id: 43u8,
weather: Weather::new(true, 0.5f32, TemperatureModifier::None, 0.5f32),
features: &[
&[],
@ -1831,6 +1845,7 @@ impl Biome {
pub const DEEP_OCEAN: Biome = Biome {
id: 13,
registry_id: "deep_ocean",
be_network_id: 24u8,
weather: Weather::new(true, 0.5f32, TemperatureModifier::None, 0.5f32),
features: &[
&[],
@ -1986,6 +2001,7 @@ impl Biome {
pub const DESERT: Biome = Biome {
id: 14,
registry_id: "desert",
be_network_id: 2u8,
weather: Weather::new(false, 2f32, TemperatureModifier::None, 0f32),
features: &[
&[],
@ -2138,6 +2154,7 @@ impl Biome {
pub const DRIPSTONE_CAVES: Biome = Biome {
id: 15,
registry_id: "dripstone_caves",
be_network_id: 188u8,
weather: Weather::new(true, 0.8f32, TemperatureModifier::None, 0.4f32),
features: &[
&[],
@ -2276,6 +2293,7 @@ impl Biome {
pub const END_BARRENS: Biome = Biome {
id: 16,
registry_id: "end_barrens",
be_network_id: 9u8,
weather: Weather::new(false, 0.5f32, TemperatureModifier::None, 0.5f32),
features: &[],
creature_spawn_probability: 0.1f32,
@ -2298,6 +2316,7 @@ impl Biome {
pub const END_HIGHLANDS: Biome = Biome {
id: 17,
registry_id: "end_highlands",
be_network_id: 9u8,
weather: Weather::new(false, 0.5f32, TemperatureModifier::None, 0.5f32),
features: &[
&[],
@ -2331,6 +2350,7 @@ impl Biome {
pub const END_MIDLANDS: Biome = Biome {
id: 18,
registry_id: "end_midlands",
be_network_id: 9u8,
weather: Weather::new(false, 0.5f32, TemperatureModifier::None, 0.5f32),
features: &[],
creature_spawn_probability: 0.1f32,
@ -2353,6 +2373,7 @@ impl Biome {
pub const ERODED_BADLANDS: Biome = Biome {
id: 19,
registry_id: "eroded_badlands",
be_network_id: 165u8,
weather: Weather::new(false, 2f32, TemperatureModifier::None, 0f32),
features: &[
&[],
@ -2509,6 +2530,7 @@ impl Biome {
pub const FLOWER_FOREST: Biome = Biome {
id: 20,
registry_id: "flower_forest",
be_network_id: 132u8,
weather: Weather::new(true, 0.7f32, TemperatureModifier::None, 0.8f32),
features: &[
&[],
@ -2664,6 +2686,7 @@ impl Biome {
pub const FOREST: Biome = Biome {
id: 21,
registry_id: "forest",
be_network_id: 4u8,
weather: Weather::new(true, 0.7f32, TemperatureModifier::None, 0.8f32),
features: &[
&[],
@ -2820,6 +2843,7 @@ impl Biome {
pub const FROZEN_OCEAN: Biome = Biome {
id: 22,
registry_id: "frozen_ocean",
be_network_id: 46u8,
weather: Weather::new(true, 0f32, TemperatureModifier::Frozen, 0.5f32),
features: &[
&[],
@ -2976,6 +3000,7 @@ impl Biome {
pub const FROZEN_PEAKS: Biome = Biome {
id: 23,
registry_id: "frozen_peaks",
be_network_id: 183u8,
weather: Weather::new(true, -0.7f32, TemperatureModifier::None, 0.9f32),
features: &[
&[],
@ -3100,6 +3125,7 @@ impl Biome {
pub const FROZEN_RIVER: Biome = Biome {
id: 24,
registry_id: "frozen_river",
be_network_id: 11u8,
weather: Weather::new(true, 0f32, TemperatureModifier::None, 0.5f32),
features: &[
&[],
@ -3242,6 +3268,7 @@ impl Biome {
pub const GROVE: Biome = Biome {
id: 25,
registry_id: "grove",
be_network_id: 185u8,
weather: Weather::new(true, -0.2f32, TemperatureModifier::None, 0.8f32),
features: &[
&[],
@ -3382,6 +3409,7 @@ impl Biome {
pub const ICE_SPIKES: Biome = Biome {
id: 26,
registry_id: "ice_spikes",
be_network_id: 140u8,
weather: Weather::new(true, 0f32, TemperatureModifier::None, 0.5f32),
features: &[
&[],
@ -3529,6 +3557,7 @@ impl Biome {
pub const JAGGED_PEAKS: Biome = Biome {
id: 27,
registry_id: "jagged_peaks",
be_network_id: 182u8,
weather: Weather::new(true, -0.7f32, TemperatureModifier::None, 0.9f32),
features: &[
&[],
@ -3653,6 +3682,7 @@ impl Biome {
pub const JUNGLE: Biome = Biome {
id: 28,
registry_id: "jungle",
be_network_id: 21u8,
weather: Weather::new(true, 0.95f32, TemperatureModifier::None, 0.9f32),
features: &[
&[],
@ -3825,6 +3855,7 @@ impl Biome {
pub const LUKEWARM_OCEAN: Biome = Biome {
id: 29,
registry_id: "lukewarm_ocean",
be_network_id: 42u8,
weather: Weather::new(true, 0.5f32, TemperatureModifier::None, 0.5f32),
features: &[
&[],
@ -3992,6 +4023,7 @@ impl Biome {
pub const LUSH_CAVES: Biome = Biome {
id: 30,
registry_id: "lush_caves",
be_network_id: 187u8,
weather: Weather::new(true, 0.5f32, TemperatureModifier::None, 0.5f32),
features: &[
&[],
@ -4129,6 +4161,7 @@ impl Biome {
pub const MANGROVE_SWAMP: Biome = Biome {
id: 31,
registry_id: "mangrove_swamp",
be_network_id: 191u8,
weather: Weather::new(true, 0.8f32, TemperatureModifier::None, 0.9f32),
features: &[
&[],
@ -4274,6 +4307,7 @@ impl Biome {
pub const MEADOW: Biome = Biome {
id: 32,
registry_id: "meadow",
be_network_id: 186u8,
weather: Weather::new(true, 0.5f32, TemperatureModifier::None, 0.8f32),
features: &[
&[],
@ -4416,6 +4450,7 @@ impl Biome {
pub const MUSHROOM_FIELDS: Biome = Biome {
id: 33,
registry_id: "mushroom_fields",
be_network_id: 14u8,
weather: Weather::new(true, 0.9f32, TemperatureModifier::None, 1f32),
features: &[
&[],
@ -4504,6 +4539,7 @@ impl Biome {
pub const NETHER_WASTES: Biome = Biome {
id: 34,
registry_id: "nether_wastes",
be_network_id: 8u8,
weather: Weather::new(false, 2f32, TemperatureModifier::None, 0f32),
features: &[
&[],
@ -4583,6 +4619,7 @@ impl Biome {
pub const OCEAN: Biome = Biome {
id: 35,
registry_id: "ocean",
be_network_id: 0u8,
weather: Weather::new(true, 0.5f32, TemperatureModifier::None, 0.5f32),
features: &[
&[],
@ -4738,6 +4775,7 @@ impl Biome {
pub const OLD_GROWTH_BIRCH_FOREST: Biome = Biome {
id: 36,
registry_id: "old_growth_birch_forest",
be_network_id: 155u8,
weather: Weather::new(true, 0.6f32, TemperatureModifier::None, 0.6f32),
features: &[
&[],
@ -4890,6 +4928,7 @@ impl Biome {
pub const OLD_GROWTH_PINE_TAIGA: Biome = Biome {
id: 37,
registry_id: "old_growth_pine_taiga",
be_network_id: 32u8,
weather: Weather::new(true, 0.3f32, TemperatureModifier::None, 0.8f32),
features: &[
&[],
@ -5062,6 +5101,7 @@ impl Biome {
pub const OLD_GROWTH_SPRUCE_TAIGA: Biome = Biome {
id: 38,
registry_id: "old_growth_spruce_taiga",
be_network_id: 160u8,
weather: Weather::new(true, 0.25f32, TemperatureModifier::None, 0.8f32),
features: &[
&[],
@ -5234,6 +5274,7 @@ impl Biome {
pub const PALE_GARDEN: Biome = Biome {
id: 39,
registry_id: "pale_garden",
be_network_id: 193u8,
weather: Weather::new(true, 0.7f32, TemperatureModifier::None, 0.8f32),
features: &[
&[],
@ -5362,6 +5403,7 @@ impl Biome {
pub const PLAINS: Biome = Biome {
id: 40,
registry_id: "plains",
be_network_id: 1u8,
weather: Weather::new(true, 0.8f32, TemperatureModifier::None, 0.4f32),
features: &[
&[],
@ -5528,6 +5570,7 @@ impl Biome {
pub const RIVER: Biome = Biome {
id: 41,
registry_id: "river",
be_network_id: 7u8,
weather: Weather::new(true, 0.5f32, TemperatureModifier::None, 0.5f32),
features: &[
&[],
@ -5671,6 +5714,7 @@ impl Biome {
pub const SAVANNA: Biome = Biome {
id: 42,
registry_id: "savanna",
be_network_id: 35u8,
weather: Weather::new(false, 2f32, TemperatureModifier::None, 0f32),
features: &[
&[],
@ -5841,6 +5885,7 @@ impl Biome {
pub const SAVANNA_PLATEAU: Biome = Biome {
id: 43,
registry_id: "savanna_plateau",
be_network_id: 36u8,
weather: Weather::new(false, 2f32, TemperatureModifier::None, 0f32),
features: &[
&[],
@ -6021,6 +6066,7 @@ impl Biome {
pub const SMALL_END_ISLANDS: Biome = Biome {
id: 44,
registry_id: "small_end_islands",
be_network_id: 9u8,
weather: Weather::new(false, 0.5f32, TemperatureModifier::None, 0.5f32),
features: &[&[crate::placed_feature::PlacedFeature::EndIslandDecorated]],
creature_spawn_probability: 0.1f32,
@ -6043,6 +6089,7 @@ impl Biome {
pub const SNOWY_BEACH: Biome = Biome {
id: 45,
registry_id: "snowy_beach",
be_network_id: 26u8,
weather: Weather::new(true, 0.05f32, TemperatureModifier::None, 0.3f32),
features: &[
&[],
@ -6170,6 +6217,7 @@ impl Biome {
pub const SNOWY_PLAINS: Biome = Biome {
id: 46,
registry_id: "snowy_plains",
be_network_id: 12u8,
weather: Weather::new(true, 0f32, TemperatureModifier::None, 0.5f32),
features: &[
&[],
@ -6319,6 +6367,7 @@ impl Biome {
pub const SNOWY_SLOPES: Biome = Biome {
id: 47,
registry_id: "snowy_slopes",
be_network_id: 184u8,
weather: Weather::new(true, -0.3f32, TemperatureModifier::None, 0.9f32),
features: &[
&[],
@ -6453,6 +6502,7 @@ impl Biome {
pub const SNOWY_TAIGA: Biome = Biome {
id: 48,
registry_id: "snowy_taiga",
be_network_id: 30u8,
weather: Weather::new(true, -0.5f32, TemperatureModifier::None, 0.4f32),
features: &[
&[],
@ -6619,6 +6669,7 @@ impl Biome {
pub const SOUL_SAND_VALLEY: Biome = Biome {
id: 49,
registry_id: "soul_sand_valley",
be_network_id: 178u8,
weather: Weather::new(false, 2f32, TemperatureModifier::None, 0f32),
features: &[
&[],
@ -6684,6 +6735,7 @@ impl Biome {
pub const SPARSE_JUNGLE: Biome = Biome {
id: 50,
registry_id: "sparse_jungle",
be_network_id: 23u8,
weather: Weather::new(true, 0.95f32, TemperatureModifier::None, 0.8f32),
features: &[
&[],
@ -6845,6 +6897,7 @@ impl Biome {
pub const STONY_PEAKS: Biome = Biome {
id: 51,
registry_id: "stony_peaks",
be_network_id: 189u8,
weather: Weather::new(true, 1f32, TemperatureModifier::None, 0.3f32),
features: &[
&[],
@ -6964,6 +7017,7 @@ impl Biome {
pub const STONY_SHORE: Biome = Biome {
id: 52,
registry_id: "stony_shore",
be_network_id: 25u8,
weather: Weather::new(true, 0.2f32, TemperatureModifier::None, 0.3f32),
features: &[
&[],
@ -7091,6 +7145,7 @@ impl Biome {
pub const SULFUR_CAVES: Biome = Biome {
id: 53,
registry_id: "sulfur_caves",
be_network_id: 1u8,
weather: Weather::new(true, 0.8f32, TemperatureModifier::None, 0.4f32),
features: &[
&[],
@ -7218,6 +7273,7 @@ impl Biome {
pub const SUNFLOWER_PLAINS: Biome = Biome {
id: 54,
registry_id: "sunflower_plains",
be_network_id: 129u8,
weather: Weather::new(true, 0.8f32, TemperatureModifier::None, 0.4f32),
features: &[
&[],
@ -7384,6 +7440,7 @@ impl Biome {
pub const SWAMP: Biome = Biome {
id: 55,
registry_id: "swamp",
be_network_id: 6u8,
weather: Weather::new(true, 0.8f32, TemperatureModifier::None, 0.9f32),
features: &[
&[],
@ -7554,6 +7611,7 @@ impl Biome {
pub const TAIGA: Biome = Biome {
id: 56,
registry_id: "taiga",
be_network_id: 5u8,
weather: Weather::new(true, 0.25f32, TemperatureModifier::None, 0.8f32),
features: &[
&[],
@ -7720,6 +7778,7 @@ impl Biome {
pub const THE_END: Biome = Biome {
id: 57,
registry_id: "the_end",
be_network_id: 9u8,
weather: Weather::new(false, 0.5f32, TemperatureModifier::None, 0.5f32),
features: &[
&[],
@ -7754,6 +7813,7 @@ impl Biome {
pub const THE_VOID: Biome = Biome {
id: 58,
registry_id: "the_void",
be_network_id: 7u8,
weather: Weather::new(false, 0.5f32, TemperatureModifier::None, 0.5f32),
features: &[
&[],
@ -7784,6 +7844,7 @@ impl Biome {
pub const WARM_OCEAN: Biome = Biome {
id: 59,
registry_id: "warm_ocean",
be_network_id: 40u8,
weather: Weather::new(true, 0.5f32, TemperatureModifier::None, 0.5f32),
features: &[
&[],
@ -7947,6 +8008,7 @@ impl Biome {
pub const WARPED_FOREST: Biome = Biome {
id: 60,
registry_id: "warped_forest",
be_network_id: 180u8,
weather: Weather::new(false, 2f32, TemperatureModifier::None, 0f32),
features: &[
&[],
@ -8006,6 +8068,7 @@ impl Biome {
pub const WINDSWEPT_FOREST: Biome = Biome {
id: 61,
registry_id: "windswept_forest",
be_network_id: 34u8,
weather: Weather::new(true, 0.2f32, TemperatureModifier::None, 0.3f32),
features: &[
&[],
@ -8162,6 +8225,7 @@ impl Biome {
pub const WINDSWEPT_GRAVELLY_HILLS: Biome = Biome {
id: 62,
registry_id: "windswept_gravelly_hills",
be_network_id: 131u8,
weather: Weather::new(true, 0.2f32, TemperatureModifier::None, 0.3f32),
features: &[
&[],
@ -8318,6 +8382,7 @@ impl Biome {
pub const WINDSWEPT_HILLS: Biome = Biome {
id: 63,
registry_id: "windswept_hills",
be_network_id: 3u8,
weather: Weather::new(true, 0.2f32, TemperatureModifier::None, 0.3f32),
features: &[
&[],
@ -8474,6 +8539,7 @@ impl Biome {
pub const WINDSWEPT_SAVANNA: Biome = Biome {
id: 64,
registry_id: "windswept_savanna",
be_network_id: 163u8,
weather: Weather::new(false, 2f32, TemperatureModifier::None, 0f32),
features: &[
&[],
@ -8643,6 +8709,7 @@ impl Biome {
pub const WOODED_BADLANDS: Biome = Biome {
id: 65,
registry_id: "wooded_badlands",
be_network_id: 38u8,
weather: Weather::new(false, 2f32, TemperatureModifier::None, 0f32),
features: &[
&[],

View File

@ -70,15 +70,39 @@ impl PacketWrite for CLevelChunk<'_> {
}
}
for i in 0..self.chunk.section.count {
let biome_sections = self
.chunk
.section
.biome_sections
.read()
.map_err(|_| Error::other("biome_sections read lock poisoned"))?;
for (i, biome_palette) in biome_sections.iter().enumerate() {
let num_storages = 1;
let y = (i as i8) + min_y_section;
data_write.write_all(&[VERSION, num_storages, y as u8])?;
for _ in 0..num_storages {
1u8.write(data_write)?;
// TODO
VarInt(0).write(data_write)?;
let network_repr = biome_palette.convert_be_network();
(network_repr.bits_per_entry << 1 | 1).write(data_write)?;
for data in network_repr.packed_data {
data.write(data_write)?;
}
match network_repr.palette {
NetworkPalette::Single(id) => {
VarInt(i32::from(id)).write(data_write)?;
}
NetworkPalette::Indirect(palette) => {
VarInt(palette.len() as i32).write(data_write)?;
for id in palette {
VarInt(i32::from(id)).write(data_write)?;
}
}
NetworkPalette::Direct => (),
}
}
}

View File

@ -493,6 +493,78 @@ impl BiomePalette {
}
}
#[must_use]
pub fn convert_be_network(&self) -> BeNetworkSerialization<u8> {
match self {
Self::Homogeneous(registry_id) => BeNetworkSerialization {
bits_per_entry: 0,
palette: NetworkPalette::Single(
pumpkin_data::biome::Biome::from_id(*registry_id)
.map_or(1, |b| b.be_network_id),
),
packed_data: Box::new([]),
},
Self::Heterogeneous(data) => {
let bits_per_entry = encompassing_bits(data.palette.len());
let key_to_index_map: HashMap<_, usize> = data
.palette
.iter()
.enumerate()
.map(|(index, key)| (*key, index))
.collect();
let biomes_per_word = 32 / bits_per_entry;
let volume: usize = 4096;
let expected_word_count = volume.div_ceil(biomes_per_word as usize);
let mut packed_data = Vec::with_capacity(expected_word_count);
let mut current_word: u32 = 0;
let mut current_index_in_word = 0;
for x in 0..16 {
for y in 0..16 {
for z in 0..16 {
let key = self.get(x / 4, z / 4, y / 4);
let key_index = key_to_index_map.get(&key).unwrap();
debug_assert!((1 << bits_per_entry) > *key_index);
current_word |= (*key_index as u32)
<< (bits_per_entry as u32 * current_index_in_word);
current_index_in_word += 1;
if current_index_in_word == biomes_per_word as u32 {
packed_data.push(current_word);
current_word = 0;
current_index_in_word = 0;
}
}
}
}
// Push any remaining bits if the volume isn't a multiple of biomes_per_word
if current_index_in_word > 0 {
packed_data.push(current_word);
}
BeNetworkSerialization {
bits_per_entry,
palette: NetworkPalette::Indirect(
data.palette
.iter()
.map(|&id| {
pumpkin_data::biome::Biome::from_id(id)
.map_or(1, |b| b.be_network_id)
})
.collect::<Vec<_>>()
.into_boxed_slice(),
),
packed_data: packed_data.into_boxed_slice(),
}
}
}
}
#[must_use]
pub fn from_disk_nbt(nbt: ChunkSectionBiomes) -> Self {
let palette = nbt.palette;