diff --git a/Cargo.lock b/Cargo.lock index ff0a3cf88..d354cf574 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -37,6 +37,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "alloca" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7d05ea6aea7e9e64d25b9156ba2fee3fdd659e34e41063cd2fc7cd020d7f4" +dependencies = [ + "cc", +] + [[package]] name = "allocator-api2" version = "0.2.21" @@ -297,9 +306,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.46" +version = "1.2.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97463e1064cb1b1c1384ad0a0b9c8abd0988e2a91f52606c80ef14aadb63e36" +checksum = "c481bdbf0ed3b892f6f806287d72acd515b352a4ec27a208489b8c1bc839633a" dependencies = [ "find-msvc-tools", "shlex", @@ -531,9 +540,9 @@ dependencies = [ [[package]] name = "crc" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" +checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d" dependencies = [ "crc-catalog", ] @@ -567,10 +576,11 @@ dependencies = [ [[package]] name = "criterion" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1c047a62b0cc3e145fa84415a3191f628e980b194c2755aa12300a4e6cbd928" +checksum = "a0dfe5e9e71bdcf4e4954f7d14da74d1cdb92a3a07686452d1509652684b1aab" dependencies = [ + "alloca", "anes", "cast", "ciborium", @@ -579,6 +589,7 @@ dependencies = [ "itertools 0.13.0", "num-traits", "oorandom", + "page_size", "regex", "serde", "serde_json", @@ -589,9 +600,9 @@ dependencies = [ [[package]] name = "criterion-plot" -version = "0.6.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b1bcc0dc7dfae599d84ad0b1a55f80cde8af3725da8313b528da95ef783e338" +checksum = "5de36c2bee19fba779808f92bf5d9b0fa5a40095c277aba10c458a12b35d21d6" dependencies = [ "cast", "itertools 0.13.0", @@ -799,17 +810,6 @@ dependencies = [ "powerfmt", ] -[[package]] -name = "derive-getters" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74ef43543e701c01ad77d3a5922755c6a1d71b22d942cb8042be4994b380caff" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "derive_more" version = "2.0.1" @@ -1277,12 +1277,11 @@ dependencies = [ [[package]] name = "http" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" dependencies = [ "bytes", - "fnv", "itoa", ] @@ -1497,9 +1496,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.12.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" +checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" dependencies = [ "equivalent", "hashbrown 0.16.1", @@ -1572,9 +1571,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.82" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" +checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" dependencies = [ "once_cell", "wasm-bindgen", @@ -1856,6 +1855,16 @@ dependencies = [ "sha2 0.10.9", ] +[[package]] +name = "page_size" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "parking_lot" version = "0.12.5" @@ -1905,9 +1914,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.8.3" +version = "2.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989e7521a040efde50c3ab6bbadafbe15ab6dc042686926be59ac35d74607df4" +checksum = "cbcfd20a6d4eeba40179f05735784ad32bdaef05ce8e8af05f180d45bb3e7e22" dependencies = [ "memchr", "ucd-trie", @@ -1915,9 +1924,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.8.3" +version = "2.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "187da9a3030dbafabbbfb20cb323b976dc7b7ce91fcd84f2f74d6e31d378e2de" +checksum = "51f72981ade67b1ca6adc26ec221be9f463f2b5839c7508998daa17c23d94d7f" dependencies = [ "pest", "pest_generator", @@ -1925,9 +1934,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.8.3" +version = "2.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b401d98f5757ebe97a26085998d6c0eecec4995cad6ab7fc30ffdf4b052843" +checksum = "dee9efd8cdb50d719a80088b76f81aec7c41ed6d522ee750178f83883d271625" dependencies = [ "pest", "pest_meta", @@ -1938,9 +1947,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.8.3" +version = "2.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72f27a2cfee9f9039c4d86faa5af122a0ac3851441a34865b8a043b46be0065a" +checksum = "bf1d70880e76bdc13ba52eafa6239ce793d85c8e43896507e43dd8984ff05b82" dependencies = [ "pest", "sha2 0.10.9", @@ -2123,9 +2132,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d" +checksum = "101fec8d036f8d9d4a1e8ebf90d566d1d798f3b1aa379d2576a54a0d9acea5bd" dependencies = [ "bytes", "prost-derive", @@ -2133,9 +2142,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425" +checksum = "d2d93e596a829ebe00afa41c3a056e6308d6b8a4c7d869edf184e2c91b1ba564" dependencies = [ "anyhow", "itertools 0.14.0", @@ -2146,9 +2155,9 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9b4db3d6da204ed77bb26ba83b6122a73aeb2e87e25fbf7ad2e84c4ccbf8f72" +checksum = "f5d7b7346e150de32340ae3390b8b3ffa37ad93ec31fb5dad86afe817619e4e7" dependencies = [ "prost", ] @@ -2344,7 +2353,6 @@ dependencies = [ "crossbeam", "crossfire", "dashmap", - "derive-getters", "enum_dispatch", "env_logger", "flate2", @@ -2577,9 +2585,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94182ad936a0c91c324cd46c6511b9510ed16af436d7b5bab34beab0afd55f7a" +checksum = "708c0f9d5f54ba0272468c1d306a52c495b31fa155e91bc25371e6df7996908c" dependencies = [ "zeroize", ] @@ -2804,9 +2812,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.6" +version = "1.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" +checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad" dependencies = [ "libc", ] @@ -2944,9 +2952,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.110" +version = "2.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" dependencies = [ "proc-macro2", "quote", @@ -3266,9 +3274,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647" dependencies = [ "pin-project-lite", "tracing-attributes", @@ -3277,9 +3285,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", @@ -3288,9 +3296,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.34" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c" dependencies = [ "once_cell", "valuable", @@ -3298,9 +3306,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.20" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" dependencies = [ "matchers", "once_cell", @@ -3391,9 +3399,9 @@ dependencies = [ [[package]] name = "ureq-proto" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b4531c118335662134346048ddb0e54cc86bd7e81866757873055f0e38f5d2" +checksum = "d81f9efa9df032be5934a46a068815a10a042b494b6a58cb0a1a97bb5467ed6f" dependencies = [ "base64 0.22.1", "http", @@ -3492,9 +3500,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.105" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" +checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" dependencies = [ "cfg-if", "once_cell", @@ -3505,9 +3513,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.105" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" +checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3515,9 +3523,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.105" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" +checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" dependencies = [ "bumpalo", "proc-macro2", @@ -3528,9 +3536,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.105" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" +checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" dependencies = [ "unicode-ident", ] @@ -3748,9 +3756,9 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" -version = "0.7.13" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" [[package]] name = "wit-bindgen" @@ -3789,18 +3797,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.28" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43fa6694ed34d6e57407afbccdeecfa268c470a7d2a5b0cf49ce9fcc345afb90" +checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.28" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c640b22cd9817fae95be82f0d2f90b11f7605f6c319d16705c459b27ac2cbc26" +checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 6e04cbae6..4f84896b4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,17 +30,9 @@ debug = true [workspace.dependencies] log = "0.4" -tokio = { version = "1.48", features = [ - "macros", - "net", - "rt-multi-thread", - "sync", - "io-std", - "signal", - "fs", - "io-util", - "time", -] } +tokio = { version = "1.48", default-features = false } +syn = { version = "2.0", default-features = false, features=["printing"] } + thiserror = "2.0" diff --git a/pumpkin-api-macros/Cargo.toml b/pumpkin-api-macros/Cargo.toml index 44db176e8..020f0f824 100644 --- a/pumpkin-api-macros/Cargo.toml +++ b/pumpkin-api-macros/Cargo.toml @@ -7,7 +7,7 @@ edition.workspace = true proc-macro = true [dependencies] -syn = "2.0" +syn .workspace = true quote = "1.0" proc-macro2 = "1.0" proc-macro-error2.workspace = true diff --git a/pumpkin-config/Cargo.toml b/pumpkin-config/Cargo.toml index 5c3b90383..a031537c5 100644 --- a/pumpkin-config/Cargo.toml +++ b/pumpkin-config/Cargo.toml @@ -9,8 +9,6 @@ serde.workspace = true log.workspace = true uuid.workspace = true -#TODO Toml format is simple: make our own parser! -#This crate has 19 dependencies toml = "0.9" [features] diff --git a/pumpkin-config/src/lib.rs b/pumpkin-config/src/lib.rs index 0d7670ff8..e35cb0a61 100644 --- a/pumpkin-config/src/lib.rs +++ b/pumpkin-config/src/lib.rs @@ -189,7 +189,7 @@ impl Default for BasicConfiguration { impl BasicConfiguration { pub fn get_world_path(&self) -> PathBuf { - format!("./{}", self.default_level_name).parse().unwrap() + PathBuf::from(&self.default_level_name) } } @@ -222,7 +222,7 @@ trait LoadConfiguration { if changed { println!( "{} changed because values were missing. The missing values were filled with default values.", - path.file_name().unwrap().to_str().unwrap() + path.file_name().unwrap().display() ); if let Err(err) = fs::write(&path, toml::to_string(&merged_config).unwrap()) { warn!( diff --git a/pumpkin-data/Cargo.toml b/pumpkin-data/Cargo.toml index 862df5758..256edba44 100644 --- a/pumpkin-data/Cargo.toml +++ b/pumpkin-data/Cargo.toml @@ -23,6 +23,6 @@ serde_json5 = "0.2.1" heck = "0.5" proc-macro2 = "1.0" quote = "1.0" -syn = "2.0" +syn.workspace = true rayon.workspace = true diff --git a/pumpkin-data/build/attributes.rs b/pumpkin-data/build/attributes.rs index 4a23cb1cc..9604c390c 100644 --- a/pumpkin-data/build/attributes.rs +++ b/pumpkin-data/build/attributes.rs @@ -1,8 +1,10 @@ -use proc_macro2::TokenStream; +use heck::ToShoutySnakeCase; +use proc_macro2::{Span, TokenStream}; use quote::{format_ident, quote}; use serde::Deserialize; use std::collections::BTreeMap; use std::fs; +use syn::LitInt; #[derive(Deserialize)] struct Attributes { @@ -17,26 +19,28 @@ pub(crate) fn build() -> TokenStream { serde_json::from_str(&fs::read_to_string("../assets/attributes.json").unwrap()) .expect("Failed to parse attributes.json"); - let mut consts = TokenStream::new(); + let mut sorted_attributes: Vec<(String, Attributes)> = attributes.into_iter().collect(); + sorted_attributes.sort_by_key(|(_, raw)| raw.id); - let mut data_component_vec = attributes.iter().collect::>(); - data_component_vec.sort_by_key(|(_, i)| i.id); + let mut constant_defs = Vec::new(); - for (raw_name, raw_value) in &data_component_vec { - let pascal_case = format_ident!("{}", raw_name.to_uppercase()); + for (raw_name, raw_value) in sorted_attributes { + let constant_ident = format_ident!("{}", raw_name.to_shouty_snake_case()); - let id = raw_value.id; - let default_value = raw_value.default_value; - consts.extend(quote! { - pub const #pascal_case: Self = Self { - id: #id, - default_value: #default_value, + let id_lit = LitInt::new(&raw_value.id.to_string(), Span::call_site()); + let default_value_lit = raw_value.default_value; + + constant_defs.push(quote! { + pub const #constant_ident: Self = Self { + id: #id_lit, + default_value: #default_value_lit, }; }); } quote! { use std::hash::Hash; + #[derive(Clone, Debug)] pub struct Attributes { pub id: u8, @@ -54,7 +58,7 @@ pub(crate) fn build() -> TokenStream { } } impl Attributes { - #consts + #(#constant_defs)* } } } diff --git a/pumpkin-data/build/chunk_status.rs b/pumpkin-data/build/chunk_status.rs index ef0c31b11..106d3fe0f 100644 --- a/pumpkin-data/build/chunk_status.rs +++ b/pumpkin-data/build/chunk_status.rs @@ -10,22 +10,24 @@ pub(crate) fn build() -> TokenStream { let chunk_status: Vec = serde_json::from_str(&fs::read_to_string("../assets/chunk_status.json").unwrap()) .expect("Failed to parse chunk_status.json"); - let mut variants = TokenStream::new(); + let variants: Vec = chunk_status + .into_iter() + .map(|status| { + let full_name = format!("minecraft:{}", status); + let name = format_ident!("{}", status.to_pascal_case()); - for status in chunk_status.iter() { - let full_name = format!("minecraft:{status}"); - let name = format_ident!("{}", status.to_pascal_case()); - variants.extend([quote! { - #[serde(rename = #full_name)] - #name, - }]); - } + quote! { + #[serde(rename = #full_name)] + #name, + } + }) + .collect(); quote! { use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy)] pub enum ChunkStatus { - #variants + #(#variants)* } } } diff --git a/pumpkin-data/build/composter_increase_chance.rs b/pumpkin-data/build/composter_increase_chance.rs index 96806704f..401e7bf09 100644 --- a/pumpkin-data/build/composter_increase_chance.rs +++ b/pumpkin-data/build/composter_increase_chance.rs @@ -1,7 +1,8 @@ use std::{collections::BTreeMap, fs}; -use proc_macro2::TokenStream; +use proc_macro2::{Span, TokenStream}; use quote::quote; +use syn::LitInt; pub(crate) fn build() -> TokenStream { println!("cargo:rerun-if-changed=../assets/composter_increase_chance.json"); @@ -10,18 +11,22 @@ pub(crate) fn build() -> TokenStream { &fs::read_to_string("../assets/composter_increase_chance.json").unwrap(), ) .expect("Failed to parse composter_increase_chance.json"); - let mut variants = TokenStream::new(); + let match_arms: Vec = composter_increase_chance + .into_iter() // Consume the map for efficiency + .map(|(item_id, chance)| { + let item_id_lit = LitInt::new(&item_id.to_string(), Span::call_site()); + let chance_lit = chance; - for (item_id, chance) in composter_increase_chance { - variants.extend(quote! { - #item_id => Some(#chance), - }); - } + quote! { + #item_id_lit => Some(#chance_lit), + } + }) + .collect(); quote! { #[must_use] pub const fn get_composter_increase_chance_from_item_id(item_id: u16) -> Option { match item_id { - #variants + #(#match_arms)* _ => None, } } diff --git a/pumpkin-data/build/entity_status.rs b/pumpkin-data/build/entity_status.rs index 81f6f1fd9..cd1e7ef50 100644 --- a/pumpkin-data/build/entity_status.rs +++ b/pumpkin-data/build/entity_status.rs @@ -1,8 +1,9 @@ use std::{collections::BTreeMap, fs}; use heck::ToPascalCase; -use proc_macro2::TokenStream; +use proc_macro2::{Span, TokenStream}; use quote::{format_ident, quote}; +use syn::LitInt; pub(crate) fn build() -> TokenStream { println!("cargo:rerun-if-changed=../assets/entity_statuses.json"); @@ -10,18 +11,21 @@ pub(crate) fn build() -> TokenStream { let events: BTreeMap = serde_json::from_str(&fs::read_to_string("../assets/entity_statuses.json").unwrap()) .expect("Failed to parse entity_statuses.json"); - let mut variants = TokenStream::new(); + let variants: Vec = events + .into_iter() + .map(|(event_name, id)| { + let name = format_ident!("{}", event_name.to_pascal_case()); + let id_lit = LitInt::new(&id.to_string(), Span::call_site()); - for (event, id) in events.iter() { - let name = format_ident!("{}", event.to_pascal_case()); - variants.extend([quote! { - #name = #id, - }]); - } + quote! { + #name = #id_lit + } + }) + .collect(); quote! { #[repr(u8)] pub enum EntityStatus { - #variants + #(#variants),* } } } diff --git a/pumpkin-data/build/flower_pot_transformations.rs b/pumpkin-data/build/flower_pot_transformations.rs index 868b53bed..7fb9f7b13 100644 --- a/pumpkin-data/build/flower_pot_transformations.rs +++ b/pumpkin-data/build/flower_pot_transformations.rs @@ -1,6 +1,7 @@ -use proc_macro2::TokenStream; +use proc_macro2::{Span, TokenStream}; use quote::quote; use std::{collections::BTreeMap, fs}; +use syn::LitInt; pub(crate) fn build() -> TokenStream { println!("cargo:rerun-if-changed=../assets/flower_pot_transformations.json"); @@ -8,18 +9,21 @@ pub(crate) fn build() -> TokenStream { &fs::read_to_string("../assets/flower_pot_transformations.json").unwrap(), ) .expect("Failed to parse flower_pot_transformations.json"); - let mut variants = TokenStream::new(); - - for (item_id, potted_block_id) in flower_pot_transformation { - variants.extend(quote! { - #item_id => #potted_block_id, - }); - } + let match_arms: Vec = flower_pot_transformation + .into_iter() + .map(|(item_id, potted_block_id)| { + let item_id_lit = LitInt::new(&item_id.to_string(), Span::call_site()); + let potted_id_lit = LitInt::new(&potted_block_id.to_string(), Span::call_site()); + quote! { + #item_id_lit => #potted_id_lit, + } + }) + .collect(); quote! { #[must_use] pub const fn get_potted_item(item_id: u16) -> u16 { match item_id { - #variants + #(#match_arms)* _ => 0, } } diff --git a/pumpkin-data/build/potion_brewing.rs b/pumpkin-data/build/potion_brewing.rs index 58095c345..57f4c3704 100644 --- a/pumpkin-data/build/potion_brewing.rs +++ b/pumpkin-data/build/potion_brewing.rs @@ -78,18 +78,20 @@ pub(crate) fn build() -> TokenStream { serde_json::from_str(&fs::read_to_string("../assets/potion_brewing.json").unwrap()) .expect("Failed to parse potion_brewing.json"); - let mut item = TokenStream::new(); - let mut potion = TokenStream::new(); + let item_recipes_tokens: Vec = json + .item_recipes + .into_iter() + .map(|recipe| recipe.get_tokens_item()) + .collect(); + let item_len = item_recipes_tokens.len(); - let item_len = json.item_recipes.len(); - let potion_len = json.potion_recipes.len(); - - for j in json.item_recipes { - item.extend(j.get_tokens_item()); - } - for j in json.potion_recipes { - potion.extend(j.get_tokens_potion()); - } + // 3. Generate Potion Recipes + let potion_recipes_tokens: Vec = json + .potion_recipes + .into_iter() + .map(|recipe| recipe.get_tokens_potion()) + .collect(); + let potion_len = potion_recipes_tokens.len(); quote! { #![allow(dead_code)] @@ -108,7 +110,7 @@ pub(crate) fn build() -> TokenStream { to: &'static Item, } - pub const ITEM_RECIPES: [ItemRecipe; #item_len] = [#item]; - pub const POTION_RECIPES: [PotionRecipe; #potion_len] = [#potion]; + pub const ITEM_RECIPES: [ItemRecipe; #item_len] = [#(#item_recipes_tokens)*]; + pub const POTION_RECIPES: [PotionRecipe; #potion_len] = [#(#potion_recipes_tokens)*]; } } diff --git a/pumpkin-data/build/recipe_remainder.rs b/pumpkin-data/build/recipe_remainder.rs index 016a74613..8b167ecda 100644 --- a/pumpkin-data/build/recipe_remainder.rs +++ b/pumpkin-data/build/recipe_remainder.rs @@ -1,24 +1,29 @@ -use proc_macro2::TokenStream; +use proc_macro2::{Span, TokenStream}; use quote::quote; use std::{collections::BTreeMap, fs}; +use syn::LitInt; pub(crate) fn build() -> TokenStream { println!("cargo:rerun-if-changed=../assets/recipe_remainder.json"); let remainder: BTreeMap = serde_json::from_str(&fs::read_to_string("../assets/recipe_remainder.json").unwrap()) .expect("Failed to parse recipe_remainder.json"); - let mut variants = TokenStream::new(); + let match_arms: Vec = remainder + .into_iter() + .map(|(item_id, remainder_id)| { + let item_id_lit = LitInt::new(&item_id.to_string(), Span::call_site()); + let remainder_id_lit = LitInt::new(&remainder_id.to_string(), Span::call_site()); - for (item_id, remainder_id) in remainder { - variants.extend(quote! { - #item_id => Some(#remainder_id), - }); - } + quote! { + #item_id_lit => Some(#remainder_id_lit), + } + }) + .collect(); quote! { #[must_use] pub const fn get_recipe_remainder_id(item_id: u16) -> Option { match item_id { - #variants + #(#match_arms)* _ => None, } } diff --git a/pumpkin-data/build/world_event.rs b/pumpkin-data/build/world_event.rs index 8689b78de..44de81349 100644 --- a/pumpkin-data/build/world_event.rs +++ b/pumpkin-data/build/world_event.rs @@ -10,18 +10,21 @@ pub(crate) fn build() -> TokenStream { let events: BTreeMap = serde_json::from_str(&fs::read_to_string("../assets/world_event.json").unwrap()) .expect("Failed to parse world_event.json"); - let mut variants = TokenStream::new(); + let variants: Vec = events + .into_iter() + .map(|(event_name, id)| { + let name = format_ident!("{}", event_name.to_pascal_case()); + + quote! { + #name = #id, + } + }) + .collect(); - for (event, id) in events.iter() { - let name = format_ident!("{}", event.to_pascal_case()); - variants.extend([quote! { - #name = #id, - }]); - } quote! { #[repr(u16)] pub enum WorldEvent { - #variants + #(#variants)* } } } diff --git a/pumpkin-macros/Cargo.toml b/pumpkin-macros/Cargo.toml index 4e01829a5..1ab6388af 100644 --- a/pumpkin-macros/Cargo.toml +++ b/pumpkin-macros/Cargo.toml @@ -12,4 +12,4 @@ proc-macro-error2.workspace = true heck = "0.5" proc-macro2 = "1.0" quote = "1.0" -syn = "2.0" +syn.workspace = true diff --git a/pumpkin-protocol/src/java/client/play/chunk_data.rs b/pumpkin-protocol/src/java/client/play/chunk_data.rs index d25200b9f..27880370c 100644 --- a/pumpkin-protocol/src/java/client/play/chunk_data.rs +++ b/pumpkin-protocol/src/java/client/play/chunk_data.rs @@ -22,30 +22,20 @@ impl ClientPacket for CChunkData<'_> { write.write_i32_be(self.0.position.y)?; let heightmaps = &self.0.heightmap; - // the heighmap is a map, we put 3 values in so the size is 3 - write.write_var_int(&VarInt(3))?; + write.write_var_int(&VarInt(3))?; // Map size - // heighmap index - write.write_var_int(&VarInt(1))?; - // write long array - write.write_var_int(&VarInt(heightmaps.world_surface.len() as i32))?; - for mb in &heightmaps.world_surface { - write.write_i64_be(*mb)?; - } - // heighmap index - write.write_var_int(&VarInt(4))?; - // write long array - write.write_var_int(&VarInt(heightmaps.motion_blocking.len() as i32))?; - for mb in &heightmaps.motion_blocking { - write.write_i64_be(*mb)?; - } - // heighmap index - write.write_var_int(&VarInt(5))?; - // write long array - write.write_var_int(&VarInt(heightmaps.motion_blocking_no_leaves.len() as i32))?; - for mb in &heightmaps.motion_blocking { - write.write_i64_be(*mb)?; - } + let mut write_heightmap = |index: i32, data: &[i64]| -> Result<(), WritingError> { + write.write_var_int(&VarInt(index))?; + write.write_var_int(&VarInt(data.len() as i32))?; + for val in data { + write.write_i64_be(*val)?; + } + Ok(()) + }; + + write_heightmap(1, &heightmaps.world_surface)?; + write_heightmap(4, &heightmaps.motion_blocking)?; + write_heightmap(5, &heightmaps.motion_blocking_no_leaves)?; { let mut blocks_and_biomes_buf = Vec::new(); @@ -120,16 +110,15 @@ impl ClientPacket for CChunkData<'_> { write.write_var_int(&VarInt(self.0.block_entities.len() as i32))?; for block_entity in self.0.block_entities.values() { - let block_entity = &block_entity; - let chunk_data_nbt = block_entity.chunk_data_nbt(); let pos = block_entity.get_position(); - let block_entity_id = block_entity.get_id(); - let local_xz = (get_local_cord(pos.0.x) << 4) | get_local_cord(pos.0.z); + let local_xz = ((get_local_cord(pos.0.x) & 0xF) << 4) | (get_local_cord(pos.0.z) & 0xF); + write.write_u8(local_xz as u8)?; write.write_i16_be(pos.0.y as i16)?; - write.write_var_int(&VarInt(block_entity_id as i32))?; - if let Some(chunk_data_nbt) = chunk_data_nbt { - write.write_nbt(&chunk_data_nbt.into())?; + write.write_var_int(&VarInt(block_entity.get_id() as i32))?; + + if let Some(nbt) = block_entity.chunk_data_nbt() { + write.write_nbt(&nbt.into())?; } else { write.write_u8(END_ID)?; } diff --git a/pumpkin-protocol/src/java/packet_encoder.rs b/pumpkin-protocol/src/java/packet_encoder.rs index 3044bed35..b5437f324 100644 --- a/pumpkin-protocol/src/java/packet_encoder.rs +++ b/pumpkin-protocol/src/java/packet_encoder.rs @@ -383,8 +383,7 @@ mod tests { #[tokio::test] async fn test_encode_with_compression() { // Create a CStatusResponse packet - let packet = - CStatusResponse::new("{\"description\": \"A Minecraft Server\"}".parse().unwrap()); + let packet = CStatusResponse::new("{\"description\": \"A Minecraft Server\"}".to_string()); // Build the packet with compression enabled let packet_bytes = build_packet_with_encoder(&packet, Some((0, 6)), None).await; @@ -431,8 +430,7 @@ mod tests { #[tokio::test] async fn test_encode_with_encryption() { // Create a CStatusResponse packet - let packet = - CStatusResponse::new("{\"description\": \"A Minecraft Server\"}".parse().unwrap()); + let packet = CStatusResponse::new("{\"description\": \"A Minecraft Server\"}".to_string()); // Encryption key and IV (IV is the same as key in this case) let key = [0x00u8; 16]; // Example key @@ -468,8 +466,7 @@ mod tests { #[tokio::test] async fn test_encode_with_compression_and_encryption() { // Create a CStatusResponse packet - let packet = - CStatusResponse::new("{\"description\": \"A Minecraft Server\"}".parse().unwrap()); + let packet = CStatusResponse::new("{\"description\": \"A Minecraft Server\"}".to_string()); // Encryption key and IV (IV is the same as key in this case) let key = [0x01u8; 16]; // Example key diff --git a/pumpkin-util/Cargo.toml b/pumpkin-util/Cargo.toml index 91ba6d9cc..c1e88b5cd 100644 --- a/pumpkin-util/Cargo.toml +++ b/pumpkin-util/Cargo.toml @@ -15,12 +15,14 @@ num-traits = "0.2" colored = "3.0" md5 = "0.8" quote = "1.0" -syn = "2.0" +syn.workspace = true proc-macro2 = "1.0" enum_dispatch = "0.3.13" uuid.workspace = true -tokio.workspace = true +tokio = { workspace = true, features = [ + "sync", +] } base64 = "0.22.1" p384 = { version = "0.13.1", features = ["ecdsa"] } thiserror.workspace = true diff --git a/pumpkin-world/Cargo.toml b/pumpkin-world/Cargo.toml index 017416d5a..8922098d0 100644 --- a/pumpkin-world/Cargo.toml +++ b/pumpkin-world/Cargo.toml @@ -39,7 +39,6 @@ ruzstd = "0.8.2" itertools = "0.14.0" enum_dispatch = "0.3" -derive-getters = "0.5.0" thread_local = "1.1.9" lru = "0.16.2" @@ -52,7 +51,7 @@ slotmap = "1.0" crossfire = "2.1.7" [dev-dependencies] -criterion = { version = "0.7", default-features = false, features = ["html_reports", "async_tokio"] } +criterion = { version = "0.8", default-features = false, features = ["html_reports", "async_tokio"] } temp-dir = "0.1.16" # Print log info inside tests when needed env_logger = "0.11.8" diff --git a/pumpkin-world/src/chunk/format/anvil.rs b/pumpkin-world/src/chunk/format/anvil.rs index cbe04531a..798853b67 100644 --- a/pumpkin-world/src/chunk/format/anvil.rs +++ b/pumpkin-world/src/chunk/format/anvil.rs @@ -354,7 +354,7 @@ impl AnvilChunkFile { } async fn write_indices(&self, path: &Path, indices: &[usize]) -> Result<(), std::io::Error> { - log::trace!("Writing in place: {path:?}"); + log::trace!("Writing in place: {}", path.display()); let file = tokio::fs::OpenOptions::new() .read(false) @@ -500,7 +500,7 @@ impl AnvilChunkFile { // that the data is not corrupted before the rename is completed tokio::fs::rename(temp_path, path).await?; - log::trace!("Wrote file to Disk: {path:?}"); + log::trace!("Wrote file to Disk: {}", path.display()); Ok(()) } } @@ -542,7 +542,10 @@ impl ChunkSerializer for AnvilChunkFile { let mut write_action = self.write_action.lock().await; match &*write_action { WriteAction::Pass => { - log::debug!("Skipping write for {path:?} as there were no dirty chunks"); + log::debug!( + "Skipping write for {}, as there were no dirty chunks", + path.display() + ); Ok(()) } WriteAction::All => self.write_all(&path).await, diff --git a/pumpkin-world/src/chunk/format/linear.rs b/pumpkin-world/src/chunk/format/linear.rs index eb42e8e06..864f65d25 100644 --- a/pumpkin-world/src/chunk/format/linear.rs +++ b/pumpkin-world/src/chunk/format/linear.rs @@ -179,7 +179,7 @@ impl ChunkSerializer for LinearFile { async fn write(&self, path: PathBuf) -> Result<(), std::io::Error> { let temp_path = path.with_extension("tmp"); - log::trace!("Writing tmp file to disk: {:?}", temp_path); + log::trace!("Writing tmp file to disk: {}", temp_path.display()); let file = tokio::fs::OpenOptions::new() .read(false) @@ -236,7 +236,7 @@ impl ChunkSerializer for LinearFile { // that the data is not corrupted before the rename is completed tokio::fs::rename(temp_path, &path).await?; - log::trace!("Wrote file to Disk: {:?}", path); + log::trace!("Wrote file to Disk: {}", path.display()); Ok(()) } diff --git a/pumpkin-world/src/chunk/io/file_manager.rs b/pumpkin-world/src/chunk/io/file_manager.rs index 07b0cdb04..3324d2e7e 100644 --- a/pumpkin-world/src/chunk/io/file_manager.rs +++ b/pumpkin-world/src/chunk/io/file_manager.rs @@ -83,7 +83,7 @@ impl> ChunkSerializerLazyLoader { } async fn read_from_disk(&self) -> Result { - trace!("Opening file from Disk: {:?}", self.path); + trace!("Opening file from Disk: {}", self.path.display()); let file = tokio::fs::OpenOptions::new() .read(true) .write(false) @@ -114,7 +114,7 @@ impl> ChunkSerializerLazyLoader { Err(err) => return Err(err), }; - trace!("Successfully read file from Disk: {:?}", self.path); + trace!("Successfully read file from Disk: {}", self.path.display()); Ok(value) } } @@ -279,7 +279,7 @@ where .into_iter() .map(async |(file_name, chunk_locks)| { let path = P::file_path(folder, &file_name); - log::trace!("Updating data for file {path:?}"); + log::trace!("Updating data for file {}", path.display()); let chunk_serializer = match self.get_serializer(&path).await { Ok(file) => Ok(file), @@ -317,7 +317,7 @@ where }); // Run all update tasks concurrently and propagate any error futures::future::try_join_all(update_tasks).await?; - log::trace!("Updated data for file {path:?}"); + log::trace!("Updated data for file {}", path.display()); let is_watched = self .watchers @@ -331,7 +331,7 @@ where // to avoid other threads to write/modify the data, but allow other threads to read it let serializer = chunk_serializer.read().await; - log::debug!("Writing file for {path:?}"); + log::debug!("Writing file for {}", path.display()); serializer .write(path.clone()) .await @@ -360,9 +360,9 @@ where if can_remove { locks.remove(&path); - log::trace!("Removed lockfile cache {path:?}"); + log::trace!("Removed lockfile cache {}", path.display()); } else { - log::trace!("Wanted to remove lockfile cache {path:?} but someone still holds a reference to it!"); + log::trace!("Wanted to remove lockfile cache {} but someone still holds a reference to it!", path.display()); } } } diff --git a/pumpkin-world/src/data/player_data.rs b/pumpkin-world/src/data/player_data.rs index e4dc9d9cf..1e9b07b84 100644 --- a/pumpkin-world/src/data/player_data.rs +++ b/pumpkin-world/src/data/player_data.rs @@ -31,7 +31,10 @@ impl PlayerDataStorage { if !path.exists() && let Err(e) = create_dir_all(&path) { - log::error!("Failed to create player data directory at {path:?}: {e}"); + log::error!( + "Failed to create player data directory at {}: {e}", + path.display() + ); } Self { diff --git a/pumpkin-world/src/generation/noise/router/density_function/test.rs b/pumpkin-world/src/generation/noise/router/density_function/test.rs index aba7c072b..dd9c8946e 100644 --- a/pumpkin-world/src/generation/noise/router/density_function/test.rs +++ b/pumpkin-world/src/generation/noise/router/density_function/test.rs @@ -125,7 +125,7 @@ macro_rules! sample_surface_router_function { // TODO: Test all dimensions/noise routers #[test] -// This test verifys that the generated functions after seed initialization but before chunk +// This test verifies that the generated functions after seed initialization but before chunk // initialization matches the respected Java values. // // This is equivalent to a Java `NoiseRouter` after being passed into `NoiseConfig` but before being diff --git a/pumpkin/Cargo.toml b/pumpkin/Cargo.toml index 48116707c..1a27163ba 100644 --- a/pumpkin/Cargo.toml +++ b/pumpkin/Cargo.toml @@ -30,7 +30,17 @@ pumpkin-macros = { path = "../pumpkin-macros" } log.workspace = true crossbeam.workspace = true uuid.workspace = true -tokio.workspace = true +tokio = { workspace = true, features = [ + "macros", + "net", + "rt-multi-thread", + "sync", + "io-std", + "signal", + "fs", + "io-util", + "time", +] } rayon.workspace = true thiserror.workspace = true async-trait.workspace = true diff --git a/pumpkin/src/server/mod.rs b/pumpkin/src/server/mod.rs index fcc12617b..0b3ba57da 100644 --- a/pumpkin/src/server/mod.rs +++ b/pumpkin/src/server/mod.rs @@ -142,7 +142,7 @@ impl Server { // So TODO let locker = AnvilLevelLocker::lock(&world_path).expect("Failed to lock level"); - let world_name = world_path.to_str().unwrap(); + let player_data_path = world_path.join("playerdata"); let level_info = level_info.unwrap_or_else(|err| { log::warn!("Failed to get level_info, using default instead: {err}"); @@ -173,7 +173,7 @@ impl Server { gamemode: BASIC_CONFIG.default_gamemode, }), player_data_storage: ServerPlayerData::new( - format!("{world_name}/playerdata"), + player_data_path, Duration::from_secs(advanced_config().player_data.save_player_cron_interval), ), white_list: AtomicBool::new(BASIC_CONFIG.white_list), @@ -209,7 +209,7 @@ impl Server { ); log::info!("Loading End: {seed}"); let end = World::load( - Dimension::End.into_level(world_path.clone(), block_registry.clone(), seed), + Dimension::End.into_level(world_path, block_registry.clone(), seed), level_info, VanillaDimensionType::TheEnd, block_registry, diff --git a/pumpkin/src/world/mod.rs b/pumpkin/src/world/mod.rs index 258819360..b3cf4a914 100644 --- a/pumpkin/src/world/mod.rs +++ b/pumpkin/src/world/mod.rs @@ -562,52 +562,17 @@ impl World { pub async fn tick(self: &Arc, server: &Server) { let start = tokio::time::Instant::now(); + self.flush_block_updates().await; // tick block entities self.flush_synced_block_events().await; - // world ticks - { - let mut level_time = self.level_time.lock().await; - level_time.tick_time(); - if level_time.world_age % 100 == 0 { - // log::debug!("should unload set true"); - self.level.should_unload.store(true, Relaxed); - if level_time.world_age % 300 != 0 { - self.level.level_channel.notify(); - } - } - if level_time.world_age % 300 == 0 { - // log::debug!("should save set true"); - self.level.should_save.store(true, Relaxed); - self.level.level_channel.notify(); - } - let mut weather = self.weather.lock().await; - weather.tick_weather(self).await; - - if self.should_skip_night().await { - let time = level_time.time_of_day + 24000; - level_time.set_time(time - time % 24000); - level_time.send_time(self).await; - - for player in self.players.read().await.values() { - player.wake_up().await; - } - - if weather.weather_cycle_enabled && (weather.raining || weather.thundering) { - weather.reset_weather_cycle(self).await; - drop(weather); - } - } else if level_time.world_age % 20 == 0 { - level_time.send_time(self).await; - drop(level_time); - } - } + self.tick_environment().await; let chunk_start = tokio::time::Instant::now(); // log::debug!("Ticking chunks"); self.tick_chunks().await; - let elapsed = chunk_start.elapsed(); + let chunk_elapsed = chunk_start.elapsed(); let players_to_tick: Vec<_> = self.players.read().await.values().cloned().collect(); @@ -642,12 +607,13 @@ impl World { self.level.chunk_loading.lock().unwrap().send_change(); - log::debug!( - "Ticking world took {:?}, loaded chunks: {}, chunk tick took {:?}", - start.elapsed(), - self.level.loaded_chunk_count(), - elapsed - ); + if start.elapsed().as_millis() > 50 { + log::warn!( + "Slow Tick: Total {:?} | Chunks {:?}", + start.elapsed(), + chunk_elapsed, + ); + } } pub async fn flush_block_updates(&self) { @@ -680,6 +646,42 @@ impl World { } } + async fn tick_environment(&self) { + let mut level_time = self.level_time.lock().await; + level_time.tick_time(); + + // Auto-save logic + if level_time.world_age % 100 == 0 { + self.level.should_unload.store(true, Relaxed); + if level_time.world_age % 300 != 0 { + self.level.level_channel.notify(); + } + } + if level_time.world_age % 300 == 0 { + self.level.should_save.store(true, Relaxed); + self.level.level_channel.notify(); + } + + let mut weather = self.weather.lock().await; + weather.tick_weather(self).await; + + if self.should_skip_night().await { + let time = level_time.time_of_day + 24000; + level_time.set_time(time - time % 24000); + level_time.send_time(self).await; + + for player in self.players.read().await.values() { + player.wake_up().await; + } + + if weather.weather_cycle_enabled && (weather.raining || weather.thundering) { + weather.reset_weather_cycle(self).await; + } + } else if level_time.world_age % 20 == 0 { + level_time.send_time(self).await; + } + } + pub async fn tick_chunks(self: &Arc) { let tick_data = self.level.get_tick_data().await; for scheduled_tick in tick_data.block_ticks {