diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 7fc84ba..0000000 --- a/.editorconfig +++ /dev/null @@ -1,17 +0,0 @@ -# EditorConfig is awesome: http://EditorConfig.org - -root = true - -[*] -indent_style = space -indent_size = 4 -trim_trailing_whitespace = true -insert_final_newline = true -end_of_line = lf - -[*.md] -trim_trailing_whitespace = false - -[Makefile] -indent_style = tab -trim_trailing_whitespace = false diff --git a/.gitignore b/.gitignore index 4ae8070..73e70f0 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ release/ rls/ *.o .vscode/ - +perf.data # Generated by Cargo # will have compiled files and executables debug/ @@ -108,19 +108,19 @@ fabric.properties .idea/caches/build_file_checksums.ser .idea/ + + # different file generated by the server -# World folder -world/* -world/DIM1/ -world/DIM-1/ -world/region/ -# logs folder +# World directories +world/ + +# Logs directory logs/ -#conf files +# Configuration files ops.json whitelist.json banned-ips.json @@ -128,5 +128,11 @@ banned-players.json usercache.json session.lock version.json -server.properties +*.properties eula.txt + +# macOS files +.DS_Store + +# Other +.editorconfig diff --git a/Cargo.lock b/Cargo.lock index d3224b3..fd4b542 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -182,6 +182,46 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "clap" +version = "4.5.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + [[package]] name = "colorchoice" version = "1.0.2" @@ -203,6 +243,7 @@ name = "copper_server" version = "0.1.0" dependencies = [ "chrono", + "clap", "colored", "ctrlc", "dot-properties", @@ -416,6 +457,12 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.3.9" @@ -1255,6 +1302,12 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "subtle" version = "2.6.1" diff --git a/Cargo.toml b/Cargo.toml index bc9547e..f98f741 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ tempfile = "3.12.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.127" reqwest = { version = "0.12.7", features = ["json", "rustls-tls"] } +clap = { version = "4.5.17", features = ["derive"] } [profile.release] opt-level = 3 # optimiosation level 3 is the best debug = false diff --git a/README.md b/README.md index e1c5daf..917fe28 100644 --- a/README.md +++ b/README.md @@ -48,4 +48,4 @@ Copper is licensed under the Mozilla Public License Version 2.0. See the `LICENS --- -For any questions or comments, feel free to open an issue or contact me directly at the email: [minecraft.copper@proton.me](mailto:minecraft.copper@proton.me) +For any questions or comments, feel free to open an issue or contact me directly at the email: [minecraft.copper@proton.me](mailto:minecraft.cactus@proton.me) diff --git a/TODO.md b/TODO.md index 8fe978c..b02a396 100644 --- a/TODO.md +++ b/TODO.md @@ -13,3 +13,86 @@ - [ ] Somehow get a player to connect +# Issues +- [ ] resolve this memory leak +spectre@fedora:~/RustProject/CopperMC$ valgrind --tool=memcheck --leak-check=full ./target/release/copper_server +==20441== Memcheck, a memory error detector +==20441== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al. +==20441== Using Valgrind-3.23.0 and LibVEX; rerun with -h for copyright info +==20441== Command: ./target/release/copper_server +==20441== +[2024-09-25T07:26:15Z INFO copper_server] Starting minecraft server version 1.21.1 +[2024-09-25T07:26:15Z INFO copper_server] Hello, world from Copper! +[2024-09-25T07:26:15Z ERROR copper_server::fs_manager] Cannot start the server, please agree to the 'eula.txt' +[2024-09-25T07:26:15Z WARN copper_server] [ SERVER SHUTDOWN WITH CODE: -1] +==20441== +==20441== HEAP SUMMARY: +==20441== in use at exit: 103,256 bytes in 172 blocks +==20441== total heap usage: 289 allocs, 117 frees, 118,951 bytes allocated +==20441== +==20441== 280 bytes in 1 blocks are possibly lost in loss record 42 of 60 +==20441== at 0x4843866: malloc (vg_replace_malloc.c:446) +==20441== by 0x1455A3: hashbrown::raw::RawTable::reserve_rehash (in /home/spectre/RustProject/CopperMC/target/release/copper_server) +==20441== by 0x36DF4B: tokio::runtime::blocking::pool::Spawner::spawn_task (in /home/spectre/RustProject/CopperMC/target/release/copper_server) +==20441== by 0x363AA8: tokio::runtime::builder::Builder::build (in /home/spectre/RustProject/CopperMC/target/release/copper_server) +==20441== by 0x16EFF4: copper_server::main (in /home/spectre/RustProject/CopperMC/target/release/copper_server) +==20441== by 0x17A502: std::sys::backtrace::__rust_begin_short_backtrace (in /home/spectre/RustProject/CopperMC/target/release/copper_server) +==20441== by 0x16ECAC: main (in /home/spectre/RustProject/CopperMC/target/release/copper_server) +==20441== +==20441== 304 bytes in 1 blocks are possibly lost in loss record 43 of 60 +==20441== at 0x484B133: calloc (vg_replace_malloc.c:1675) +==20441== by 0x4011FE3: UnknownInlinedFun (rtld-malloc.h:44) +==20441== by 0x4011FE3: allocate_dtv (dl-tls.c:370) +==20441== by 0x4012A71: _dl_allocate_tls (dl-tls.c:629) +==20441== by 0x4FA2233: allocate_stack (allocatestack.c:429) +==20441== by 0x4FA2233: pthread_create@@GLIBC_2.34 (pthread_create.c:655) +==20441== by 0x3526A9: std::sys::pal::unix::thread::Thread::new (in /home/spectre/RustProject/CopperMC/target/release/copper_server) +==20441== by 0x16E031: copper_server::init_ctrlc_handler (in /home/spectre/RustProject/CopperMC/target/release/copper_server) +==20441== by 0x16F674: copper_server::main (in /home/spectre/RustProject/CopperMC/target/release/copper_server) +==20441== by 0x17A502: std::sys::backtrace::__rust_begin_short_backtrace (in /home/spectre/RustProject/CopperMC/target/release/copper_server) +==20441== by 0x16ECAC: main (in /home/spectre/RustProject/CopperMC/target/release/copper_server) +==20441== +==20441== 304 bytes in 1 blocks are possibly lost in loss record 44 of 60 +==20441== at 0x484B133: calloc (vg_replace_malloc.c:1675) +==20441== by 0x4011FE3: UnknownInlinedFun (rtld-malloc.h:44) +==20441== by 0x4011FE3: allocate_dtv (dl-tls.c:370) +==20441== by 0x4012A71: _dl_allocate_tls (dl-tls.c:629) +==20441== by 0x4FA2233: allocate_stack (allocatestack.c:429) +==20441== by 0x4FA2233: pthread_create@@GLIBC_2.34 (pthread_create.c:655) +==20441== by 0x3526A9: std::sys::pal::unix::thread::Thread::new (in /home/spectre/RustProject/CopperMC/target/release/copper_server) +==20441== by 0x36DEB0: tokio::runtime::blocking::pool::Spawner::spawn_task (in /home/spectre/RustProject/CopperMC/target/release/copper_server) +==20441== by 0x181CC8: copper_server::commands::command_line::handle_input::{{closure}} (in /home/spectre/RustProject/CopperMC/target/release/copper_server) +==20441== by 0x1814C7: tokio::runtime::task::core::Core::poll (in /home/spectre/RustProject/CopperMC/target/release/copper_server) +==20441== by 0x149521: tokio::runtime::task::raw::poll (in /home/spectre/RustProject/CopperMC/target/release/copper_server) +==20441== by 0x355454: tokio::runtime::scheduler::multi_thread::worker::Context::run_task (in /home/spectre/RustProject/CopperMC/target/release/copper_server) +==20441== by 0x3594C3: tokio::runtime::task::raw::poll (in /home/spectre/RustProject/CopperMC/target/release/copper_server) +==20441== by 0x35BBB6: std::sys::backtrace::__rust_begin_short_backtrace (in /home/spectre/RustProject/CopperMC/target/release/copper_server) +==20441== +==20441== 1,216 bytes in 4 blocks are possibly lost in loss record 51 of 60 +==20441== at 0x484B133: calloc (vg_replace_malloc.c:1675) +==20441== by 0x4011FE3: UnknownInlinedFun (rtld-malloc.h:44) +==20441== by 0x4011FE3: allocate_dtv (dl-tls.c:370) +==20441== by 0x4012A71: _dl_allocate_tls (dl-tls.c:629) +==20441== by 0x4FA2233: allocate_stack (allocatestack.c:429) +==20441== by 0x4FA2233: pthread_create@@GLIBC_2.34 (pthread_create.c:655) +==20441== by 0x3526A9: std::sys::pal::unix::thread::Thread::new (in /home/spectre/RustProject/CopperMC/target/release/copper_server) +==20441== by 0x36DEB0: tokio::runtime::blocking::pool::Spawner::spawn_task (in /home/spectre/RustProject/CopperMC/target/release/copper_server) +==20441== by 0x363AA8: tokio::runtime::builder::Builder::build (in /home/spectre/RustProject/CopperMC/target/release/copper_server) +==20441== by 0x16EFF4: copper_server::main (in /home/spectre/RustProject/CopperMC/target/release/copper_server) +==20441== by 0x17A502: std::sys::backtrace::__rust_begin_short_backtrace (in /home/spectre/RustProject/CopperMC/target/release/copper_server) +==20441== by 0x16ECAC: main (in /home/spectre/RustProject/CopperMC/target/release/copper_server) +==20441== +==20441== LEAK SUMMARY: +==20441== definitely lost: 0 bytes in 0 blocks +==20441== indirectly lost: 0 bytes in 0 blocks +==20441== possibly lost: 2,104 bytes in 7 blocks +==20441== still reachable: 101,152 bytes in 165 blocks +==20441== suppressed: 0 bytes in 0 blocks +==20441== Reachable blocks (those to which a pointer was found) are not shown. +==20441== To see them, rerun with: --leak-check=full --show-leak-kinds=all +==20441== +==20441== For lists of detected and suppressed errors, rerun with: -s +==20441== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0) +spectre@fedora:~/RustProject/CopperMC$ + + diff --git a/perf.data b/perf.data new file mode 100644 index 0000000..04a5759 Binary files /dev/null and b/perf.data differ diff --git a/src/args/mod.rs b/src/args/mod.rs new file mode 100644 index 0000000..809c91c --- /dev/null +++ b/src/args/mod.rs @@ -0,0 +1,28 @@ +use crate::fs_manager; +use clap::Parser; +use log::error; + +#[derive(Parser)] +#[command(name = "CopperMC")] +#[command(about = "This is the about, please change", long_about = None)] +struct Cli { + /// Removes all files related to the server, excluding the server. + #[arg(short, long)] + remove_files: Option, +} + +/// Retrieves args and initializes the argument parsing logic. +pub fn init() { + let args = Cli::parse(); + + parse_args(args); +} + +/// Parses args and calls the appropriate functions. +fn parse_args(args: Cli) { + if let Some(_) = args.remove_files { + if let Err(e) = fs_manager::clean_files() { + error!("Error(s) when cleaning files: {e}"); + } + } +} diff --git a/src/commands/command_line.rs b/src/commands/command_line.rs index c906560..8d1a0bd 100644 --- a/src/commands/command_line.rs +++ b/src/commands/command_line.rs @@ -41,8 +41,8 @@ pub async fn handle_input() -> ! { }; let content = match fs_manager::write_ops_json( &consts::filepaths::OPERATORS, - uuid.as_str(), - element, + &uuid.as_str(), + &element, 4, true, ) { diff --git a/src/config/mod.rs b/src/config/mod.rs index e125ff0..a165b66 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -66,7 +66,7 @@ pub struct Settings { max_tick_time: i64, require_resource_pack: bool, use_native_transport: bool, - max_players: u32, + pub max_players: u32, online_mode: bool, enable_status: bool, allow_flight: bool, @@ -134,7 +134,12 @@ impl Settings { "" => None, s => Some(s.parse::().unwrap()), }, - gamemode: match config_file.get_property("gamemode").unwrap().to_lowercase().as_str() { + gamemode: match config_file + .get_property("gamemode") + .unwrap() + .to_lowercase() + .as_str() + { "creative" => Gamemode::CREATIVE, "survival" => Gamemode::SURVIVAL, "spectator" => Gamemode::SPECTATOR, diff --git a/src/consts/mod.rs b/src/consts/mod.rs index 5f2d4a5..88cc5e5 100644 --- a/src/consts/mod.rs +++ b/src/consts/mod.rs @@ -145,3 +145,16 @@ white-list=false"#; ) } } +pub mod ping_slp { + use crate::config; + + use super::minecraft::{PROTOCOL_VERSION, VERSION}; + ///return the json which will be send as a response of the ping to the CLI. + pub fn JSON_response() -> () { + // For the version like 1.21.1,767. + let version_name = VERSION; + let version_protocol = PROTOCOL_VERSION; + // For the players. + //let player_max = config::Settings::new().max_players(); + } +} diff --git a/src/file_folder_parser/mod.rs b/src/file_folder_parser/mod.rs new file mode 100644 index 0000000..ba1c7a8 --- /dev/null +++ b/src/file_folder_parser/mod.rs @@ -0,0 +1,11 @@ +use std::fs::File; +use std::io::{self, Write}; // Importer std::io pour utiliser io::Result et io::Error + +pub fn create_server_properties(content:&str) -> io::Result<()> { + // create the file + let mut file = File::create("server_test.properties")?; + //write into the file + file.write_all(content.as_bytes())?; // chatgpt says me rust want have bytes for write anything ... + + Ok(()) +} diff --git a/src/fs_manager/mod.rs b/src/fs_manager/mod.rs index 52ea16d..bd775df 100644 --- a/src/fs_manager/mod.rs +++ b/src/fs_manager/mod.rs @@ -68,62 +68,6 @@ fn check_eula() -> io::Result { Ok(false) } -pub fn clean_file() -> () { - match fs::remove_file(consts::filepaths::EULA) { - Ok(_) => info!("File delete."), - Err(e) => info!("Error when delete file: {}", e), - } - match fs::remove_file(consts::filepaths::PROPERTIES) { - Ok(_) => info!("File delete."), - Err(e) => info!("Error when delete file: {}", e), - } - match fs::remove_file(consts::filepaths::BANNED_IP) { - Ok(_) => info!("File delete."), - Err(e) => info!("Error when delete file: {}", e), - } - match fs::remove_file(consts::filepaths::BANNED_PLAYERS) { - Ok(_) => info!("File delete."), - Err(e) => info!("Error when delete file: {}", e), - } - match fs::remove_file(consts::filepaths::OPERATORS) { - Ok(_) => info!("File delete."), - Err(e) => info!("Error when delete file: {}", e), - } - match fs::remove_file(consts::filepaths::SESSION) { - Ok(_) => info!("File delete."), - Err(e) => info!("Error when delete file: {}", e), - } - match fs::remove_file(consts::filepaths::USERCACHE) { - Ok(_) => info!("File delete."), - Err(e) => info!("Error when delete file: {}", e), - } - match fs::remove_file(consts::filepaths::WHITELIST) { - Ok(_) => info!("File delete."), - Err(e) => info!("Error when delete file: {}", e), - } - //clean folder: - match fs::remove_dir(consts::folderpath::LOGS) { - Ok(_) => info!("File delete."), - Err(e) => info!("Error when delete file: {}", e), - } - match fs::remove_dir(consts::folderpath::NETHER) { - Ok(_) => info!("File delete."), - Err(e) => info!("Error when delete file: {}", e), - } - match fs::remove_dir(consts::folderpath::OVERWORLD) { - Ok(_) => info!("File delete."), - Err(e) => info!("Error when delete file: {}", e), - } - match fs::remove_dir(consts::folderpath::THE_END) { - Ok(_) => info!("File delete."), - Err(e) => info!("Error when delete file: {}", e), - } - match fs::remove_dir(consts::folderpath::WORLDS_DIRECTORY) { - Ok(_) => info!("File delete."), - Err(e) => info!("Error when delete file: {}", e), - } -} - pub fn create_other_files() { match utils::create_file_nn(Path::new(consts::filepaths::BANNED_IP)) { Ok(_) => info!("Created file {}", consts::filepaths::BANNED_IP), @@ -260,3 +204,70 @@ pub fn write_ops_json( file.write_all(serde_json::to_string_pretty(&json_data)?.as_bytes()); Ok(()) } + +/// Removes all files related to the server, excluding the server. +/// +/// I am not sure if this is a good idea, because it takes some time to maintain and is not very +/// useful. +pub fn clean_files() -> Result<(), std::io::Error> { + // Define a helper function to handle file removals + fn remove_file(file_path: &str) -> Result<(), std::io::Error> { + match fs::remove_file(file_path) { + Ok(_) => { + info!("File deleted: {}", file_path); + Ok(()) + } + Err(e) => { + info!("Error when deleting file {}: {}", file_path, e); + Err(e) + } + } + } + + // Define a helper function to handle directory removals + fn remove_dir(dir_path: &str) -> Result<(), std::io::Error> { + match fs::remove_dir(dir_path) { + Ok(_) => { + info!("Directory deleted: {}", dir_path); + Ok(()) + } + Err(e) => { + info!("Error when deleting directory {}: {}", dir_path, e); + Err(e) + } + } + } + + // List all files to be deleted + let files = [ + consts::filepaths::EULA, + consts::filepaths::PROPERTIES, + consts::filepaths::BANNED_IP, + consts::filepaths::BANNED_PLAYERS, + consts::filepaths::OPERATORS, + consts::filepaths::SESSION, + consts::filepaths::USERCACHE, + consts::filepaths::WHITELIST, + ]; + + // Delete files using the `remove_file` helper function + for file in &files { + remove_file(file)?; + } + + // List all directories to be deleted + let directories = [ + consts::folderpath::LOGS, + consts::folderpath::NETHER, + consts::folderpath::OVERWORLD, + consts::folderpath::THE_END, + consts::folderpath::WORLDS_DIRECTORY, + ]; + + // Delete directories using the `remove_dir` helper function + for dir in &directories { + remove_dir(dir)?; + } + + gracefully_exit(0); +} diff --git a/src/main.rs b/src/main.rs index 405f81c..2e07de6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,39 +1,25 @@ //! The servers's entrypoint file. +mod args; mod commands; mod config; mod consts; +mod file_folder_parser; mod fs_manager; mod logging; mod net; mod packet; -mod player; + mod slp; +use log::{error, info, warn}; +mod player; mod time; -use std::env::{self}; use config::Gamemode; use consts::messages; -use fs_manager::clean_file; -use log::{error, info, warn}; #[tokio::main] async fn main() { - let arguments: Vec = env::args().collect(); - - if arguments.len() > 1 { - match arguments[1].as_str() { - "-remove_files" | "--remove" => { - clean_file(); - info!("All files have been removed."); - gracefully_exit(-1); - } - _ => { - warn!("Failed to read the arguments..."); - } - } - } - if let Err(e) = early_init().await { error!("Failed to start the server, error in early initialization: {e}. \nExiting..."); gracefully_exit(-1); @@ -68,7 +54,6 @@ async fn early_init() -> Result<(), Box> { // Listens for cli input commands commands::listen_console_commands().await; - Ok(()) } diff --git a/src/player/mod.rs b/src/player/mod.rs new file mode 100644 index 0000000..54edb70 --- /dev/null +++ b/src/player/mod.rs @@ -0,0 +1,24 @@ +use reqwest::Client; +use serde_json::Value; +use std::error::Error; + +pub async fn get_uuid(username: &str) -> Result> { + let url = format!( + "https://api.mojang.com/users/profiles/minecraft/{}", + username + ); + let client = Client::new(); + let response = client.get(&url).send().await?; + let body = response.text().await?; + get_id(&body) +} + +fn get_id(all: &str) -> Result> { + let v: Value = serde_json::from_str(all)?; + if let Some(id) = v.get("id") { + if let Some(id_str) = id.as_str() { + return Ok(id_str.to_string()); + } + } + Err("Champ 'id' introuvable ou incorrectement formaté".into()) +}