use std::collections::HashMap;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct YogDimensionTypeDef {
pub min_y: i32,
pub height: i32,
pub logical_height: i32,
pub has_sky_light: bool,
pub sky_light_updates: bool,
pub ambient_light: f32,
pub coordinate_scale: f32,
pub ultrawarm: bool,
pub beds_explode: bool,
pub respawn_anchors_explode: bool,
pub piglin_safe: bool,
pub natural: bool,
pub has_ceiling: bool,
pub effects: String,
pub has_sky: bool,
pub has_clouds: bool,
pub cloud_height: f64,
pub has_fog: bool,
pub fog_color: Option<i32>,
pub sky_color: Option<i32>,
pub water_color: Option<i32>,
pub water_fog_color: Option<i32>,
}
impl Default for YogDimensionTypeDef {
fn default() -> Self {
Self {
min_y: -64,
height: 384,
logical_height: 384,
has_sky_light: true,
sky_light_updates: true,
ambient_light: 0.0,
coordinate_scale: 1.0,
ultrawarm: false,
beds_explode: false,
respawn_anchors_explode: false,
piglin_safe: false,
natural: true,
has_ceiling: false,
effects: "overworld".to_owned(),
has_sky: true,
has_clouds: true,
cloud_height: 192.0,
has_fog: false,
fog_color: None,
sky_color: None,
water_color: None,
water_fog_color: None,
}
}
}
impl YogDimensionTypeDef {
pub fn min_y(mut self, v: i32) -> Self {
self.min_y = v;
self
}
pub fn height(mut self, v: i32) -> Self {
self.height = v;
self.logical_height = v;
self
}
pub fn logical_height(mut self, v: i32) -> Self {
self.logical_height = v;
self
}
pub fn has_sky_light(mut self, v: bool) -> Self {
self.has_sky_light = v;
self
}
pub fn sky_light_updates(mut self, v: bool) -> Self {
self.sky_light_updates = v;
self
}
pub fn ambient_light(mut self, v: f32) -> Self {
self.ambient_light = v;
self
}
pub fn coordinate_scale(mut self, v: f32) -> Self {
self.coordinate_scale = v;
self
}
pub fn ultrawarm(mut self, v: bool) -> Self {
self.ultrawarm = v;
self
}
pub fn beds_explode(mut self, v: bool) -> Self {
self.beds_explode = v;
self
}
pub fn respawn_anchors_explode(mut self, v: bool) -> Self {
self.respawn_anchors_explode = v;
self
}
pub fn piglin_safe(mut self, v: bool) -> Self {
self.piglin_safe = v;
self
}
pub fn natural(mut self, v: bool) -> Self {
self.natural = v;
self
}
pub fn has_ceiling(mut self, v: bool) -> Self {
self.has_ceiling = v;
self
}
pub fn effects(mut self, v: impl Into<String>) -> Self {
self.effects = v.into();
self
}
pub fn has_sky(mut self, v: bool) -> Self {
self.has_sky = v;
self
}
pub fn has_clouds(mut self, v: bool) -> Self {
self.has_clouds = v;
self
}
pub fn cloud_height(mut self, v: f64) -> Self {
self.cloud_height = v;
self
}
pub fn has_fog(mut self, v: bool) -> Self {
self.has_fog = v;
self
}
pub fn fog_color(mut self, v: i32) -> Self {
self.fog_color = Some(v);
self
}
pub fn sky_color(mut self, v: i32) -> Self {
self.sky_color = Some(v);
self
}
pub fn water_color(mut self, v: i32) -> Self {
self.water_color = Some(v);
self
}
pub fn water_fog_color(mut self, v: i32) -> Self {
self.water_fog_color = Some(v);
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct YogDimensionDef {
pub id: String,
pub dimension_type: YogDimensionTypeDef,
pub generator_type: Option<String>,
pub biome: String,
pub structures: bool,
pub features: bool,
pub mob_spawning: bool,
pub extra: HashMap<String, String>,
}
impl Default for YogDimensionDef {
fn default() -> Self {
Self {
id: String::new(),
dimension_type: YogDimensionTypeDef::default(),
generator_type: None,
biome: "minecraft:plains".into(),
structures: true,
features: true,
mob_spawning: true,
extra: HashMap::new(),
}
}
}
impl YogDimensionDef {
pub fn new(id: impl Into<String>) -> Self {
Self {
id: id.into(),
..Self::default()
}
}
pub fn dimension_type(mut self, dimension_type: YogDimensionTypeDef) -> Self {
self.dimension_type = dimension_type;
self
}
pub fn generator_type(mut self, generator_type_id: impl Into<String>) -> Self {
self.generator_type = Some(generator_type_id.into());
self
}
pub fn biome(mut self, biome: impl Into<String>) -> Self {
self.biome = biome.into();
self
}
pub fn structures(mut self, on: bool) -> Self {
self.structures = on;
self
}
pub fn features(mut self, on: bool) -> Self {
self.features = on;
self
}
pub fn mob_spawning(mut self, on: bool) -> Self {
self.mob_spawning = on;
self
}
pub fn with_extra(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.extra.insert(key.into(), value.into());
self
}
pub fn to_json(&self) -> String {
serde_json::to_string(self).expect("YogDimensionDef serializes infallibly")
}
}
pub struct ChunkWriter(*const yog_abi::YogChunkWriterApi);
impl ChunkWriter {
#[doc(hidden)]
pub unsafe fn from_raw(raw: *const yog_abi::YogChunkWriterApi) -> Self {
Self(raw)
}
#[inline]
fn api(&self) -> &yog_abi::YogChunkWriterApi {
unsafe { &*self.0 }
}
pub fn chunk_x(&self) -> i32 {
self.api().chunk_x
}
pub fn chunk_z(&self) -> i32 {
self.api().chunk_z
}
pub fn min_y(&self) -> i32 {
self.api().min_y
}
pub fn height(&self) -> i32 {
self.api().height
}
pub fn set_block(&self, x: i32, y: i32, z: i32, block_id: &str) -> bool {
let api = self.api();
unsafe { (api.set_block)(api.ctx, x, y, z, yog_abi::YogStr::from_str(block_id)) }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn dimension_def_to_json_roundtrips_through_serde() {
let def = YogDimensionDef::new("mymod:my_dim")
.dimension_type(
YogDimensionTypeDef::default()
.ultrawarm(true)
.effects("nether"),
)
.generator_type("mymod:custom_terrain")
.with_extra("note", "test");
let json = def.to_json();
let back: YogDimensionDef = serde_json::from_str(&json).expect("valid json");
assert_eq!(back.id, "mymod:my_dim");
assert!(back.dimension_type.ultrawarm);
assert_eq!(back.dimension_type.effects, "nether");
assert_eq!(back.generator_type.as_deref(), Some("mymod:custom_terrain"));
assert_eq!(back.extra.get("note").map(String::as_str), Some("test"));
}
#[test]
fn dimension_def_can_target_a_vanilla_id_to_patch_it() {
let def =
YogDimensionDef::new("minecraft:overworld").generator_type("mymod:custom_terrain");
assert_eq!(def.id, "minecraft:overworld");
assert_eq!(def.generator_type.as_deref(), Some("mymod:custom_terrain"));
}
}