and some compilation changes,
fix https://github.com/Pumpkin-MC/Pumpkin/issues/1010
This commit is contained in:
Alexander Medvedev
2025-12-01 11:23:57 +01:00
parent 6f7006fcb9
commit 74c66e25e8
27 changed files with 301 additions and 269 deletions

150
Cargo.lock generated
View File

@@ -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",

View File

@@ -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"

View File

@@ -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

View File

@@ -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]

View File

@@ -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!(

View File

@@ -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

View File

@@ -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::<Vec<_>>();
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)*
}
}
}

View File

@@ -10,22 +10,24 @@ pub(crate) fn build() -> TokenStream {
let chunk_status: Vec<String> =
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<TokenStream> = 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)*
}
}
}

View File

@@ -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<TokenStream> = 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<f32> {
match item_id {
#variants
#(#match_arms)*
_ => None,
}
}

View File

@@ -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<String, u8> =
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<TokenStream> = 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),*
}
}
}

View File

@@ -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<TokenStream> = 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,
}
}

View File

@@ -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<TokenStream> = 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<TokenStream> = 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)*];
}
}

View File

@@ -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<u16, u16> =
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<TokenStream> = 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<u16> {
match item_id {
#variants
#(#match_arms)*
_ => None,
}
}

View File

@@ -10,18 +10,21 @@ pub(crate) fn build() -> TokenStream {
let events: BTreeMap<String, u16> =
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<TokenStream> = 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)*
}
}
}

View File

@@ -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

View File

@@ -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)?;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -354,7 +354,7 @@ impl<S: SingleChunkDataSerializer> AnvilChunkFile<S> {
}
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<S: SingleChunkDataSerializer> AnvilChunkFile<S> {
// 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<S: SingleChunkDataSerializer> ChunkSerializer for AnvilChunkFile<S> {
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,

View File

@@ -179,7 +179,7 @@ impl<S: SingleChunkDataSerializer> ChunkSerializer for LinearFile<S> {
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<S: SingleChunkDataSerializer> ChunkSerializer for LinearFile<S> {
// 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(())
}

View File

@@ -83,7 +83,7 @@ impl<S: ChunkSerializer<WriteBackend = PathBuf>> ChunkSerializerLazyLoader<S> {
}
async fn read_from_disk(&self) -> Result<S, ChunkReadingError> {
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<S: ChunkSerializer<WriteBackend = PathBuf>> ChunkSerializerLazyLoader<S> {
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());
}
}
}

View File

@@ -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 {

View File

@@ -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

View File

@@ -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

View File

@@ -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,

View File

@@ -562,52 +562,17 @@ impl World {
pub async fn tick(self: &Arc<Self>, 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<Self>) {
let tick_data = self.level.get_tick_data().await;
for scheduled_tick in tick_data.block_ticks {