diff --git a/Cargo.lock b/Cargo.lock index 88afc84..3685eb4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -88,6 +88,7 @@ dependencies = [ "flate2", "half", "internment", + "optional_struct", "parking_lot", "rand", "safer-bytes", @@ -247,6 +248,37 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "optional_struct" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cc83044fbb5cf2dfbf5bbe011f1ce6c68ce1c7f0c41423091e2c3b21c7ebb66" +dependencies = [ + "optional_struct_export", + "serde", +] + +[[package]] +name = "optional_struct_export" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3aab351802d85e41a5e679e6862c7639726920c7b93fbd2a7aec925509c088ed" +dependencies = [ + "optional_struct_macro_impl", + "quote", +] + +[[package]] +name = "optional_struct_macro_impl" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d8ed6022d195dd0ab66d5d214eddbe887ef5489f708ff8be131296111d475ef" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "parking_lot" version = "0.12.1" diff --git a/Cargo.toml b/Cargo.toml index 2128780..276863a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,11 +4,12 @@ name = "classics" version = "0.1.0" [dependencies] -bytes = "1.6.0" +bytes = "1" flate2 = "1" half = "2" -internment = { version = "0.8", features = ["serde"] } -parking_lot = "0.12.1" +internment = {version = "0.8", features = ["serde"]} +optional_struct = "0.4" +parking_lot = "0.12" rand = "0.8" safer-bytes = "0.2" serde = {version = "1", features = ["derive"]} diff --git a/src/level/generation.rs b/src/level/generation.rs index 86b9f51..1fc0719 100644 --- a/src/level/generation.rs +++ b/src/level/generation.rs @@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize}; use super::{block::BLOCK_STRING_ID_MAP, Level}; /// enum for different kinds of level generation -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(tag = "type")] pub enum LevelGeneration { /// an empty level @@ -17,7 +17,7 @@ pub enum LevelGeneration { } /// enum for level presents -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(tag = "flat_type")] pub enum FlatPreset { /// the level is mostly stone, then dirt, then a layer of grass on the top @@ -27,7 +27,7 @@ pub enum FlatPreset { } /// description of a flat world's layer -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct FlatLayer { /// the block for the layer pub block: String, diff --git a/src/main.rs b/src/main.rs index 46b9613..d4e46ae 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,10 @@ use std::path::PathBuf; -use server::{config::ServerConfig, Server}; +use server::{ + config::{OptionalServerConfig, ServerConfig}, + Server, +}; mod level; mod packet; @@ -15,16 +18,16 @@ const CONFIG_FILE: &str = "./server-config.json"; async fn main() -> std::io::Result<()> { let config_path = PathBuf::from(CONFIG_FILE); let config = if config_path.exists() { - serde_json::from_str(&std::fs::read_to_string(config_path)?) + serde_json::from_str::(&std::fs::read_to_string(&config_path)?) .expect("failed to deserialize config") + .build_default() } else { - let config = ServerConfig::default(); - std::fs::write( - config_path, - serde_json::to_string_pretty(&config).expect("failed to serialize default config"), - )?; - config + ServerConfig::default() }; + std::fs::write( + config_path, + serde_json::to_string_pretty(&config).expect("failed to serialize default config"), + )?; println!("starting server with config: {config:#?}"); diff --git a/src/server.rs b/src/server.rs index 904b677..e088072 100644 --- a/src/server.rs +++ b/src/server.rs @@ -9,8 +9,6 @@ use crate::{level::Level, player::Player}; use self::config::ServerConfig; -const DEFAULT_SERVER_SIZE: usize = 128; - /// the server #[derive(Debug)] pub struct Server { @@ -38,16 +36,11 @@ impl Server { pub async fn new(config: ServerConfig) -> std::io::Result { println!("generating level"); let mut rng = rand::thread_rng(); - let (level_x, level_y, level_z) = if let Some(size) = &config.level_size { - (size.x, size.y, size.z) - } else { - ( - DEFAULT_SERVER_SIZE, - DEFAULT_SERVER_SIZE, - DEFAULT_SERVER_SIZE, - ) - }; - let mut level = Level::new(level_x, level_y, level_z); + let mut level = Level::new( + config.level_size.x, + config.level_size.y, + config.level_size.z, + ); config.generation.generate(&mut level, &mut rng); println!("done!"); diff --git a/src/server/config.rs b/src/server/config.rs index 810f54b..2022840 100644 --- a/src/server/config.rs +++ b/src/server/config.rs @@ -1,10 +1,12 @@ use std::collections::BTreeMap; +use optional_struct::optional_struct; use serde::{Deserialize, Serialize}; use crate::level::generation::LevelGeneration; /// configuration for the server +#[optional_struct] #[derive(Debug, Serialize, Deserialize)] pub struct ServerConfig { /// the server's name @@ -15,28 +17,39 @@ pub struct ServerConfig { #[serde(rename = "password")] pub protection_mode: ServerProtectionMode, /// the level's size - pub level_size: Option, + pub level_size: ConfigCoordinates, /// the level's spawn point pub spawn: Option, /// the method to generate the server's level with pub generation: LevelGeneration, } +impl OptionalServerConfig { + /// builds the server config filling with default options + pub fn build_default(self) -> ServerConfig { + self.build(Default::default()) + } +} + impl Default for ServerConfig { fn default() -> Self { Self { name: "classic server wowie".to_string(), motd: "here's the default server motd".to_string(), protection_mode: ServerProtectionMode::None, - level_size: None, + level_size: ConfigCoordinates { + x: 256, + y: 64, + z: 256, + }, spawn: None, - generation: LevelGeneration::Empty, + generation: LevelGeneration::Flat(crate::level::generation::FlatPreset::StoneAndGrass), } } } /// coordinates as stored in configuration -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct ConfigCoordinates { /// the X coordinate pub x: usize, @@ -47,7 +60,7 @@ pub struct ConfigCoordinates { } /// enum for the different kinds of server protection -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(untagged)] pub enum ServerProtectionMode { /// the server is unprotected and anyone can join with any username