652 lines
23 KiB
Rust
652 lines
23 KiB
Rust
use heck::ToShoutySnakeCase;
|
|
use proc_macro2::TokenStream;
|
|
use quote::{ToTokens, format_ident, quote};
|
|
use serde::Deserialize;
|
|
use std::{collections::BTreeMap, fs};
|
|
|
|
/// Deserialized block reference used in chunk generation settings (e.g., default block or fluid).
|
|
#[derive(Deserialize)]
|
|
pub struct BlockStateCodecStruct {
|
|
/// Block registry name including the `minecraft:` namespace prefix.
|
|
#[serde(rename = "Name")]
|
|
pub name: String,
|
|
/// Optional block state properties (e.g., `{"facing": "north"}`).
|
|
#[serde(rename = "Properties")]
|
|
#[allow(dead_code)]
|
|
pub properties: Option<BTreeMap<String, String>>,
|
|
}
|
|
|
|
/// Deserialized chunk generation settings for a dimension, sourced from `chunk_gen_settings.json`.
|
|
#[derive(Deserialize)]
|
|
pub struct GenerationSettingsStruct {
|
|
/// Whether aquifer (underground water pocket) generation is enabled.
|
|
#[serde(default)]
|
|
pub aquifers_enabled: bool,
|
|
/// Whether ore-vein generation is enabled.
|
|
#[serde(default)]
|
|
pub ore_veins_enabled: bool,
|
|
/// Whether to use the legacy random number source for this dimension.
|
|
#[serde(default)]
|
|
pub legacy_random_source: bool,
|
|
/// Y-level treated as sea level for this dimension.
|
|
pub sea_level: i32,
|
|
/// Default fluid block (usually water or lava) placed by the aquifer generator.
|
|
pub default_fluid: BlockStateCodecStruct,
|
|
/// Default solid block used to fill the terrain.
|
|
pub default_block: BlockStateCodecStruct,
|
|
/// Noise shape parameters controlling vertical and horizontal cell sizes.
|
|
#[serde(rename = "noise")]
|
|
pub shape: GenerationShapeConfigStruct,
|
|
/// Hierarchical surface material rule determining which block is placed at each surface point.
|
|
pub surface_rule: MaterialRuleStruct,
|
|
}
|
|
|
|
/// Deserialized noise-shape configuration controlling terrain cell dimensions.
|
|
#[derive(Deserialize)]
|
|
pub struct GenerationShapeConfigStruct {
|
|
/// Minimum Y level for terrain generation.
|
|
pub min_y: i8,
|
|
/// Total vertical span of the generation region in blocks.
|
|
pub height: u16,
|
|
/// Log₂ of the horizontal cell block count (cell width = `1 << size_horizontal`).
|
|
pub size_horizontal: u8,
|
|
/// Log₂ of the vertical cell block count (cell height = `1 << size_vertical`).
|
|
pub size_vertical: u8,
|
|
}
|
|
|
|
/// Deserialized surface material rule that determines which block to place at a given surface point.
|
|
#[derive(Deserialize)]
|
|
#[serde(tag = "type")]
|
|
pub enum MaterialRuleStruct {
|
|
/// Place a specific block state unconditionally.
|
|
#[serde(rename = "minecraft:block")]
|
|
Block {
|
|
/// The block state to place.
|
|
result_state: BlockStateCodecStruct,
|
|
},
|
|
/// Evaluate each rule in order, stopping at the first match.
|
|
#[serde(rename = "minecraft:sequence")]
|
|
Sequence {
|
|
/// The ordered list of child rules.
|
|
sequence: Vec<Self>,
|
|
},
|
|
/// Apply `then_run` only when `if_true` evaluates to true.
|
|
#[serde(rename = "minecraft:condition")]
|
|
Condition {
|
|
/// The condition that must be satisfied.
|
|
if_true: MaterialConditionStruct,
|
|
/// The rule to apply when the condition is met.
|
|
then_run: Box<Self>,
|
|
},
|
|
/// Special Badlands terrain coloring rule.
|
|
#[serde(rename = "minecraft:bandlands")]
|
|
Badlands,
|
|
}
|
|
|
|
fn deserialize_string_or_vec<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
|
|
where
|
|
D: serde::Deserializer<'de>,
|
|
{
|
|
struct StringOrVec;
|
|
|
|
impl<'de> serde::de::Visitor<'de> for StringOrVec {
|
|
type Value = Vec<String>;
|
|
|
|
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
formatter.write_str("string or list of strings")
|
|
}
|
|
|
|
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
|
where
|
|
E: serde::de::Error,
|
|
{
|
|
Ok(vec![value.to_owned()])
|
|
}
|
|
|
|
fn visit_seq<S>(self, mut seq: S) -> Result<Self::Value, S::Error>
|
|
where
|
|
S: serde::de::SeqAccess<'de>,
|
|
{
|
|
let mut vec = Vec::new();
|
|
while let Some(el) = seq.next_element()? {
|
|
vec.push(el);
|
|
}
|
|
Ok(vec)
|
|
}
|
|
}
|
|
|
|
deserializer.deserialize_any(StringOrVec)
|
|
}
|
|
|
|
/// Deserialized surface material condition that gates a material rule.
|
|
#[derive(Deserialize)]
|
|
#[serde(tag = "type")]
|
|
pub enum MaterialConditionStruct {
|
|
/// True when the current position is in one of the listed biomes.
|
|
#[serde(rename = "minecraft:biome")]
|
|
Biome {
|
|
/// List of biome resource locations to match against.
|
|
#[serde(deserialize_with = "deserialize_string_or_vec")]
|
|
biome_is: Vec<String>,
|
|
},
|
|
/// True when a named noise value is within the given range.
|
|
#[serde(rename = "minecraft:noise_threshold")]
|
|
NoiseThreshold {
|
|
/// Resource location of the noise parameter.
|
|
noise: String,
|
|
/// Minimum threshold (inclusive).
|
|
min_threshold: f64,
|
|
/// Maximum threshold (inclusive).
|
|
max_threshold: f64,
|
|
},
|
|
/// True below a Y offset and false above another, with a linear gradient in between.
|
|
#[serde(rename = "minecraft:vertical_gradient")]
|
|
VerticalGradient {
|
|
/// Name of the random source used for this gradient.
|
|
random_name: String,
|
|
/// Y offset below which the condition is always true.
|
|
true_at_and_below: YOffsetStruct,
|
|
/// Y offset above which the condition is always false.
|
|
false_at_and_above: YOffsetStruct,
|
|
},
|
|
/// True when the position is above a given Y anchor.
|
|
#[serde(rename = "minecraft:y_above")]
|
|
YAbove {
|
|
/// The Y offset anchor to compare against.
|
|
anchor: YOffsetStruct,
|
|
/// Multiplier applied to surface depth when computing the threshold.
|
|
surface_depth_multiplier: i32,
|
|
/// Whether to add stone depth to the comparison value.
|
|
add_stone_depth: bool,
|
|
},
|
|
/// True when the position is above a water surface within a certain offset.
|
|
#[serde(rename = "minecraft:water")]
|
|
Water {
|
|
/// Y offset relative to the water surface.
|
|
offset: i32,
|
|
/// Multiplier applied to surface depth.
|
|
surface_depth_multiplier: i32,
|
|
/// Whether to add stone depth to the comparison value.
|
|
add_stone_depth: bool,
|
|
},
|
|
/// True when the biome temperature is cold (below freezing).
|
|
#[serde(rename = "minecraft:temperature")]
|
|
Temperature,
|
|
/// True when the terrain is steep (high slope).
|
|
#[serde(rename = "minecraft:steep")]
|
|
Steep,
|
|
/// Inverts the inner condition.
|
|
#[serde(rename = "minecraft:not")]
|
|
Not {
|
|
/// The condition to invert.
|
|
invert: Box<Self>,
|
|
},
|
|
/// True when there is a hole (cave opening) at the position.
|
|
#[serde(rename = "minecraft:hole")]
|
|
Hole,
|
|
/// True when the position is above the preliminary surface estimate.
|
|
#[serde(rename = "minecraft:above_preliminary_surface")]
|
|
AbovePreliminarySurface,
|
|
/// True based on the depth of stone/ceiling relative to the surface.
|
|
#[serde(rename = "minecraft:stone_depth")]
|
|
StoneDepth {
|
|
/// Y offset added to the depth value.
|
|
offset: i32,
|
|
/// Whether to include surface depth in the calculation.
|
|
add_surface_depth: bool,
|
|
/// Additional secondary depth range.
|
|
secondary_depth_range: i32,
|
|
/// Surface type to measure from: `"ceiling"` or `"floor"`.
|
|
surface_type: String,
|
|
},
|
|
}
|
|
|
|
/// Deserialized Y offset that can be expressed relative to different reference points.
|
|
#[derive(Deserialize)]
|
|
#[serde(untagged)]
|
|
pub enum YOffsetStruct {
|
|
/// An absolute Y coordinate.
|
|
Absolute {
|
|
/// The absolute Y level.
|
|
absolute: i16,
|
|
},
|
|
/// A Y level measured upward from the dimension's minimum Y.
|
|
AboveBottom {
|
|
/// Number of blocks above the bottom of the dimension.
|
|
above_bottom: i8,
|
|
},
|
|
/// A Y level measured downward from the dimension's maximum Y.
|
|
BelowTop {
|
|
/// Number of blocks below the top of the dimension.
|
|
below_top: i8,
|
|
},
|
|
}
|
|
|
|
// --- ToTokens Implementations ---
|
|
|
|
impl ToTokens for BlockStateCodecStruct {
|
|
/// Emits a `BlockBlueprint` literal, stripping the `minecraft:` namespace prefix from the block name.
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
let name = &self.name.strip_prefix("minecraft:").unwrap_or(&self.name);
|
|
let name_stripped = name.strip_prefix("minecraft:").unwrap_or(name);
|
|
let block_ident =
|
|
quote::format_ident!("{}", name_stripped.to_uppercase().replace([':', '-'], "_"));
|
|
// TODO: use props
|
|
tokens.extend(quote! {
|
|
crate::Block::#block_ident.default_state
|
|
});
|
|
}
|
|
}
|
|
|
|
impl ToTokens for GenerationSettingsStruct {
|
|
/// Emits a `GenerationSettings` struct literal with all fields populated from the deserialized data.
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
let aquifers = self.aquifers_enabled;
|
|
let ores = self.ore_veins_enabled;
|
|
let legacy = self.legacy_random_source;
|
|
let sea_level = self.sea_level;
|
|
let fluid = &self.default_fluid;
|
|
let block = &self.default_block;
|
|
let shape = &self.shape;
|
|
let rule = &self.surface_rule;
|
|
|
|
tokens.extend(quote!(
|
|
GenerationSettings {
|
|
aquifers_enabled: #aquifers,
|
|
ore_veins_enabled: #ores,
|
|
legacy_random_source: #legacy,
|
|
sea_level: #sea_level,
|
|
default_fluid: #fluid,
|
|
shape: #shape,
|
|
surface_rule: #rule,
|
|
default_block: #block,
|
|
}
|
|
));
|
|
}
|
|
}
|
|
|
|
impl ToTokens for GenerationShapeConfigStruct {
|
|
/// Emits a `GenerationShapeConfig` struct literal with all noise-shape dimensions.
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
let min_y = self.min_y;
|
|
let height = self.height;
|
|
let hor = self.size_horizontal;
|
|
let ver = self.size_vertical;
|
|
tokens.extend(quote!(
|
|
GenerationShapeConfig { min_y: #min_y, height: #height, size_horizontal: #hor, size_vertical: #ver }
|
|
));
|
|
}
|
|
}
|
|
|
|
impl ToTokens for YOffsetStruct {
|
|
/// Emits a `YOffset` enum variant literal corresponding to the deserialized offset kind.
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
match self {
|
|
Self::Absolute { absolute } => {
|
|
tokens.extend(quote!(YOffset::Absolute(pumpkin_util::y_offset::Absolute { absolute: #absolute })));
|
|
}
|
|
Self::AboveBottom { above_bottom } => {
|
|
tokens.extend(quote!(YOffset::AboveBottom(pumpkin_util::y_offset::AboveBottom { above_bottom: #above_bottom })));
|
|
}
|
|
Self::BelowTop { below_top } => {
|
|
tokens.extend(quote!(YOffset::BelowTop(pumpkin_util::y_offset::BelowTop { below_top: #below_top })));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ToTokens for MaterialConditionStruct {
|
|
/// Emits a `MaterialCondition` enum variant literal for each surface condition kind.
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
match self {
|
|
Self::Biome { biome_is } => {
|
|
let biomes = biome_is
|
|
.iter()
|
|
.map(|b| b.strip_prefix("minecraft:").unwrap_or(b).to_uppercase());
|
|
let biome_refs: Vec<TokenStream> = biomes
|
|
.map(|b| {
|
|
let ident = format_ident!("{}", b);
|
|
quote!(&crate::biome::Biome::#ident)
|
|
})
|
|
.collect();
|
|
|
|
tokens.extend(quote!(
|
|
MaterialCondition::Biome(BiomeMaterialCondition {
|
|
biome_is: &[#(#biome_refs),*],
|
|
})
|
|
));
|
|
}
|
|
Self::NoiseThreshold {
|
|
noise,
|
|
min_threshold,
|
|
max_threshold,
|
|
} => {
|
|
let noise_id = quote::format_ident!(
|
|
"{}",
|
|
noise
|
|
.strip_prefix("minecraft:")
|
|
.unwrap()
|
|
.to_shouty_snake_case()
|
|
);
|
|
|
|
tokens.extend(quote!(
|
|
MaterialCondition::NoiseThreshold(NoiseThresholdMaterialCondition {
|
|
noise: DoublePerlinNoiseParameters::#noise_id,
|
|
min_threshold: #min_threshold,
|
|
max_threshold: #max_threshold,
|
|
})
|
|
));
|
|
}
|
|
Self::VerticalGradient {
|
|
random_name,
|
|
true_at_and_below,
|
|
false_at_and_above,
|
|
} => {
|
|
// Pre calc for speed :D
|
|
let bytes = md5::compute(random_name.as_bytes());
|
|
let lo = u64::from_be_bytes(bytes[0..8].try_into().expect("incorrect length"));
|
|
let hi = u64::from_be_bytes(bytes[8..16].try_into().expect("incorrect length"));
|
|
tokens.extend(quote!(
|
|
MaterialCondition::VerticalGradient(VerticalGradientMaterialCondition {
|
|
random_lo: #lo,
|
|
random_hi: #hi,
|
|
true_at_and_below: #true_at_and_below,
|
|
false_at_and_above: #false_at_and_above,
|
|
})
|
|
));
|
|
}
|
|
Self::YAbove {
|
|
anchor,
|
|
surface_depth_multiplier,
|
|
add_stone_depth,
|
|
} => {
|
|
tokens.extend(quote!(
|
|
MaterialCondition::YAbove(AboveYMaterialCondition {
|
|
anchor: #anchor,
|
|
surface_depth_multiplier: #surface_depth_multiplier,
|
|
add_stone_depth: #add_stone_depth,
|
|
})
|
|
));
|
|
}
|
|
Self::Water {
|
|
offset,
|
|
surface_depth_multiplier,
|
|
add_stone_depth,
|
|
} => {
|
|
tokens.extend(quote!(
|
|
MaterialCondition::Water(WaterMaterialCondition {
|
|
offset: #offset,
|
|
surface_depth_multiplier: #surface_depth_multiplier,
|
|
add_stone_depth: #add_stone_depth,
|
|
})
|
|
));
|
|
}
|
|
Self::Temperature => {
|
|
tokens.extend(quote!(MaterialCondition::Temperature));
|
|
}
|
|
Self::Steep => {
|
|
tokens.extend(quote!(MaterialCondition::Steep));
|
|
}
|
|
Self::Not { invert } => {
|
|
tokens.extend(quote!(
|
|
MaterialCondition::Not(NotMaterialCondition {
|
|
invert: &#invert,
|
|
})
|
|
));
|
|
}
|
|
Self::Hole => {
|
|
tokens.extend(quote!(MaterialCondition::Hole(HoleMaterialCondition)));
|
|
}
|
|
Self::AbovePreliminarySurface => {
|
|
tokens.extend(quote!(MaterialCondition::AbovePreliminarySurface(
|
|
SurfaceMaterialCondition
|
|
)));
|
|
}
|
|
Self::StoneDepth {
|
|
offset,
|
|
add_surface_depth,
|
|
secondary_depth_range,
|
|
surface_type,
|
|
} => {
|
|
let surface_type_token = match surface_type.as_str() {
|
|
"ceiling" => quote!(
|
|
pumpkin_util::math::vertical_surface_type::VerticalSurfaceType::Ceiling
|
|
),
|
|
"floor" => quote!(
|
|
pumpkin_util::math::vertical_surface_type::VerticalSurfaceType::Floor
|
|
),
|
|
_ => quote!(panic!("Unknown surface type")),
|
|
};
|
|
|
|
tokens.extend(quote!(
|
|
MaterialCondition::StoneDepth(StoneDepthMaterialCondition {
|
|
offset: #offset,
|
|
add_surface_depth: #add_surface_depth,
|
|
secondary_depth_range: #secondary_depth_range,
|
|
surface_type: #surface_type_token,
|
|
})
|
|
));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ToTokens for MaterialRuleStruct {
|
|
/// Emits a `MaterialRule` enum variant literal for each surface placement rule kind.
|
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
|
match self {
|
|
Self::Block { result_state } => {
|
|
tokens.extend(quote!(
|
|
MaterialRule::Block(BlockMaterialRule {
|
|
result_state: #result_state
|
|
})
|
|
));
|
|
}
|
|
Self::Sequence { sequence } => {
|
|
tokens.extend(quote!(
|
|
MaterialRule::Sequence(SequenceMaterialRule {
|
|
sequence: &[#(#sequence),*]
|
|
})
|
|
));
|
|
}
|
|
Self::Condition { if_true, then_run } => {
|
|
tokens.extend(quote!(
|
|
MaterialRule::Condition(ConditionMaterialRule {
|
|
if_true: #if_true,
|
|
then_run: &#then_run
|
|
})
|
|
));
|
|
}
|
|
Self::Badlands => {
|
|
tokens.extend(quote!(MaterialRule::Badlands(BadLandsMaterialRule)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Reads `chunk_gen_settings.json` and emits the complete chunk generation settings `TokenStream`.
|
|
pub fn build() -> TokenStream {
|
|
let json: BTreeMap<String, GenerationSettingsStruct> =
|
|
serde_json::from_str(&fs::read_to_string("../assets/chunk_gen_settings.json").unwrap())
|
|
.expect("Failed to parse settings.json");
|
|
|
|
let mut const_defs = TokenStream::new();
|
|
|
|
for (name, settings) in &json {
|
|
let upper_name = name.to_uppercase();
|
|
let const_name = format_ident!("{}", upper_name);
|
|
|
|
const_defs.extend(quote!(
|
|
pub const #const_name: GenerationSettings = #settings;
|
|
));
|
|
}
|
|
|
|
quote!(
|
|
use crate::dimension::Dimension;
|
|
use crate::chunk::DoublePerlinNoiseParameters;
|
|
use crate::BlockState;
|
|
|
|
use std::{cell::RefCell, num::NonZeroUsize};
|
|
use pumpkin_util::random::RandomDeriver;
|
|
use pumpkin_util::y_offset::YOffset;
|
|
use crate::biome::Biome;
|
|
use pumpkin_util::y_offset::Absolute;
|
|
|
|
pub struct GenerationSettings {
|
|
pub aquifers_enabled: bool,
|
|
pub ore_veins_enabled: bool,
|
|
pub legacy_random_source: bool,
|
|
pub sea_level: i32,
|
|
pub default_fluid: &'static BlockState,
|
|
pub shape: GenerationShapeConfig,
|
|
pub surface_rule: MaterialRule,
|
|
pub default_block: &'static BlockState,
|
|
}
|
|
|
|
pub struct GenerationShapeConfig {
|
|
pub min_y: i8,
|
|
pub height: u16,
|
|
pub size_horizontal: u8,
|
|
pub size_vertical: u8,
|
|
}
|
|
|
|
impl GenerationShapeConfig {
|
|
#[inline]
|
|
#[must_use]
|
|
pub const fn vertical_cell_block_count(&self) -> u8 { self.size_vertical << 2 }
|
|
|
|
#[inline]
|
|
#[must_use]
|
|
pub const fn horizontal_cell_block_count(&self) -> u8 { self.size_horizontal << 2 }
|
|
|
|
#[must_use]
|
|
pub const fn max_y(&self) -> u16 {
|
|
if self.min_y >= 0 {
|
|
self.height + self.min_y as u16
|
|
} else {
|
|
(self.height as i32 + self.min_y as i32) as u16
|
|
}
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn trim_height(&self, bottom_y: i8, top_y: u16) -> Self {
|
|
let new_min = self.min_y.max(bottom_y);
|
|
let this_top = if self.min_y >= 0 {
|
|
self.height + self.min_y as u16
|
|
} else {
|
|
self.height - self.min_y.unsigned_abs() as u16
|
|
};
|
|
let new_top = this_top.min(top_y);
|
|
let new_height = if new_min >= 0 {
|
|
new_top - new_min as u16
|
|
} else {
|
|
new_top + new_min.unsigned_abs() as u16
|
|
};
|
|
|
|
Self {
|
|
min_y: new_min,
|
|
height: new_height,
|
|
size_horizontal: self.size_horizontal,
|
|
size_vertical: self.size_vertical,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct BlockMaterialRule {
|
|
pub result_state: &'static BlockState,
|
|
}
|
|
|
|
pub struct SequenceMaterialRule {
|
|
pub sequence: &'static [MaterialRule],
|
|
}
|
|
|
|
pub struct ConditionMaterialRule {
|
|
pub if_true: MaterialCondition,
|
|
pub then_run: &'static MaterialRule,
|
|
}
|
|
|
|
pub struct BadLandsMaterialRule;
|
|
|
|
pub enum MaterialRule {
|
|
Block(BlockMaterialRule),
|
|
Sequence(SequenceMaterialRule),
|
|
Condition(ConditionMaterialRule),
|
|
Badlands(BadLandsMaterialRule),
|
|
}
|
|
|
|
|
|
pub struct BiomeMaterialCondition {
|
|
pub biome_is: &'static [&'static Biome],
|
|
}
|
|
|
|
pub struct NoiseThresholdMaterialCondition {
|
|
pub noise: DoublePerlinNoiseParameters,
|
|
pub min_threshold: f64,
|
|
pub max_threshold: f64,
|
|
}
|
|
|
|
pub struct VerticalGradientMaterialCondition {
|
|
pub random_lo: u64,
|
|
pub random_hi: u64,
|
|
pub true_at_and_below: YOffset,
|
|
pub false_at_and_above: YOffset,
|
|
}
|
|
|
|
pub struct AboveYMaterialCondition {
|
|
pub anchor: YOffset,
|
|
pub surface_depth_multiplier: i32,
|
|
pub add_stone_depth: bool,
|
|
}
|
|
|
|
pub struct WaterMaterialCondition {
|
|
pub offset: i32,
|
|
pub surface_depth_multiplier: i32,
|
|
pub add_stone_depth: bool,
|
|
}
|
|
|
|
pub struct HoleMaterialCondition;
|
|
|
|
pub struct NotMaterialCondition {
|
|
pub invert: &'static MaterialCondition,
|
|
}
|
|
|
|
pub struct SurfaceMaterialCondition;
|
|
|
|
pub struct StoneDepthMaterialCondition {
|
|
pub offset: i32,
|
|
pub add_surface_depth: bool,
|
|
pub secondary_depth_range: i32,
|
|
pub surface_type: pumpkin_util::math::vertical_surface_type::VerticalSurfaceType,
|
|
}
|
|
|
|
pub enum MaterialCondition {
|
|
Biome(BiomeMaterialCondition),
|
|
NoiseThreshold(NoiseThresholdMaterialCondition),
|
|
VerticalGradient(VerticalGradientMaterialCondition),
|
|
YAbove(AboveYMaterialCondition),
|
|
Water(WaterMaterialCondition),
|
|
Temperature,
|
|
Steep,
|
|
Not(NotMaterialCondition),
|
|
Hole(HoleMaterialCondition),
|
|
AbovePreliminarySurface(SurfaceMaterialCondition),
|
|
StoneDepth(StoneDepthMaterialCondition),
|
|
}
|
|
|
|
impl GenerationSettings {
|
|
#const_defs
|
|
|
|
#[must_use]
|
|
pub fn from_dimension(dimension: &Dimension) -> &'static Self {
|
|
if dimension == &Dimension::OVERWORLD {
|
|
&Self::OVERWORLD
|
|
} else if dimension == &Dimension::THE_NETHER {
|
|
&Self::NETHER
|
|
} else {
|
|
&Self::END
|
|
}
|
|
}
|
|
}
|
|
)
|
|
}
|