diff --git a/CHANGELOG.md b/CHANGELOG.md index ef41795..8c7c159 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] - ReleaseDate +- Added support for Minecraft 1.21.4 block types +- Added support for Minecraft 1.21.4 Pale Garden biome +- viewer: added images for pale oak signs + ## [2.2.0] - 2024-06-23 ### Added diff --git a/Cargo.lock b/Cargo.lock index d32985d..ff64b60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -83,9 +83,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" [[package]] name = "autocfg" @@ -131,9 +131,9 @@ checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bytemuck" -version = "1.20.0" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b37c88a63ffd85d15b406896cc343916d7cf57838a847b3a6f2ca5d39a5695a" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" [[package]] name = "byteorder" @@ -149,9 +149,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "cc" -version = "1.2.4" +version = "1.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9157bbaa6b165880c27a4293a474c91cdcf265cc68cc829bf10be0964a391caf" +checksum = "8d6dbb628b8f8555f86d0323c2eb39e3ec81901f4b83e091db8a6a76d316a333" dependencies = [ "jobserver", "libc", @@ -357,9 +357,9 @@ dependencies = [ [[package]] name = "foldhash" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" +checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" [[package]] name = "futures-core" @@ -514,9 +514,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.168" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libz-ng-sys" @@ -627,9 +627,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" dependencies = [ "adler2", "simd-adler32", @@ -675,9 +675,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.5" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] @@ -737,9 +737,9 @@ checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "png" -version = "0.17.15" +version = "0.17.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67582bd5b65bdff614270e2ea89a1cf15bef71245cc1e5f7ea126977144211d" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" dependencies = [ "bitflags 1.3.2", "crc32fast", @@ -759,9 +759,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -863,9 +863,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.216" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] @@ -881,9 +881,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.216" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", @@ -892,9 +892,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.133" +version = "1.0.134" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" dependencies = [ "itoa", "memchr", @@ -946,9 +946,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.90" +version = "2.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +checksum = "9c786062daee0d6db1132800e623df74274a0a87322d8e183338e01b3d98d058" dependencies = [ "proc-macro2", "quote", diff --git a/README.md b/README.md index 2312c03..4c684f9 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ * Render beautiful maps of your [Minecraft](https://minecraft.net/) worlds! * Put them on a webserver and view them in your browser! -* Compatible with unmodified Minecraft Java Edition 1.8 up to 1.21 (no mod installation necessary!) +* Compatible with unmodified Minecraft Java Edition 1.8 up to 1.21.4 (no mod installation required!) * Illumination layer: the world at night * Fast: create a full map for a huge 3GB savegame in less than 5 minutes in single-threaded operation * Multi-threading support: pass `-j N` to the renderer to use `N` parallel threads for generation diff --git a/crates/resource/src/biomes.rs b/crates/resource/src/biomes.rs index 61f8339..55c5e74 100644 --- a/crates/resource/src/biomes.rs +++ b/crates/resource/src/biomes.rs @@ -1,437 +1,117 @@ -//! Biome data structures +//! Biome data +//! +//! This file is generated using resource/biomes.py, do not edit -use serde::{Deserialize, Serialize}; +use super::*; +use BiomeGrassColorModifier::*; -use super::Color; - -/// Grass color modifier used by a biome -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum BiomeGrassColorModifier { - /// Grass color modifier used by the dark forest biome - DarkForest, - /// Grass color modifier used by swamp biomes - Swamp, -} - -/// A biome specification -/// -/// A Biome contains all information about a biome necessary to compute a block -/// color given a block type and depth -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct Biome { - /// Temperature value - /// - /// For more efficient storage, the temperature is stored as an integer - /// after mutiplying the raw value by 20 - pub temp: i8, - /// Downfall value - /// - /// For more efficient storage, the downfall is stored as an integer - /// after mutiplying the raw value by 20 - pub downfall: i8, - /// Water color override - pub water_color: Option, - /// Foliage color override - pub foliage_color: Option, - /// Grass color override - pub grass_color: Option, - /// Grass color modifier - pub grass_color_modifier: Option, -} - -impl Biome { - /// Constructs a new Biome - const fn new(temp: i16, downfall: i16) -> Biome { - /// Helper to encode temperature and downfall values - /// - /// Converts temperatue and downfall from the input format - /// (mutiplied by 100) to i8 range for more efficient storage. - const fn encode(v: i16) -> i8 { - (v / 5) as i8 - } - Biome { - temp: encode(temp), - downfall: encode(downfall), - grass_color_modifier: None, - water_color: None, - foliage_color: None, - grass_color: None, - } - } - - /// Builder function to override the biome water color - const fn water(self, water_color: [u8; 3]) -> Biome { - Biome { - water_color: Some(Color(water_color)), - ..self - } - } - - /// Builder function to override the biome foliage color - const fn foliage(self, foliage_color: [u8; 3]) -> Biome { - Biome { - foliage_color: Some(Color(foliage_color)), - ..self - } - } - - /// Builder function to override the biome grass color - const fn grass(self, grass_color: [u8; 3]) -> Biome { - Biome { - grass_color: Some(Color(grass_color)), - ..self - } - } - - /// Builder function to set a grass color modifier - const fn modify(self, grass_color_modifier: BiomeGrassColorModifier) -> Biome { - Biome { - grass_color_modifier: Some(grass_color_modifier), - ..self - } - } - - /// Decodes a temperature or downfall value from the storage format to - /// f32 for further calculation - fn decode(val: i8) -> f32 { - f32::from(val) / 20.0 - } - - /// Returns the biome's temperature decoded to its original float value - pub fn temp(&self) -> f32 { - Self::decode(self.temp) - } - - /// Returns the biome's downfall decoded to its original float value - pub fn downfall(&self) -> f32 { - Self::decode(self.downfall) - } -} - -/// 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)), - ("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)), - ] -}; - -/// Biome ID aliases -/// -/// Some biomes have been renamed or merged in recent Minecraft versions. -/// Maintain a list of aliases to support chunks saved by older versions. -pub const BIOME_ALIASES: &[(&str, &str)] = &[ - // Biomes fix - ("beaches", "beach"), - ("cold_beach", "snowy_beach"), - ("cold_deep_ocean", "deep_cold_ocean"), - ("extreme_hills", "mountains"), - ("extreme_hills_with_trees", "wooded_mountains"), - ("forest_hills", "wooded_hills"), - ("frozen_deep_ocean", "deep_frozen_ocean"), - ("hell", "nether_wastes"), - ("ice_flats", "snowy_tundra"), - ("ice_mountains", "snowy_mountains"), - ("lukewarm_deep_ocean", "deep_lukewarm_ocean"), - ("mesa", "badlands"), - ("mesa_clear_rock", "badlands_plateau"), - ("mesa_rock", "wooded_badlands_plateau"), - ("mushroom_island", "mushroom_fields"), - ("mushroom_island_shore", "mushroom_field_shore"), - ("mutated_birch_forest", "tall_birch_forest"), - ("mutated_birch_forest_hills", "tall_birch_hills"), - ("mutated_desert", "desert_lakes"), - ("mutated_extreme_hills", "gravelly_mountains"), +/// List if known biomes and their properties +pub const BIOMES: &[(&str, Biome)] = &[ ( - "mutated_extreme_hills_with_trees", - "modified_gravelly_mountains", + "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]), ), - ("mutated_forest", "flower_forest"), - ("mutated_ice_flats", "ice_spikes"), - ("mutated_jungle", "modified_jungle"), - ("mutated_jungle_edge", "modified_jungle_edge"), - ("mutated_mesa", "eroded_badlands"), - ("mutated_mesa_clear_rock", "modified_badlands_plateau"), - ("mutated_mesa_rock", "modified_wooded_badlands_plateau"), - ("mutated_plains", "sunflower_plains"), - ("mutated_redwood_taiga", "giant_spruce_taiga"), - ("mutated_redwood_taiga_hills", "giant_spruce_taiga_hills"), - ("mutated_roofed_forest", "dark_forest_hills"), - ("mutated_savanna", "shattered_savanna"), - ("mutated_savanna_rock", "shattered_savanna_plateau"), - ("mutated_swampland", "swamp_hills"), - ("mutated_taiga", "taiga_mountains"), - ("mutated_taiga_cold", "snowy_taiga_mountains"), - ("redwood_taiga", "giant_tree_taiga"), - ("redwood_taiga_hills", "giant_tree_taiga_hills"), - ("roofed_forest", "dark_forest"), - ("savanna_rock", "savanna_plateau"), - ("sky", "the_end"), - ("sky_island_barren", "end_barrens"), - ("sky_island_high", "end_highlands"), - ("sky_island_low", "small_end_islands"), - ("sky_island_medium", "end_midlands"), - ("smaller_extreme_hills", "mountain_edge"), - ("stone_beach", "stone_shore"), - ("swampland", "swamp"), - ("taiga_cold", "snowy_taiga"), - ("taiga_cold_hills", "snowy_taiga_hills"), - ("void", "the_void"), - ("warm_deep_ocean", "deep_warm_ocean"), - // Nether biome rename - ("nether", "nether_wastes"), - // Caves and Cliffs biome renames - ("badlands_plateau", "badlands"), - ("bamboo_jungle_hills", "bamboo_jungle"), - ("birch_forest_hills", "birch_forest"), - ("dark_forest_hills", "dark_forest"), - ("desert_hills", "desert"), - ("desert_lakes", "desert"), - ("giant_spruce_taiga", "old_growth_spruce_taiga"), - ("giant_spruce_taiga_hills", "old_growth_spruce_taiga"), - ("giant_tree_taiga", "old_growth_pine_taiga"), - ("giant_tree_taiga_hills", "old_growth_pine_taiga"), - ("gravelly_mountains", "windswept_gravelly_hills"), - ("jungle_edge", "sparse_jungle"), - ("jungle_hills", "jungle"), - ("lofty_peaks", "jagged_peaks"), - ("modified_badlands_plateau", "badlands"), - ("modified_gravelly_mountains", "windswept_gravelly_hills"), - ("modified_jungle", "jungle"), - ("modified_jungle_edge", "sparse_jungle"), - ("modified_wooded_badlands_plateau", "wooded_badlands"), - ("mountain_edge", "windswept_hills"), - ("mountains", "windswept_hills"), - ("mushroom_field_shore", "mushroom_fields"), - ("shattered_savanna", "windswept_savanna"), - ("shattered_savanna_plateau", "windswept_savanna"), - ("snowcapped_peaks", "frozen_peaks"), - ("snowy_mountains", "snowy_plains"), - ("snowy_taiga_hills", "snowy_taiga"), - ("snowy_taiga_mountains", "snowy_taiga"), - ("snowy_tundra", "snowy_plains"), - ("stone_shore", "stony_shore"), - ("swamp_hills", "swamp"), - ("taiga_hills", "taiga"), - ("taiga_mountains", "taiga"), - ("tall_birch_forest", "old_growth_birch_forest"), - ("tall_birch_hills", "old_growth_birch_forest"), - ("wooded_badlands_plateau", "wooded_badlands"), - ("wooded_hills", "forest"), - ("wooded_mountains", "windswept_forest"), - // Remove Deep Warm Ocean - ("deep_warm_ocean", "warm_ocean"), ]; - -/// Maps old numeric biome IDs to new string IDs -pub fn legacy_biome(index: u8) -> &'static str { - match index { - 0 => "ocean", - 1 => "plains", - 2 => "desert", - 3 => "mountains", - 4 => "forest", - 5 => "taiga", - 6 => "swamp", - 7 => "river", - 8 => "nether_wastes", - 9 => "the_end", - 10 => "frozen_ocean", - 11 => "frozen_river", - 12 => "snowy_tundra", - 13 => "snowy_mountains", - 14 => "mushroom_fields", - 15 => "mushroom_field_shore", - 16 => "beach", - 17 => "desert_hills", - 18 => "wooded_hills", - 19 => "taiga_hills", - 20 => "mountain_edge", - 21 => "jungle", - 22 => "jungle_hills", - 23 => "jungle_edge", - 24 => "deep_ocean", - 25 => "stone_shore", - 26 => "snowy_beach", - 27 => "birch_forest", - 28 => "birch_forest_hills", - 29 => "dark_forest", - 30 => "snowy_taiga", - 31 => "snowy_taiga_hills", - 32 => "giant_tree_taiga", - 33 => "giant_tree_taiga_hills", - 34 => "wooded_mountains", - 35 => "savanna", - 36 => "savanna_plateau", - 37 => "badlands", - 38 => "wooded_badlands_plateau", - 39 => "badlands_plateau", - 40 => "small_end_islands", - 41 => "end_midlands", - 42 => "end_highlands", - 43 => "end_barrens", - 44 => "warm_ocean", - 45 => "lukewarm_ocean", - 46 => "cold_ocean", - 47 => "deep_warm_ocean", - 48 => "deep_lukewarm_ocean", - 49 => "deep_cold_ocean", - 50 => "deep_frozen_ocean", - 127 => "the_void", - 129 => "sunflower_plains", - 130 => "desert_lakes", - 131 => "gravelly_mountains", - 132 => "flower_forest", - 133 => "taiga_mountains", - 134 => "swamp_hills", - 140 => "ice_spikes", - 149 => "modified_jungle", - 151 => "modified_jungle_edge", - 155 => "tall_birch_forest", - 156 => "tall_birch_hills", - 157 => "dark_forest_hills", - 158 => "snowy_taiga_mountains", - 160 => "giant_spruce_taiga", - 161 => "giant_spruce_taiga_hills", - 162 => "modified_gravelly_mountains", - 163 => "shattered_savanna", - 164 => "shattered_savanna_plateau", - 165 => "eroded_badlands", - 166 => "modified_wooded_badlands_plateau", - 167 => "modified_badlands_plateau", - 168 => "bamboo_jungle", - 169 => "bamboo_jungle_hills", - 170 => "soul_sand_valley", - 171 => "crimson_forest", - 172 => "warped_forest", - 173 => "basalt_deltas", - 174 => "dripstone_caves", - 175 => "lush_caves", - 177 => "meadow", - 178 => "grove", - 179 => "snowy_slopes", - 180 => "snowcapped_peaks", - 181 => "lofty_peaks", - 182 => "stony_peaks", - _ => "ocean", - } -} diff --git a/crates/resource/src/block_types.rs b/crates/resource/src/block_types.rs index cbfe1b7..53abd54 100644 --- a/crates/resource/src/block_types.rs +++ b/crates/resource/src/block_types.rs @@ -1,7 +1,12 @@ +//! Block type information +//! +//! This file is generated using resource/generate.py, do not edit + use enumflags2::make_bitflags; use super::*; +/// List if known block types and their properties pub const BLOCK_TYPES: &[(&str, ConstBlockType)] = &[ ( "acacia_button", @@ -1868,7 +1873,7 @@ pub const BLOCK_TYPES: &[(&str, ConstBlockType)] = &[ ConstBlockType { block_color: BlockColor { flags: make_bitflags!(BlockFlag::{Opaque}), - color: Color([47, 23, 28]), + color: Color([45, 22, 27]), }, sign_material: None, }, @@ -1903,6 +1908,16 @@ pub const BLOCK_TYPES: &[(&str, ConstBlockType)] = &[ sign_material: None, }, ), + ( + "chiseled_resin_bricks", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{Opaque}), + color: Color([200, 84, 24]), + }, + sign_material: None, + }, + ), ( "chiseled_sandstone", ConstBlockType { @@ -1973,6 +1988,16 @@ pub const BLOCK_TYPES: &[(&str, ConstBlockType)] = &[ sign_material: None, }, ), + ( + "closed_eyeblossom", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{}), + color: Color([0, 0, 0]), + }, + sign_material: None, + }, + ), ( "coal_block", ConstBlockType { @@ -2283,6 +2308,16 @@ pub const BLOCK_TYPES: &[(&str, ConstBlockType)] = &[ sign_material: None, }, ), + ( + "creaking_heart", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{Opaque}), + color: Color([73, 59, 54]), + }, + sign_material: None, + }, + ), ( "creeper_head", ConstBlockType { @@ -6253,6 +6288,16 @@ pub const BLOCK_TYPES: &[(&str, ConstBlockType)] = &[ sign_material: None, }, ), + ( + "open_eyeblossom", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{}), + color: Color([0, 0, 0]), + }, + sign_material: None, + }, + ), ( "orange_banner", ConstBlockType { @@ -6523,6 +6568,206 @@ pub const BLOCK_TYPES: &[(&str, ConstBlockType)] = &[ sign_material: None, }, ), + ( + "pale_hanging_moss", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{}), + color: Color([0, 0, 0]), + }, + sign_material: None, + }, + ), + ( + "pale_moss_block", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{Opaque}), + color: Color([106, 112, 104]), + }, + sign_material: None, + }, + ), + ( + "pale_moss_carpet", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{Opaque}), + color: Color([106, 112, 104]), + }, + sign_material: None, + }, + ), + ( + "pale_oak_button", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{}), + color: Color([0, 0, 0]), + }, + sign_material: None, + }, + ), + ( + "pale_oak_door", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{Opaque}), + color: Color([216, 208, 206]), + }, + sign_material: None, + }, + ), + ( + "pale_oak_fence", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{Opaque}), + color: Color([227, 217, 216]), + }, + sign_material: None, + }, + ), + ( + "pale_oak_fence_gate", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{Opaque}), + color: Color([227, 217, 216]), + }, + sign_material: None, + }, + ), + ( + "pale_oak_hanging_sign", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{}), + color: Color([0, 0, 0]), + }, + sign_material: Some("pale_oak"), + }, + ), + ( + "pale_oak_leaves", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{Opaque}), + color: Color([116, 121, 114]), + }, + sign_material: None, + }, + ), + ( + "pale_oak_log", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{Opaque}), + color: Color([198, 189, 187]), + }, + sign_material: None, + }, + ), + ( + "pale_oak_planks", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{Opaque}), + color: Color([227, 217, 216]), + }, + sign_material: None, + }, + ), + ( + "pale_oak_pressure_plate", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{Opaque}), + color: Color([227, 217, 216]), + }, + sign_material: None, + }, + ), + ( + "pale_oak_sapling", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{Opaque}), + color: Color([109, 105, 99]), + }, + sign_material: None, + }, + ), + ( + "pale_oak_sign", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{}), + color: Color([0, 0, 0]), + }, + sign_material: Some("pale_oak"), + }, + ), + ( + "pale_oak_slab", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{Opaque}), + color: Color([227, 217, 216]), + }, + sign_material: None, + }, + ), + ( + "pale_oak_stairs", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{Opaque}), + color: Color([227, 217, 216]), + }, + sign_material: None, + }, + ), + ( + "pale_oak_trapdoor", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{Opaque}), + color: Color([229, 220, 218]), + }, + sign_material: None, + }, + ), + ( + "pale_oak_wall_hanging_sign", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{WallSign}), + color: Color([0, 0, 0]), + }, + sign_material: Some("pale_oak"), + }, + ), + ( + "pale_oak_wall_sign", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{WallSign}), + color: Color([0, 0, 0]), + }, + sign_material: Some("pale_oak"), + }, + ), + ( + "pale_oak_wood", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{Opaque}), + color: Color([87, 77, 75]), + }, + sign_material: None, + }, + ), ( "pearlescent_froglight", ConstBlockType { @@ -7213,6 +7458,16 @@ pub const BLOCK_TYPES: &[(&str, ConstBlockType)] = &[ sign_material: None, }, ), + ( + "potted_closed_eyeblossom", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{Opaque}), + color: Color([108, 98, 101]), + }, + sign_material: None, + }, + ), ( "potted_cornflower", ConstBlockType { @@ -7333,6 +7588,16 @@ pub const BLOCK_TYPES: &[(&str, ConstBlockType)] = &[ sign_material: None, }, ), + ( + "potted_open_eyeblossom", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{Opaque}), + color: Color([133, 124, 127]), + }, + sign_material: None, + }, + ), ( "potted_orange_tulip", ConstBlockType { @@ -7353,6 +7618,16 @@ pub const BLOCK_TYPES: &[(&str, ConstBlockType)] = &[ sign_material: None, }, ), + ( + "potted_pale_oak_sapling", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{Opaque}), + color: Color([109, 105, 99]), + }, + sign_material: None, + }, + ), ( "potted_pink_tulip", ConstBlockType { @@ -8193,6 +8468,66 @@ pub const BLOCK_TYPES: &[(&str, ConstBlockType)] = &[ sign_material: None, }, ), + ( + "resin_block", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{Opaque}), + color: Color([217, 99, 25]), + }, + sign_material: None, + }, + ), + ( + "resin_brick_slab", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{Opaque}), + color: Color([205, 88, 24]), + }, + sign_material: None, + }, + ), + ( + "resin_brick_stairs", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{Opaque}), + color: Color([205, 88, 24]), + }, + sign_material: None, + }, + ), + ( + "resin_brick_wall", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{Opaque}), + color: Color([205, 88, 24]), + }, + sign_material: None, + }, + ), + ( + "resin_bricks", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{Opaque}), + color: Color([205, 88, 24]), + }, + sign_material: None, + }, + ), + ( + "resin_clump", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{}), + color: Color([0, 0, 0]), + }, + sign_material: None, + }, + ), ( "respawn_anchor", ConstBlockType { @@ -9173,6 +9508,26 @@ pub const BLOCK_TYPES: &[(&str, ConstBlockType)] = &[ sign_material: None, }, ), + ( + "stripped_pale_oak_log", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{Opaque}), + color: Color([235, 226, 225]), + }, + sign_material: None, + }, + ), + ( + "stripped_pale_oak_wood", + ConstBlockType { + block_color: BlockColor { + flags: make_bitflags!(BlockFlag::{Opaque}), + color: Color([245, 238, 236]), + }, + sign_material: None, + }, + ), ( "stripped_spruce_log", ConstBlockType { diff --git a/crates/resource/src/legacy_biomes.rs b/crates/resource/src/legacy_biomes.rs new file mode 100644 index 0000000..d980823 --- /dev/null +++ b/crates/resource/src/legacy_biomes.rs @@ -0,0 +1,202 @@ +//! Manually maintained biome data (aliases and legacy biome IDs) + +/// Biome ID aliases +/// +/// Some biomes have been renamed or merged in recent Minecraft versions. +/// Maintain a list of aliases to support chunks saved by older versions. +pub const BIOME_ALIASES: &[(&str, &str)] = &[ + // Biomes fix + ("beaches", "beach"), + ("cold_beach", "snowy_beach"), + ("cold_deep_ocean", "deep_cold_ocean"), + ("extreme_hills", "mountains"), + ("extreme_hills_with_trees", "wooded_mountains"), + ("forest_hills", "wooded_hills"), + ("frozen_deep_ocean", "deep_frozen_ocean"), + ("hell", "nether_wastes"), + ("ice_flats", "snowy_tundra"), + ("ice_mountains", "snowy_mountains"), + ("lukewarm_deep_ocean", "deep_lukewarm_ocean"), + ("mesa", "badlands"), + ("mesa_clear_rock", "badlands_plateau"), + ("mesa_rock", "wooded_badlands_plateau"), + ("mushroom_island", "mushroom_fields"), + ("mushroom_island_shore", "mushroom_field_shore"), + ("mutated_birch_forest", "tall_birch_forest"), + ("mutated_birch_forest_hills", "tall_birch_hills"), + ("mutated_desert", "desert_lakes"), + ("mutated_extreme_hills", "gravelly_mountains"), + ( + "mutated_extreme_hills_with_trees", + "modified_gravelly_mountains", + ), + ("mutated_forest", "flower_forest"), + ("mutated_ice_flats", "ice_spikes"), + ("mutated_jungle", "modified_jungle"), + ("mutated_jungle_edge", "modified_jungle_edge"), + ("mutated_mesa", "eroded_badlands"), + ("mutated_mesa_clear_rock", "modified_badlands_plateau"), + ("mutated_mesa_rock", "modified_wooded_badlands_plateau"), + ("mutated_plains", "sunflower_plains"), + ("mutated_redwood_taiga", "giant_spruce_taiga"), + ("mutated_redwood_taiga_hills", "giant_spruce_taiga_hills"), + ("mutated_roofed_forest", "dark_forest_hills"), + ("mutated_savanna", "shattered_savanna"), + ("mutated_savanna_rock", "shattered_savanna_plateau"), + ("mutated_swampland", "swamp_hills"), + ("mutated_taiga", "taiga_mountains"), + ("mutated_taiga_cold", "snowy_taiga_mountains"), + ("redwood_taiga", "giant_tree_taiga"), + ("redwood_taiga_hills", "giant_tree_taiga_hills"), + ("roofed_forest", "dark_forest"), + ("savanna_rock", "savanna_plateau"), + ("sky", "the_end"), + ("sky_island_barren", "end_barrens"), + ("sky_island_high", "end_highlands"), + ("sky_island_low", "small_end_islands"), + ("sky_island_medium", "end_midlands"), + ("smaller_extreme_hills", "mountain_edge"), + ("stone_beach", "stone_shore"), + ("swampland", "swamp"), + ("taiga_cold", "snowy_taiga"), + ("taiga_cold_hills", "snowy_taiga_hills"), + ("void", "the_void"), + ("warm_deep_ocean", "deep_warm_ocean"), + // Nether biome rename + ("nether", "nether_wastes"), + // Caves and Cliffs biome renames + ("badlands_plateau", "badlands"), + ("bamboo_jungle_hills", "bamboo_jungle"), + ("birch_forest_hills", "birch_forest"), + ("dark_forest_hills", "dark_forest"), + ("desert_hills", "desert"), + ("desert_lakes", "desert"), + ("giant_spruce_taiga", "old_growth_spruce_taiga"), + ("giant_spruce_taiga_hills", "old_growth_spruce_taiga"), + ("giant_tree_taiga", "old_growth_pine_taiga"), + ("giant_tree_taiga_hills", "old_growth_pine_taiga"), + ("gravelly_mountains", "windswept_gravelly_hills"), + ("jungle_edge", "sparse_jungle"), + ("jungle_hills", "jungle"), + ("lofty_peaks", "jagged_peaks"), + ("modified_badlands_plateau", "badlands"), + ("modified_gravelly_mountains", "windswept_gravelly_hills"), + ("modified_jungle", "jungle"), + ("modified_jungle_edge", "sparse_jungle"), + ("modified_wooded_badlands_plateau", "wooded_badlands"), + ("mountain_edge", "windswept_hills"), + ("mountains", "windswept_hills"), + ("mushroom_field_shore", "mushroom_fields"), + ("shattered_savanna", "windswept_savanna"), + ("shattered_savanna_plateau", "windswept_savanna"), + ("snowcapped_peaks", "frozen_peaks"), + ("snowy_mountains", "snowy_plains"), + ("snowy_taiga_hills", "snowy_taiga"), + ("snowy_taiga_mountains", "snowy_taiga"), + ("snowy_tundra", "snowy_plains"), + ("stone_shore", "stony_shore"), + ("swamp_hills", "swamp"), + ("taiga_hills", "taiga"), + ("taiga_mountains", "taiga"), + ("tall_birch_forest", "old_growth_birch_forest"), + ("tall_birch_hills", "old_growth_birch_forest"), + ("wooded_badlands_plateau", "wooded_badlands"), + ("wooded_hills", "forest"), + ("wooded_mountains", "windswept_forest"), + // Remove Deep Warm Ocean + ("deep_warm_ocean", "warm_ocean"), +]; + +/// Maps old numeric biome IDs to new string IDs +pub fn legacy_biome(index: u8) -> &'static str { + match index { + 0 => "ocean", + 1 => "plains", + 2 => "desert", + 3 => "mountains", + 4 => "forest", + 5 => "taiga", + 6 => "swamp", + 7 => "river", + 8 => "nether_wastes", + 9 => "the_end", + 10 => "frozen_ocean", + 11 => "frozen_river", + 12 => "snowy_tundra", + 13 => "snowy_mountains", + 14 => "mushroom_fields", + 15 => "mushroom_field_shore", + 16 => "beach", + 17 => "desert_hills", + 18 => "wooded_hills", + 19 => "taiga_hills", + 20 => "mountain_edge", + 21 => "jungle", + 22 => "jungle_hills", + 23 => "jungle_edge", + 24 => "deep_ocean", + 25 => "stone_shore", + 26 => "snowy_beach", + 27 => "birch_forest", + 28 => "birch_forest_hills", + 29 => "dark_forest", + 30 => "snowy_taiga", + 31 => "snowy_taiga_hills", + 32 => "giant_tree_taiga", + 33 => "giant_tree_taiga_hills", + 34 => "wooded_mountains", + 35 => "savanna", + 36 => "savanna_plateau", + 37 => "badlands", + 38 => "wooded_badlands_plateau", + 39 => "badlands_plateau", + 40 => "small_end_islands", + 41 => "end_midlands", + 42 => "end_highlands", + 43 => "end_barrens", + 44 => "warm_ocean", + 45 => "lukewarm_ocean", + 46 => "cold_ocean", + 47 => "deep_warm_ocean", + 48 => "deep_lukewarm_ocean", + 49 => "deep_cold_ocean", + 50 => "deep_frozen_ocean", + 127 => "the_void", + 129 => "sunflower_plains", + 130 => "desert_lakes", + 131 => "gravelly_mountains", + 132 => "flower_forest", + 133 => "taiga_mountains", + 134 => "swamp_hills", + 140 => "ice_spikes", + 149 => "modified_jungle", + 151 => "modified_jungle_edge", + 155 => "tall_birch_forest", + 156 => "tall_birch_hills", + 157 => "dark_forest_hills", + 158 => "snowy_taiga_mountains", + 160 => "giant_spruce_taiga", + 161 => "giant_spruce_taiga_hills", + 162 => "modified_gravelly_mountains", + 163 => "shattered_savanna", + 164 => "shattered_savanna_plateau", + 165 => "eroded_badlands", + 166 => "modified_wooded_badlands_plateau", + 167 => "modified_badlands_plateau", + 168 => "bamboo_jungle", + 169 => "bamboo_jungle_hills", + 170 => "soul_sand_valley", + 171 => "crimson_forest", + 172 => "warped_forest", + 173 => "basalt_deltas", + 174 => "dripstone_caves", + 175 => "lush_caves", + 177 => "meadow", + 178 => "grove", + 179 => "snowy_slopes", + 180 => "snowcapped_peaks", + 181 => "lofty_peaks", + 182 => "stony_peaks", + _ => "ocean", + } +} diff --git a/crates/resource/src/lib.rs b/crates/resource/src/lib.rs index 1baffda..1afcc62 100644 --- a/crates/resource/src/lib.rs +++ b/crates/resource/src/lib.rs @@ -4,10 +4,9 @@ mod biomes; mod block_color; -mod legacy_block_types; - -#[allow(clippy::missing_docs_in_private_items)] // Generated module mod block_types; +mod legacy_biomes; +mod legacy_block_types; use std::collections::HashMap; @@ -135,9 +134,112 @@ impl BlockTypes { } } -pub use biomes::{Biome, BiomeGrassColorModifier}; pub use block_color::{block_color, needs_biome}; +/// Grass color modifier used by a biome +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum BiomeGrassColorModifier { + /// Grass color modifier used by the dark forest biome + DarkForest, + /// Grass color modifier used by swamp biomes + Swamp, +} + +/// A biome specification +/// +/// A Biome contains all information about a biome necessary to compute a block +/// color given a block type and depth +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct Biome { + /// Temperature value + /// + /// For more efficient storage, the temperature is stored as an integer + /// after mutiplying the raw value by 20 + pub temp: i8, + /// Downfall value + /// + /// For more efficient storage, the downfall is stored as an integer + /// after mutiplying the raw value by 20 + pub downfall: i8, + /// Water color override + pub water_color: Option, + /// Foliage color override + pub foliage_color: Option, + /// Grass color override + pub grass_color: Option, + /// Grass color modifier + pub grass_color_modifier: Option, +} + +impl Biome { + /// Constructs a new Biome + const fn new(temp: i16, downfall: i16) -> Biome { + /// Helper to encode temperature and downfall values + /// + /// Converts temperatue and downfall from the input format + /// (mutiplied by 100) to i8 range for more efficient storage. + const fn encode(v: i16) -> i8 { + (v / 5) as i8 + } + Biome { + temp: encode(temp), + downfall: encode(downfall), + grass_color_modifier: None, + water_color: None, + foliage_color: None, + grass_color: None, + } + } + + /// Builder function to override the biome water color + const fn water(self, water_color: [u8; 3]) -> Biome { + Biome { + water_color: Some(Color(water_color)), + ..self + } + } + + /// Builder function to override the biome foliage color + const fn foliage(self, foliage_color: [u8; 3]) -> Biome { + Biome { + foliage_color: Some(Color(foliage_color)), + ..self + } + } + + /// Builder function to override the biome grass color + const fn grass(self, grass_color: [u8; 3]) -> Biome { + Biome { + grass_color: Some(Color(grass_color)), + ..self + } + } + + /// Builder function to set a grass color modifier + const fn modify(self, grass_color_modifier: BiomeGrassColorModifier) -> Biome { + Biome { + grass_color_modifier: Some(grass_color_modifier), + ..self + } + } + + /// Decodes a temperature or downfall value from the storage format to + /// f32 for further calculation + fn decode(val: i8) -> f32 { + f32::from(val) / 20.0 + } + + /// Returns the biome's temperature decoded to its original float value + pub fn temp(&self) -> f32 { + Self::decode(self.temp) + } + + /// Returns the biome's downfall decoded to its original float value + pub fn downfall(&self) -> f32 { + Self::decode(self.downfall) + } +} + /// Used to look up standard Minecraft biome types #[derive(Debug)] pub struct BiomeTypes { @@ -154,7 +256,7 @@ impl Default for BiomeTypes { .map(|(k, v)| (String::from(*k), v)) .collect(); - for &(old, new) in biomes::BIOME_ALIASES.iter().rev() { + for &(old, new) in legacy_biomes::BIOME_ALIASES.iter().rev() { let biome = biome_map .get(new) .copied() @@ -164,7 +266,7 @@ impl Default for BiomeTypes { let legacy_biomes = (0..=255) .map(|index| { - let id = biomes::legacy_biome(index); + let id = legacy_biomes::legacy_biome(index); *biome_map.get(id).expect("Unknown legacy biome") }) .collect::>() diff --git a/resource/README.md b/resource/README.md index ab9d5ea..12302ec 100644 --- a/resource/README.md +++ b/resource/README.md @@ -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. diff --git a/resource/biomes.py b/resource/biomes.py new file mode 100755 index 0000000..4e3bc51 --- /dev/null +++ b/resource/biomes.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 + +import json +import os +import sys + + +if len(sys.argv) != 3: + sys.exit('Usage: biomes.py ') + +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) diff --git a/resource/blocks.json b/resource/blocks.json index 9d70f96..a88aa34 100644 --- a/resource/blocks.json +++ b/resource/blocks.json @@ -416,6 +416,7 @@ "chiseled_red_sandstone": { "texture": "red_sandstone_top" }, + "chiseled_resin_bricks": {}, "chiseled_sandstone": { "texture": "sandstone_top" }, @@ -427,6 +428,7 @@ "chorus_flower": {}, "chorus_plant": {}, "clay": {}, + "closed_eyeblossom": null, "coal_block": {}, "coal_ore": {}, "coarse_dirt": {}, @@ -482,6 +484,9 @@ "crafting_table": { "texture": "crafting_table_top" }, + "creaking_heart": { + "texture": "creaking_heart_top" + }, "creeper_head": null, "creeper_wall_head": null, "crimson_button": null, @@ -1269,6 +1274,7 @@ "ochre_froglight": { "texture": "ochre_froglight_top" }, + "open_eyeblossom": null, "orange_banner": null, "orange_bed": null, "orange_candle": null, @@ -1308,6 +1314,56 @@ }, "packed_ice": {}, "packed_mud": {}, + "pale_hanging_moss": null, + "pale_moss_block": {}, + "pale_moss_carpet": {}, + "pale_oak_button": null, + "pale_oak_door": { + "texture": "pale_oak_door_top" + }, + "pale_oak_fence": { + "texture": "pale_oak_planks" + }, + "pale_oak_fence_gate": { + "texture": "pale_oak_planks" + }, + "pale_oak_hanging_sign": { + "sign_material": "pale_oak", + "texture": null + }, + "pale_oak_leaves": {}, + "pale_oak_log": { + "texture": "pale_oak_log_top" + }, + "pale_oak_planks": {}, + "pale_oak_pressure_plate": { + "texture": "pale_oak_planks" + }, + "pale_oak_sapling": {}, + "pale_oak_sign": { + "sign_material": "pale_oak", + "texture": null + }, + "pale_oak_slab": { + "texture": "pale_oak_planks" + }, + "pale_oak_stairs": { + "texture": "pale_oak_planks" + }, + "pale_oak_trapdoor": {}, + "pale_oak_wall_hanging_sign": { + "sign_material": "pale_oak", + "texture": null, + "wall_sign": true + }, + "pale_oak_wall_sign": { + "sign_material": "pale_oak", + "texture": null, + "wall_sign": true + }, + "pale_oak_wood": { + "texture": "pale_oak_log" + }, "pearlescent_froglight": { "texture": "pearlescent_froglight_top" }, @@ -1463,6 +1519,9 @@ "potted_cherry_sapling": { "texture": "cherry_sapling" }, + "potted_closed_eyeblossom": { + "texture": "closed_eyeblossom" + }, "potted_cornflower": { "texture": "cornflower" }, @@ -1500,12 +1559,18 @@ "potted_oak_sapling": { "texture": "oak_sapling" }, + "potted_open_eyeblossom": { + "texture": "open_eyeblossom" + }, "potted_orange_tulip": { "texture": "orange_tulip" }, "potted_oxeye_daisy": { "texture": "oxeye_daisy" }, + "potted_pale_oak_sapling": { + "texture": "pale_oak_sapling" + }, "potted_pink_tulip": { "texture": "pink_tulip" }, @@ -1668,6 +1733,18 @@ "repeating_command_block": { "texture": "repeating_command_block_front" }, + "resin_block": {}, + "resin_brick_slab": { + "texture": "resin_bricks" + }, + "resin_brick_stairs": { + "texture": "resin_bricks" + }, + "resin_brick_wall": { + "texture": "resin_bricks" + }, + "resin_bricks": {}, + "resin_clump": null, "respawn_anchor": { "texture": "respawn_anchor_top" }, @@ -1903,6 +1980,12 @@ "stripped_oak_wood": { "texture": "stripped_oak_log" }, + "stripped_pale_oak_log": { + "texture": "stripped_pale_oak_log_top" + }, + "stripped_pale_oak_wood": { + "texture": "stripped_pale_oak_log" + }, "stripped_spruce_log": { "texture": "stripped_spruce_log_top" }, diff --git a/resource/generate.py b/resource/generate.py index 8064482..ab91324 100755 --- a/resource/generate.py +++ b/resource/generate.py @@ -14,10 +14,15 @@ with open(sys.argv[1]) as f: output = {} with open(sys.argv[2], 'w') as f: + print('//! Block type information', file=f); + print('//!', file=f); + print('//! This file is generated using resource/generate.py, do not edit', file=f); + print('', file=f) print('use enumflags2::make_bitflags;', file=f); print('', file=f) print('use super::*;', file=f) print('', file=f) + print('/// List if known block types and their properties', file=f); print('pub const BLOCK_TYPES: &[(&str, ConstBlockType)] = &[', file=f) for name, info in colors.items(): diff --git a/resource/sign_textures.py b/resource/sign_textures.py index e0b548d..846ab3e 100755 --- a/resource/sign_textures.py +++ b/resource/sign_textures.py @@ -15,6 +15,7 @@ MATERIALS = [ 'jungle', 'mangrove', 'oak', + 'pale_oak', 'spruce', 'warped', ] diff --git a/src/core/common.rs b/src/core/common.rs index 5f518e0..3dd01cf 100644 --- a/src/core/common.rs +++ b/src/core/common.rs @@ -24,7 +24,7 @@ use crate::{ /// /// Increase when the generation of processed regions from region data changes /// (usually because of updated resource data) -pub const REGION_FILE_META_VERSION: FileMetaVersion = FileMetaVersion(2); +pub const REGION_FILE_META_VERSION: FileMetaVersion = FileMetaVersion(3); /// MinedMap map tile data version number /// @@ -36,7 +36,7 @@ pub const MAP_FILE_META_VERSION: FileMetaVersion = FileMetaVersion(0); /// /// Increase when the generation of lightmap tiles from region data changes /// (usually because of updated resource data) -pub const LIGHTMAP_FILE_META_VERSION: FileMetaVersion = FileMetaVersion(2); +pub const LIGHTMAP_FILE_META_VERSION: FileMetaVersion = FileMetaVersion(3); /// MinedMap mipmap data version number /// diff --git a/viewer/images/bg/pale_oak_hanging_sign.png b/viewer/images/bg/pale_oak_hanging_sign.png new file mode 100644 index 0000000..972a119 Binary files /dev/null and b/viewer/images/bg/pale_oak_hanging_sign.png differ diff --git a/viewer/images/bg/pale_oak_hanging_wall_sign.png b/viewer/images/bg/pale_oak_hanging_wall_sign.png new file mode 100644 index 0000000..cf98cb2 Binary files /dev/null and b/viewer/images/bg/pale_oak_hanging_wall_sign.png differ diff --git a/viewer/images/bg/pale_oak_sign.png b/viewer/images/bg/pale_oak_sign.png new file mode 100644 index 0000000..5ea5a7e Binary files /dev/null and b/viewer/images/bg/pale_oak_sign.png differ diff --git a/viewer/images/bg/pale_oak_wall_sign.png b/viewer/images/bg/pale_oak_wall_sign.png new file mode 100644 index 0000000..f52f32a Binary files /dev/null and b/viewer/images/bg/pale_oak_wall_sign.png differ diff --git a/viewer/images/icon/pale_oak_hanging_sign.png b/viewer/images/icon/pale_oak_hanging_sign.png new file mode 100644 index 0000000..cd61dd1 Binary files /dev/null and b/viewer/images/icon/pale_oak_hanging_sign.png differ diff --git a/viewer/images/icon/pale_oak_hanging_wall_sign.png b/viewer/images/icon/pale_oak_hanging_wall_sign.png new file mode 100644 index 0000000..fefd31a Binary files /dev/null and b/viewer/images/icon/pale_oak_hanging_wall_sign.png differ diff --git a/viewer/images/icon/pale_oak_sign.png b/viewer/images/icon/pale_oak_sign.png new file mode 100644 index 0000000..3684f5d Binary files /dev/null and b/viewer/images/icon/pale_oak_sign.png differ diff --git a/viewer/images/icon/pale_oak_wall_sign.png b/viewer/images/icon/pale_oak_wall_sign.png new file mode 100644 index 0000000..32257e3 Binary files /dev/null and b/viewer/images/icon/pale_oak_wall_sign.png differ