diff --git a/.gitignore b/.gitignore index 1b74c34..3fe08f4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ /output.log /target /world +/server-icon.png diff --git a/Cargo.lock b/Cargo.lock index 2465327..b191eac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -89,11 +89,13 @@ dependencies = [ "async-trait", "chrono", "fern", + "lazy_static", "log", "radix64", "serde", "serde_json", "tokio", + "toml", ] [[package]] @@ -423,6 +425,15 @@ dependencies = [ "syn", ] +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde", +] + [[package]] name = "unicode-xid" version = "0.2.1" diff --git a/Cargo.toml b/Cargo.toml index bc945fd..2c4532d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "composition" version = "0.1.0" -authors = ["ElementG9 "] +authors = ["Garen Tyler "] edition = "2018" [dependencies] @@ -10,11 +10,12 @@ fern = { version = "0.6", features = ["colored"] } chrono = "0.4.13" serde = { version = "1.0.114", features = ["serde_derive"]} serde_json = "1.0.59" +toml = "0.5" radix64 = "0.3.0" tokio = { version = "1", features = ["full"] } async-trait = "0.1.42" +lazy_static = "1.4.0" # colorful = "0.2.1" -# lazy_static = "1.4.0" # ozelot = "0.9.0" # Ozelot 0.9.0 supports protocol version 578 (1.15.2) # toml = "0.5.6" # base64 = "0.12.3" diff --git a/src/lib.rs b/src/lib.rs index 6808bca..5c2ed6c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,6 @@ +#[macro_use] +extern crate lazy_static; + /// Data types for every entity in the game. pub mod entity; /// Implementations of the data types needed for the Minecraft protocol. @@ -8,6 +11,50 @@ pub mod server; pub mod world; pub use mctypes::*; +use serde::{Serialize, Deserialize}; +use log::warn; + +#[derive(Serialize, Deserialize)] +pub struct Config { + pub port: u16, + pub max_players: usize, + pub motd: String, + pub favicon: String, +} + +lazy_static! { + static ref CONFIG: Config = { + let config_from_file = || -> std::io::Result { + use std::{fs::File, io::prelude::*}; + let mut data = String::new(); + let mut file = File::open("composition.toml")?; + file.read_to_string(&mut data)?; + if let Ok(c) = toml::from_str::(&data) { + Ok(c) + } else { + Err(std::io::Error::new(std::io::ErrorKind::Other, "Could not parse toml")) + } + }; + if let Ok(c) = config_from_file() { + c + } else { + warn!("Could not load config from file, using default"); + Config { + port: 25565, + max_players: 20, + motd: "Hello world!".to_owned(), + favicon: "server-icon.png".to_owned(), + } + } + }; + static ref FAVICON: std::io::Result> = { + use std::{fs::File, io::prelude::*}; + let mut data = vec![]; + let mut file = File::open(CONFIG.favicon.clone())?; + file.read_to_end(&mut data)?; + Ok(data) + }; +} /// Set up logging, read the config file, etc. pub fn init() { @@ -36,7 +83,7 @@ pub fn init() { /// Start the server. pub async fn start_server() -> server::GameServer { // Start the network. - let network = server::net::NetworkServer::new("0.0.0.0:25565"); + let network = server::net::NetworkServer::new(format!("0.0.0.0:{}", CONFIG.port)); let server = server::GameServer { network: network }; server } diff --git a/src/server-icon.png b/src/server-icon.png deleted file mode 100644 index 4ef7bdb..0000000 Binary files a/src/server-icon.png and /dev/null differ diff --git a/src/server/net/mod.rs b/src/server/net/mod.rs index a792def..88b9a08 100644 --- a/src/server/net/mod.rs +++ b/src/server/net/mod.rs @@ -1,7 +1,7 @@ /// Definitions for all the packets in the Minecraft protocol. pub mod packets; -use crate::mctypes::*; +use crate::{mctypes::*, CONFIG, FAVICON}; use log::{debug, info}; use packets::*; use serde_json::json; @@ -127,7 +127,7 @@ impl NetworkClient { "protocol": 47, }, "players": { - "max": 100, + "max": CONFIG.max_players, "online": 5, "sample": [ { @@ -137,10 +137,10 @@ impl NetworkClient { ] }, "description": { - "text": "Hello world!" + "text": CONFIG.motd }, // TODO: Dynamically send the icon instead of linking statically. - "favicon": format!("data:image/png;base64,{}", radix64::STD.encode(include_bytes!("../../server-icon.png"))) + "favicon": format!("data:image/png;base64,{}", if FAVICON.is_ok() { radix64::STD.encode(FAVICON.as_ref().unwrap().as_slice()) } else { "".to_owned() }) }) .to_string() .into();