From 38298506079678e5279f11ec3d254b181f5ae596 Mon Sep 17 00:00:00 2001 From: Alexander Medvedev Date: Sun, 7 Dec 2025 22:43:26 +0100 Subject: [PATCH] removed some clones fix: https://github.com/Pumpkin-MC/Pumpkin/issues/1226 --- Cargo.lock | 155 +---- pumpkin-data/build/item.rs | 2 +- pumpkin-inventory/src/screen_handler.rs | 4 +- pumpkin-inventory/src/slot.rs | 4 +- pumpkin-macros/Cargo.toml | 1 - pumpkin-macros/src/lib.rs | 550 +++++++++--------- pumpkin-protocol/Cargo.toml | 4 +- pumpkin-util/src/registry.rs | 7 +- pumpkin-world/Cargo.toml | 1 - pumpkin-world/src/block/entities/bed.rs | 2 +- .../src/block/entities/command_block.rs | 2 +- .../src/block/entities/end_portal.rs | 2 +- .../src/block/entities/ender_chest.rs | 2 +- pumpkin-world/src/block/entities/mod.rs | 2 +- pumpkin-world/src/block/entities/sign.rs | 2 +- pumpkin-world/src/chunk/format/anvil.rs | 12 +- pumpkin-world/src/chunk/format/linear.rs | 4 +- pumpkin-world/src/chunk/format/mod.rs | 83 +-- pumpkin-world/src/chunk/io/file_manager.rs | 2 +- pumpkin-world/src/chunk/io/mod.rs | 2 +- .../src/generation/aquifer_sampler.rs | 199 ++++--- .../src/generation/block_state_provider.rs | 14 +- pumpkin-world/src/generation/chunk_noise.rs | 2 +- .../feature/features/spring_feature.rs | 54 +- pumpkin-world/src/generation/proto_chunk.rs | 6 +- pumpkin-world/src/level.rs | 4 +- pumpkin-world/src/tick/scheduler.rs | 4 +- pumpkin-world/src/world_info/anvil.rs | 4 +- pumpkin/Cargo.toml | 16 +- pumpkin/src/block/mod.rs | 20 +- pumpkin/src/command/commands/mod.rs | 15 - pumpkin/src/command/commands/profile.rs | 45 -- pumpkin/src/data/banlist_serializer.rs | 3 +- pumpkin/src/item/mod.rs | 6 +- pumpkin/src/lib.rs | 4 - pumpkin/src/main.rs | 20 +- pumpkin/src/net/mod.rs | 3 +- pumpkin/src/plugin/mod.rs | 8 +- pumpkin/src/server/key_store.rs | 17 +- 39 files changed, 576 insertions(+), 711 deletions(-) delete mode 100644 pumpkin/src/command/commands/profile.rs diff --git a/Cargo.lock b/Cargo.lock index 3f72498d5..837b1f4d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,15 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addr2line" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" -dependencies = [ - "gimli", -] - [[package]] name = "adler2" version = "2.0.1" @@ -134,9 +125,9 @@ checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "async-compression" -version = "0.4.34" +version = "0.4.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e86f6d3dc9dc4352edeea6b8e499e13e3f5dc3b964d7ca5fd411415a3498473" +checksum = "07a926debf178f2d355197f9caddb08e54a9329d44748034bba349c5848cb519" dependencies = [ "compression-codecs", "compression-core", @@ -211,21 +202,6 @@ dependencies = [ "tower-service", ] -[[package]] -name = "backtrace" -version = "0.3.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-link", -] - [[package]] name = "base16ct" version = "0.2.0" @@ -252,9 +228,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" +checksum = "0e050f626429857a27ddccb31e0aca21356bfa709c04041aefddac081a8f068a" [[package]] name = "bitflags" @@ -306,9 +282,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.48" +version = "1.2.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c481bdbf0ed3b892f6f806287d72acd515b352a4ec27a208489b8c1bc839633a" +checksum = "90583009037521a116abf44494efecd645ba48b6622457080f080b85544e2215" dependencies = [ "find-msvc-tools", "shlex", @@ -425,9 +401,9 @@ dependencies = [ [[package]] name = "compression-codecs" -version = "0.4.33" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302266479cb963552d11bd042013a58ef1adc56768016c8b82b4199488f2d4ad" +checksum = "34a3cbbb8b6eca96f3a5c4bf6938d5b27ced3675d69f95bb51948722870bc323" dependencies = [ "compression-core", "flate2", @@ -576,9 +552,9 @@ dependencies = [ [[package]] name = "criterion" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0dfe5e9e71bdcf4e4954f7d14da74d1cdb92a3a07686452d1509652684b1aab" +checksum = "4d883447757bb0ee46f233e9dc22eb84d93a9508c9b868687b274fc431d886bf" dependencies = [ "alloca", "anes", @@ -600,9 +576,9 @@ dependencies = [ [[package]] name = "criterion-plot" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de36c2bee19fba779808f92bf5d9b0fa5a40095c277aba10c458a12b35d21d6" +checksum = "ed943f81ea2faa8dcecbbfa50164acf95d555afec96a27871663b300e387b2e4" dependencies = [ "cast", "itertools 0.13.0", @@ -832,22 +808,6 @@ dependencies = [ "syn", ] -[[package]] -name = "dhat" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cd11d84628e233de0ce467de10b8633f4ddaecafadefc86e13b84b8739b827" -dependencies = [ - "backtrace", - "lazy_static", - "mintex", - "parking_lot", - "rustc-hash 1.1.0", - "serde", - "serde_json", - "thousands", -] - [[package]] name = "digest" version = "0.10.7" @@ -1008,9 +968,9 @@ checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" [[package]] name = "flate2" -version = "1.1.7" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2152dbcb980c05735e2a651d96011320a949eb31a0c8b38b72645ce97dec676" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" dependencies = [ "crc32fast", "miniz_oxide", @@ -1160,12 +1120,6 @@ dependencies = [ "wasip2", ] -[[package]] -name = "gimli" -version = "0.32.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" - [[package]] name = "group" version = "0.13.0" @@ -1666,15 +1620,6 @@ version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08ab2867e3eeeca90e844d1940eab391c9dc5228783db2ed999acbc0a9ed375a" -[[package]] -name = "matchers" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" -dependencies = [ - "regex-automata", -] - [[package]] name = "matchit" version = "0.8.4" @@ -1725,12 +1670,6 @@ dependencies = [ "simd-adler32", ] -[[package]] -name = "mintex" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c505b3e17ed6b70a7ed2e67fbb2c560ee327353556120d6e72f5232b6880d536" - [[package]] name = "mio" version = "1.1.1" @@ -1817,15 +1756,6 @@ dependencies = [ "libc", ] -[[package]] -name = "object" -version = "0.37.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.21.3" @@ -2171,13 +2101,13 @@ dependencies = [ "bytes", "console-subscriber", "crossbeam", - "dhat", "flate2", "futures", "hmac 0.13.0-rc.3", "libloading", "log", "num-bigint", + "pkcs8 0.11.0-rc.8", "pumpkin-config", "pumpkin-data", "pumpkin-inventory", @@ -2188,10 +2118,8 @@ dependencies = [ "pumpkin-util", "pumpkin-world", "rand", - "rayon", "rsa", - "rsa-der", - "rustc-hash 2.1.1", + "rustc-hash", "rustyline-async", "serde", "serde_json", @@ -2265,7 +2193,6 @@ dependencies = [ name = "pumpkin-macros" version = "0.1.0-dev+1.21.10" dependencies = [ - "heck", "proc-macro-error2", "proc-macro2", "quote", @@ -2367,8 +2294,7 @@ dependencies = [ "pumpkin-nbt", "pumpkin-util", "rand", - "rayon", - "rustc-hash 2.1.1", + "rustc-hash", "ruzstd", "serde", "serde_json", @@ -2526,27 +2452,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rsa-der" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19473b2de3164677ff38e4309c42448ba8d0fe5ad5fa722e7d278f991859aa6" -dependencies = [ - "simple_asn1", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - [[package]] name = "rustc-hash" version = "2.1.1" @@ -2858,18 +2763,6 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" -[[package]] -name = "simple_asn1" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" -dependencies = [ - "num-bigint", - "num-traits", - "thiserror", - "time", -] - [[package]] name = "simplelog" version = "0.12.2" @@ -2896,9 +2789,9 @@ checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "slotmap" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "811fec94324ff439b2d5e4a1cf88cc5b6c09d92358715d600b2fe91c0489b5cb" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" dependencies = [ "version_check", ] @@ -3054,12 +2947,6 @@ dependencies = [ "syn", ] -[[package]] -name = "thousands" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bf63baf9f5039dadc247375c29eb13706706cfde997d0330d05aa63a77d8820" - [[package]] name = "thread_local" version = "1.1.9" @@ -3323,12 +3210,8 @@ version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" dependencies = [ - "matchers", - "once_cell", - "regex-automata", "sharded-slab", "thread_local", - "tracing", "tracing-core", ] diff --git a/pumpkin-data/build/item.rs b/pumpkin-data/build/item.rs index 4c8227210..9d870497b 100644 --- a/pumpkin-data/build/item.rs +++ b/pumpkin-data/build/item.rs @@ -284,7 +284,7 @@ impl ToTokens for ItemComponents { .clone() .map(|list| { let vec: Vec<_> = list - .get_values() + .into_vec() .iter() .map(|reg| { match reg { diff --git a/pumpkin-inventory/src/screen_handler.rs b/pumpkin-inventory/src/screen_handler.rs index 1d37165bd..1fd075b6e 100644 --- a/pumpkin-inventory/src/screen_handler.rs +++ b/pumpkin-inventory/src/screen_handler.rs @@ -1025,7 +1025,7 @@ pub trait ScreenHandlerListener: Send + Sync { _slot: u8, _stack: ItemStack, ) -> Pin + Send + 'a>> { - Box::pin(async move {}) + Box::pin(async {}) } fn on_property_update<'a>( &'a self, @@ -1033,7 +1033,7 @@ pub trait ScreenHandlerListener: Send + Sync { _property: u8, _value: i32, ) -> Pin + Send + 'a>> { - Box::pin(async move {}) + Box::pin(async {}) } } diff --git a/pumpkin-inventory/src/slot.rs b/pumpkin-inventory/src/slot.rs index d09f04281..97a5e6348 100644 --- a/pumpkin-inventory/src/slot.rs +++ b/pumpkin-inventory/src/slot.rs @@ -38,7 +38,7 @@ pub trait Slot: Send + Sync + Debug { _stack: ItemStack, _stack_prev: ItemStack, ) -> BoxFuture<'_, ()> { - Box::pin(async move {}) // Default implementation + Box::pin(async {}) // Default implementation } /// Callback for when an item is taken from the slot. @@ -57,7 +57,7 @@ pub trait Slot: Send + Sync + Debug { // Used for plugins fn on_click(&self, _player: &dyn InventoryPlayer) -> BoxFuture<'_, ()> { - Box::pin(async move {}) // Default implementation + Box::pin(async {}) // Default implementation } fn can_insert<'a>(&'a self, _stack: &'a ItemStack) -> BoxFuture<'a, bool> { diff --git a/pumpkin-macros/Cargo.toml b/pumpkin-macros/Cargo.toml index 1ab6388af..f16777ac5 100644 --- a/pumpkin-macros/Cargo.toml +++ b/pumpkin-macros/Cargo.toml @@ -9,7 +9,6 @@ proc-macro = true [dependencies] proc-macro-error2.workspace = true -heck = "0.5" proc-macro2 = "1.0" quote = "1.0" syn.workspace = true diff --git a/pumpkin-macros/src/lib.rs b/pumpkin-macros/src/lib.rs index 03c8301b4..c971f0e37 100644 --- a/pumpkin-macros/src/lib.rs +++ b/pumpkin-macros/src/lib.rs @@ -1,22 +1,18 @@ -use heck::{ToPascalCase, ToSnakeCase}; use proc_macro::TokenStream; use proc_macro_error2::{abort, abort_call_site, proc_macro_error}; use quote::quote; use syn::spanned::Spanned; -use syn::{self, Attribute, Type}; -use syn::{ - Block, Expr, Field, Fields, ItemStruct, Stmt, - parse::{Nothing, Parser}, - parse_macro_input, -}; +use syn::{self, Attribute, DeriveInput, LitStr, Type, parse_quote}; +use syn::{Block, Expr, Field, Fields, ItemStruct, Stmt, parse_macro_input}; #[proc_macro_derive(Event)] pub fn event(item: TokenStream) -> TokenStream { - let input = parse_macro_input!(item as ItemStruct); - let name = &input.ident; + let ast = parse_macro_input!(item as DeriveInput); + let name = &ast.ident; + let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); quote! { - impl crate::plugin::Payload for #name { + impl #impl_generics crate::plugin::Payload for #name #ty_generics #where_clause { fn get_name_static() -> &'static str { stringify!(#name) } @@ -38,26 +34,36 @@ pub fn event(item: TokenStream) -> TokenStream { } #[proc_macro_attribute] -pub fn cancellable(args: TokenStream, input: TokenStream) -> TokenStream { +pub fn cancellable(_args: TokenStream, input: TokenStream) -> TokenStream { let mut item_struct = parse_macro_input!(input as ItemStruct); - let name = item_struct.ident.clone(); - let _ = parse_macro_input!(args as Nothing); + let name = &item_struct.ident; + let (impl_generics, ty_generics, where_clause) = item_struct.generics.split_for_impl(); - if let Fields::Named(ref mut fields) = item_struct.fields { - fields.named.push( - Field::parse_named - .parse2(quote! { - /// A boolean indicating cancel state of the event. - pub cancelled: bool - }) - .unwrap(), - ); + match &mut item_struct.fields { + Fields::Named(fields) => { + if fields + .named + .iter() + .any(|f| f.ident.as_ref().map(|i| i == "cancelled").unwrap_or(false)) + { + abort!(fields.span(), "Struct already has a `cancelled` field"); + } + + let field: Field = parse_quote! { + pub cancelled: bool + }; + fields.named.push(field); + } + _ => abort!( + item_struct.span(), + "#[cancellable] can only be used on structs with named fields" + ), } quote! { #item_struct - impl crate::plugin::Cancellable for #name { + impl #impl_generics crate::plugin::Cancellable for #name #ty_generics #where_clause { fn cancelled(&self) -> bool { self.cancelled } @@ -73,115 +79,116 @@ pub fn cancellable(args: TokenStream, input: TokenStream) -> TokenStream { #[proc_macro_error] #[proc_macro] pub fn send_cancellable(input: TokenStream) -> TokenStream { - let input = parse_macro_input!(input as Block); + let block = parse_macro_input!(input as Block); - let mut event = None; + let mut event_expr = None; let mut after_block = None; let mut cancelled_block = None; - for stmt in input.stmts { - if let Stmt::Expr(expr, _) = stmt { - if event.is_none() { - event = Some(expr); - } else if let Expr::Block(b) = expr - && let Some(ref label) = b.label - { - if label.name.ident == "after" { - after_block = Some(b); - } else if label.name.ident == "cancelled" { - cancelled_block = Some(b); + for stmt in block.stmts { + match stmt { + Stmt::Expr(expr, _) => { + // Check if it is a labeled block first + let mut is_special_block = false; + if let Expr::Block(ref b) = expr + && let Some(ref label) = b.label + { + let label_name = label.name.ident.to_string(); + if label_name == "after" { + after_block = Some(b.clone()); // Clone strictly necessary here as we split AST + is_special_block = true; + } else if label_name == "cancelled" { + cancelled_block = Some(b.clone()); + is_special_block = true; + } + } + + // If it wasn't a special block, it must be the event expression + if !is_special_block { + if event_expr.is_some() { + abort!( + expr.span(), + "Multiple event expressions found. Only one event expression allowed." + ); + } + event_expr = Some(expr); } } + // Abort on other statements (like `let x = ...`) if strictness is desired + _ => abort!( + stmt.span(), + "Only event expressions and labeled blocks allowed in `send_cancellable!`" + ), } } - if let Some(event) = event { - if let Some(after_block) = after_block { - if let Some(cancelled_block) = cancelled_block { - quote! { - let event = crate::PLUGIN_MANAGER - .fire(#event) - .await; + let event = match event_expr { + Some(e) => e, + None => abort_call_site!("Event expression must be specified"), + }; - if !event.cancelled { - #after_block - } else { - #cancelled_block - } - } - .into() - } else { - quote! { - let event = crate::PLUGIN_MANAGER - .fire(#event) - .await; + // Construct the if/else logic + let logic = match (after_block, cancelled_block) { + (Some(after), Some(cancelled)) => quote! { + if !event.cancelled { #after } else { #cancelled } + }, + (Some(after), None) => quote! { + if !event.cancelled { #after } + }, + (None, Some(cancelled)) => quote! { + if event.cancelled { #cancelled } + }, + (None, None) => quote! {}, + }; - if !event.cancelled { - #after_block - } - } - .into() - } - } else if let Some(cancelled_block) = cancelled_block { - quote! { - let event = crate::PLUGIN_MANAGER - .fire(#event) - .await; - - if event.cancelled { - #cancelled_block - } - } - .into() - } else { - quote! { - let event = crate::PLUGIN_MANAGER - .fire(#event) - .await; - } - .into() - } - } else { - abort_call_site!("Event must be specified"); + quote! { + let event = crate::PLUGIN_MANAGER.fire(#event).await; + #logic } + .into() } #[proc_macro_attribute] -pub fn packet(input: TokenStream, item: TokenStream) -> TokenStream { - let ast: syn::DeriveInput = syn::parse(item.clone()).unwrap(); +pub fn packet(args: TokenStream, item: TokenStream) -> TokenStream { + let packet_id_expr = parse_macro_input!(args as Expr); + let ast = parse_macro_input!(item as DeriveInput); + let name = &ast.ident; - let (impl_generics, ty_generics, _) = ast.generics.split_for_impl(); + let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); - let input: proc_macro2::TokenStream = input.into(); - let item: proc_macro2::TokenStream = item.into(); + quote! { + #ast + impl #impl_generics crate::packet::Packet for #name #ty_generics #where_clause { + const PACKET_ID: i32 = #packet_id_expr; + } + } + .into() +} - let code = quote! { - #item - impl #impl_generics crate::packet::Packet for #name #ty_generics { - const PACKET_ID: i32 = #input; +#[proc_macro_attribute] +pub fn pumpkin_block(args: TokenStream, item: TokenStream) -> TokenStream { + let arg_lit = parse_macro_input!(args as LitStr); + let arg_value = arg_lit.value(); + + let (namespace, id) = match arg_value.split_once(':') { + Some(pair) => pair, + None => { + return syn::Error::new( + arg_lit.span(), + "Expected format \"namespace:id\" (e.g. \"minecraft:stone\")", + ) + .to_compile_error() + .into(); } }; - code.into() -} - -#[proc_macro_attribute] -pub fn pumpkin_block(input: TokenStream, item: TokenStream) -> TokenStream { - let ast: syn::DeriveInput = syn::parse(item.clone()).unwrap(); + let ast = parse_macro_input!(item as DeriveInput); let name = &ast.ident; - let (impl_generics, ty_generics, _) = ast.generics.split_for_impl(); - - let input_string = input.to_string(); - let packet_name = input_string.trim_matches('"'); - let (namespace, id) = packet_name - .split_once(":") - .unwrap_or_else(|| abort!(packet_name, "A namespace is required!")); - - let item: proc_macro2::TokenStream = item.into(); + let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); let code = quote! { - #item - impl #impl_generics crate::block::BlockMetadata for #name #ty_generics { + #ast + impl #impl_generics crate::block::BlockMetadata for #name #ty_generics #where_clause { fn namespace(&self) -> &'static str { #namespace } @@ -195,182 +202,183 @@ pub fn pumpkin_block(input: TokenStream, item: TokenStream) -> TokenStream { } #[proc_macro_attribute] -pub fn pumpkin_block_from_tag(input: TokenStream, item: TokenStream) -> TokenStream { - let ast: syn::DeriveInput = syn::parse(item.clone()).unwrap(); +pub fn pumpkin_block_from_tag(args: TokenStream, item: TokenStream) -> TokenStream { + let arg_lit = parse_macro_input!(args as LitStr); + let ast = parse_macro_input!(item as DeriveInput); + let name = &ast.ident; - let (impl_generics, ty_generics, _) = ast.generics.split_for_impl(); + let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); - let input_string = input.to_string(); - let packet_name = input_string.trim_matches('"'); - let packet_name_split: Vec<&str> = packet_name.split(":").collect(); + let full_tag = arg_lit.value(); - let namespace = packet_name_split[0]; + // Efficient splitting + let namespace = match full_tag.split_once(':') { + Some((ns, _)) => ns, + None => abort!(arg_lit.span(), "Expected format 'namespace:path'"), + }; - let item: proc_macro2::TokenStream = item.into(); - - let code = quote! { - #item - impl #impl_generics crate::block::BlockMetadata for #name #ty_generics { + quote! { + #ast + impl #impl_generics crate::block::BlockMetadata for #name #ty_generics #where_clause { fn namespace(&self) -> &'static str { #namespace } fn ids(&self) -> &'static [&'static str] { - get_tag_values(RegistryKey::Block, #packet_name).unwrap() + get_tag_values(RegistryKey::Block, #arg_lit).unwrap() } } - }; - - code.into() -} - -#[proc_macro_error] -#[proc_macro_attribute] -pub fn block_property(input: TokenStream, item: TokenStream) -> TokenStream { - let ast: syn::DeriveInput = syn::parse(item.clone()).unwrap(); - let name = &ast.ident; - let (impl_generics, ty_generics, _) = ast.generics.split_for_impl(); - - let input_string = input.to_string(); - let input_parts: Vec<&str> = input_string.split("[").collect(); - let property_name = input_parts[0].trim_ascii().trim_matches(&['"', ','][..]); - let mut property_values: Vec<&str> = Vec::new(); - if input_parts.len() > 1 { - property_values = input_parts[1] - .trim_matches(']') - .split(", ") - .map(|p| p.trim_ascii().trim_matches(&['"', ','][..])) - .collect::>(); } - - let item: proc_macro2::TokenStream = item.into(); - - let (variants, is_enum): (Vec, bool) = match ast.data { - syn::Data::Enum(enum_item) => ( - enum_item.variants.into_iter().map(|v| v.ident).collect(), - true, - ), - syn::Data::Struct(s) => { - let fields = match s.fields { - Fields::Named(f) => abort!(f.span(), "Block properties can't have named fields"), - Fields::Unnamed(fields) => fields.unnamed, - Fields::Unit => abort!(s.fields.span(), "Block properties must have fields"), - }; - if fields.len() != 1 { - abort!( - fields.span(), - "Block properties `struct`s must have exactly one field" - ); - } - let field = fields.first().unwrap(); - let ty = &field.ty; - let struct_type = match field.ty { - syn::Type::Path(ref type_path) => { - type_path.path.segments.first().unwrap().ident.to_string() - } - ref other => abort!( - other.span(), - "Block properties can only have primitive types" - ), - }; - match struct_type.as_str() { - "bool" => ( - vec![ - proc_macro2::Ident::new("true", proc_macro2::Span::call_site()), - proc_macro2::Ident::new("false", proc_macro2::Span::call_site()), - ], - false, - ), - other => abort!( - ty.span(), - format!("`{other}` is not supported (why not implement it yourself?)") - ), - } - } - _ => abort_call_site!("Block properties can only be `enum`s or `struct`s"), - }; - - let values = variants.iter().enumerate().map(|(i, v)| match is_enum { - true => { - let mut value = v.to_string().to_snake_case(); - if !property_values.is_empty() && i < property_values.len() { - value = property_values[i].to_string(); - } - quote! { - Self::#v => #value.to_string(), - } - } - false => { - let value = v.to_string(); - quote! { - Self(#v) => #value.to_string(), - } - } - }); - - let from_values = variants.iter().enumerate().map(|(i, v)| match is_enum { - true => { - let mut value = v.to_string().to_snake_case(); - if !property_values.is_empty() && i < property_values.len() { - value = property_values[i].to_string(); - } - quote! { - #value => Self::#v, - } - } - false => { - let value = v.to_string(); - quote! { - #value => Self(#v), - } - } - }); - - let extra_fns = variants.iter().map(|v| { - let title = proc_macro2::Ident::new( - &v.to_string().to_pascal_case(), - proc_macro2::Span::call_site(), - ); - quote! { - pub fn #title() -> Self { - Self(#v) - } - } - }); - - let extra = if is_enum { - quote! {} - } else { - quote! { - impl #name { - #(#extra_fns)* - } - } - }; - - let code = quote! { - #item - impl #impl_generics pumpkin_world::block::properties::BlockPropertyMetadata for #name #ty_generics { - fn name(&self) -> &'static str { - #property_name - } - fn value(&self) -> String { - match self { - #(#values)* - } - } - fn from_value(value: String) -> Self { - match value.as_str() { - #(#from_values)* - _ => panic!("Invalid value for block property"), - } - } - } - #extra - }; - - code.into() + .into() } +// #[proc_macro_error] +// #[proc_macro_attribute] +// pub fn block_property(input: TokenStream, item: TokenStream) -> TokenStream { +// let ast: syn::DeriveInput = syn::parse(item.clone()).unwrap(); +// let name = &ast.ident; +// let (impl_generics, ty_generics, _) = ast.generics.split_for_impl(); + +// let input_string = input.to_string(); +// let input_parts: Vec<&str> = input_string.split("[").collect(); +// let property_name = input_parts[0].trim_ascii().trim_matches(&['"', ','][..]); +// let mut property_values: Vec<&str> = Vec::new(); +// if input_parts.len() > 1 { +// property_values = input_parts[1] +// .trim_matches(']') +// .split(", ") +// .map(|p| p.trim_ascii().trim_matches(&['"', ','][..])) +// .collect::>(); +// } + +// let item: proc_macro2::TokenStream = item.into(); + +// let (variants, is_enum): (Vec, bool) = match ast.data { +// syn::Data::Enum(enum_item) => ( +// enum_item.variants.into_iter().map(|v| v.ident).collect(), +// true, +// ), +// syn::Data::Struct(s) => { +// let fields = match s.fields { +// Fields::Named(f) => abort!(f.span(), "Block properties can't have named fields"), +// Fields::Unnamed(fields) => fields.unnamed, +// Fields::Unit => abort!(s.fields.span(), "Block properties must have fields"), +// }; +// if fields.len() != 1 { +// abort!( +// fields.span(), +// "Block properties `struct`s must have exactly one field" +// ); +// } +// let field = fields.first().unwrap(); +// let ty = &field.ty; +// let struct_type = match field.ty { +// syn::Type::Path(ref type_path) => { +// type_path.path.segments.first().unwrap().ident.to_string() +// } +// ref other => abort!( +// other.span(), +// "Block properties can only have primitive types" +// ), +// }; +// match struct_type.as_str() { +// "bool" => ( +// vec![ +// proc_macro2::Ident::new("true", proc_macro2::Span::call_site()), +// proc_macro2::Ident::new("false", proc_macro2::Span::call_site()), +// ], +// false, +// ), +// other => abort!( +// ty.span(), +// format!("`{other}` is not supported (why not implement it yourself?)") +// ), +// } +// } +// _ => abort_call_site!("Block properties can only be `enum`s or `struct`s"), +// }; + +// let values = variants.iter().enumerate().map(|(i, v)| match is_enum { +// true => { +// let mut value = v.to_string().to_snake_case(); +// if !property_values.is_empty() && i < property_values.len() { +// value = property_values[i].to_string(); +// } +// quote! { +// Self::#v => #value.to_string(), +// } +// } +// false => { +// let value = v.to_string(); +// quote! { +// Self(#v) => #value.to_string(), +// } +// } +// }); + +// let from_values = variants.iter().enumerate().map(|(i, v)| match is_enum { +// true => { +// let mut value = v.to_string().to_snake_case(); +// if !property_values.is_empty() && i < property_values.len() { +// value = property_values[i].to_string(); +// } +// quote! { +// #value => Self::#v, +// } +// } +// false => { +// let value = v.to_string(); +// quote! { +// #value => Self(#v), +// } +// } +// }); + +// let extra_fns = variants.iter().map(|v| { +// let title = proc_macro2::Ident::new( +// &v.to_string().to_pascal_case(), +// proc_macro2::Span::call_site(), +// ); +// quote! { +// pub fn #title() -> Self { +// Self(#v) +// } +// } +// }); + +// let extra = if is_enum { +// quote! {} +// } else { +// quote! { +// impl #name { +// #(#extra_fns)* +// } +// } +// }; + +// let code = quote! { +// #item +// impl #impl_generics pumpkin_world::block::properties::BlockPropertyMetadata for #name #ty_generics { +// fn name(&self) -> &'static str { +// #property_name +// } +// fn value(&self) -> String { +// match self { +// #(#values)* +// } +// } +// fn from_value(value: String) -> Self { +// match value.as_str() { +// #(#from_values)* +// _ => panic!("Invalid value for block property"), +// } +// } +// } +// #extra +// }; + +// code.into() +// } + #[rustfmt::skip] #[proc_macro_derive(PacketWrite, attributes(serial))] pub fn derive_serialize(input: TokenStream) -> TokenStream { diff --git a/pumpkin-protocol/Cargo.toml b/pumpkin-protocol/Cargo.toml index f7eee1c07..59979e485 100644 --- a/pumpkin-protocol/Cargo.toml +++ b/pumpkin-protocol/Cargo.toml @@ -27,11 +27,11 @@ aes = "0.8" cfb8 = "0.8" # compression -async-compression = { version = "0.4.34", features = ["tokio", "zlib"] } +async-compression = { version = "0.4.35", features = ["tokio", "zlib"] } take_mut = "0.2.2" bitflags = "2.10.0" [dev-dependencies] # Validate correctness -flate2 = "1.1.7" +flate2 = "1.1.5" diff --git a/pumpkin-util/src/registry.rs b/pumpkin-util/src/registry.rs index a8f55beee..a4f3be2f6 100644 --- a/pumpkin-util/src/registry.rs +++ b/pumpkin-util/src/registry.rs @@ -45,11 +45,10 @@ pub enum RegistryEntryList { } impl RegistryEntryList { - #[allow(dead_code)] - pub fn get_values(&self) -> Vec { + pub fn into_vec(self) -> Vec { match self { - RegistryEntryList::Single(s) => vec![s.clone()], - RegistryEntryList::Many(s) => s.clone(), + RegistryEntryList::Single(s) => vec![s], + RegistryEntryList::Many(s) => s, } } } diff --git a/pumpkin-world/Cargo.toml b/pumpkin-world/Cargo.toml index 6a466dff9..6c7cac224 100644 --- a/pumpkin-world/Cargo.toml +++ b/pumpkin-world/Cargo.toml @@ -24,7 +24,6 @@ tokio = { workspace = true, features = [ "io-util", "time", ] } -rayon.workspace = true uuid.workspace = true thiserror.workspace = true serde.workspace = true diff --git a/pumpkin-world/src/block/entities/bed.rs b/pumpkin-world/src/block/entities/bed.rs index bdbac7364..54ed74de2 100644 --- a/pumpkin-world/src/block/entities/bed.rs +++ b/pumpkin-world/src/block/entities/bed.rs @@ -29,7 +29,7 @@ impl BlockEntity for BedBlockEntity { &'a self, _nbt: &'a mut NbtCompound, ) -> Pin + Send + 'a>> { - Box::pin(async move {}) + Box::pin(async {}) } fn as_any(&self) -> &dyn std::any::Any { diff --git a/pumpkin-world/src/block/entities/command_block.rs b/pumpkin-world/src/block/entities/command_block.rs index 0d8bb4b4e..310ec0ca8 100644 --- a/pumpkin-world/src/block/entities/command_block.rs +++ b/pumpkin-world/src/block/entities/command_block.rs @@ -48,7 +48,7 @@ impl BlockEntity for CommandBlockEntity { &'a self, _nbt: &'a mut NbtCompound, ) -> Pin + Send + 'a>> { - Box::pin(async move {}) + Box::pin(async {}) } fn is_dirty(&self) -> bool { diff --git a/pumpkin-world/src/block/entities/end_portal.rs b/pumpkin-world/src/block/entities/end_portal.rs index e96bc8f88..dff237b28 100644 --- a/pumpkin-world/src/block/entities/end_portal.rs +++ b/pumpkin-world/src/block/entities/end_portal.rs @@ -36,7 +36,7 @@ impl BlockEntity for EndPortalBlockEntity { &'a self, _nbt: &'a mut NbtCompound, ) -> Pin + Send + 'a>> { - Box::pin(async move {}) + Box::pin(async {}) } fn as_any(&self) -> &dyn std::any::Any { diff --git a/pumpkin-world/src/block/entities/ender_chest.rs b/pumpkin-world/src/block/entities/ender_chest.rs index 86cec3150..0352bea20 100644 --- a/pumpkin-world/src/block/entities/ender_chest.rs +++ b/pumpkin-world/src/block/entities/ender_chest.rs @@ -43,7 +43,7 @@ impl BlockEntity for EnderChestBlockEntity { &'a self, _nbt: &'a mut NbtCompound, ) -> Pin + Send + 'a>> { - Box::pin(async move {}) + Box::pin(async {}) } fn tick<'a>( diff --git a/pumpkin-world/src/block/entities/mod.rs b/pumpkin-world/src/block/entities/mod.rs index 8b23752f5..7106acf99 100644 --- a/pumpkin-world/src/block/entities/mod.rs +++ b/pumpkin-world/src/block/entities/mod.rs @@ -51,7 +51,7 @@ pub trait BlockEntity: Send + Sync { &'a self, _world: Arc, ) -> Pin + Send + 'a>> { - Box::pin(async move {}) + Box::pin(async {}) } fn resource_location(&self) -> &'static str; fn get_position(&self) -> BlockPos; diff --git a/pumpkin-world/src/block/entities/sign.rs b/pumpkin-world/src/block/entities/sign.rs index 3a4e93118..74ca88227 100644 --- a/pumpkin-world/src/block/entities/sign.rs +++ b/pumpkin-world/src/block/entities/sign.rs @@ -271,7 +271,7 @@ impl SignBlockEntity { Text::default() }, back_text: if !is_front { - Text::new(messages.clone()) + Text::new(messages) } else { Text::default() }, diff --git a/pumpkin-world/src/chunk/format/anvil.rs b/pumpkin-world/src/chunk/format/anvil.rs index 17e36ac88..3b8b8344c 100644 --- a/pumpkin-world/src/chunk/format/anvil.rs +++ b/pumpkin-world/src/chunk/format/anvil.rs @@ -307,9 +307,9 @@ impl AnvilChunkData { .decompress_data(&self.compressed_data) .map_err(ChunkReadingError::Compression)?; - S::from_bytes(decompress_bytes.into(), pos) + S::from_bytes(&decompress_bytes.into(), pos) } else { - S::from_bytes(self.compressed_data.clone(), pos) + S::from_bytes(&self.compressed_data, pos) } } @@ -521,7 +521,7 @@ pub trait SingleChunkDataSerializer: Send + Sync + Sized + Dirtiable { fn to_bytes( &self, ) -> Pin> + Send + '_>>; - fn from_bytes(bytes: Bytes, pos: Vector2) -> Result; + fn from_bytes(bytes: &Bytes, pos: Vector2) -> Result; fn position(&self) -> &Vector2; } @@ -540,7 +540,7 @@ impl ChunkSerializer for AnvilChunkFile { format!("./r.{region_x}.{region_z}.mca") } - async fn write(&self, path: PathBuf) -> Result<(), std::io::Error> { + async fn write(&self, path: &PathBuf) -> Result<(), std::io::Error> { let mut write_action = self.write_action.lock().await; match &*write_action { WriteAction::Pass => { @@ -550,9 +550,9 @@ impl ChunkSerializer for AnvilChunkFile { ); Ok(()) } - WriteAction::All => self.write_all(&path).await, + WriteAction::All => self.write_all(path).await, WriteAction::Parts(parts) => { - self.write_indices(&path, Vec::from_iter(parts.iter().cloned()).as_slice()) + self.write_indices(path, Vec::from_iter(parts.iter().cloned()).as_slice()) .await } }?; diff --git a/pumpkin-world/src/chunk/format/linear.rs b/pumpkin-world/src/chunk/format/linear.rs index 20d18d008..9d21d24cc 100644 --- a/pumpkin-world/src/chunk/format/linear.rs +++ b/pumpkin-world/src/chunk/format/linear.rs @@ -178,7 +178,7 @@ impl ChunkSerializer for LinearFile { format!("./r.{region_x}.{region_z}.linear") } - async fn write(&self, path: PathBuf) -> Result<(), std::io::Error> { + 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.display()); @@ -358,7 +358,7 @@ impl ChunkSerializer for LinearFile { let linear_chunk_data = &self.chunks_data[index]; let result = if let Some(data) = linear_chunk_data { - match S::from_bytes(data.clone(), chunk) { + match S::from_bytes(data, chunk) { Ok(chunk) => LoadedData::Loaded(chunk), Err(err) => LoadedData::Error((chunk, err)), } diff --git a/pumpkin-world/src/chunk/format/mod.rs b/pumpkin-world/src/chunk/format/mod.rs index 04f19672d..b695ff289 100644 --- a/pumpkin-world/src/chunk/format/mod.rs +++ b/pumpkin-world/src/chunk/format/mod.rs @@ -31,8 +31,8 @@ pub mod linear; impl SingleChunkDataSerializer for ChunkData { #[inline] - fn from_bytes(bytes: Bytes, pos: Vector2) -> Result { - Self::internal_from_bytes(&bytes, pos).map_err(ChunkReadingError::ParsingError) + fn from_bytes(bytes: &Bytes, pos: Vector2) -> Result { + Self::internal_from_bytes(bytes, pos).map_err(ChunkReadingError::ParsingError) } #[inline] @@ -116,46 +116,49 @@ impl ChunkData { position.x, position.y, chunk_data.x_pos, chunk_data.z_pos, ))); } - - let light_engine = ChunkLight { - block_light: chunk_data - .sections - .iter() - .map(|x| { - x.block_light - .clone() - .map(LightContainer::new) - .unwrap_or_default() - }) - .collect(), - sky_light: chunk_data - .sections - .iter() - .map(|x| { - x.sky_light - .clone() - .map(LightContainer::new) - .unwrap_or_default() - }) - .collect(), - }; - - let sub_chunks = chunk_data + let (block_lights, sky_lights, sub_chunks) = chunk_data .sections .into_iter() - .map(|section| SubChunk { - block_states: section - .block_states - .map(BlockPalette::from_disk_nbt) - .unwrap_or_default(), - biomes: section - .biomes - .map(BiomePalette::from_disk_nbt) - .unwrap_or_default(), + .map(|section| { + let block_light = section + .block_light + .map(LightContainer::new) + .unwrap_or_default(); + let sky_light = section + .sky_light + .map(LightContainer::new) + .unwrap_or_default(); + + let sub_chunk = SubChunk { + block_states: section + .block_states + .map(BlockPalette::from_disk_nbt) + .unwrap_or_default(), + biomes: section + .biomes + .map(BiomePalette::from_disk_nbt) + .unwrap_or_default(), + }; + + (block_light, sky_light, sub_chunk) }) - .collect(); + .fold( + (Vec::new(), Vec::new(), Vec::new()), + |(mut bl, mut sl, mut sc), (block_l, sky_l, sub_c)| { + bl.push(block_l); + sl.push(sky_l); + sc.push(sub_c); + (bl, sl, sc) + }, + ); + + // 2. Assemble the final structs using the collected vectors. + let light_engine = ChunkLight { + block_light: block_lights.into_boxed_slice(), + sky_light: sky_lights.into_boxed_slice(), + }; let min_y = section_coords::section_to_block(chunk_data.min_y_section); - let section = ChunkSections::new(sub_chunks, min_y); + let section = ChunkSections::new(sub_chunks.into_boxed_slice(), min_y); Ok(ChunkData { section, @@ -249,8 +252,8 @@ impl Dirtiable for ChunkEntityData { impl SingleChunkDataSerializer for ChunkEntityData { #[inline] - fn from_bytes(bytes: Bytes, pos: Vector2) -> Result { - Self::internal_from_bytes(&bytes, pos).map_err(ChunkReadingError::ParsingError) + fn from_bytes(bytes: &Bytes, pos: Vector2) -> Result { + Self::internal_from_bytes(bytes, pos).map_err(ChunkReadingError::ParsingError) } #[inline] diff --git a/pumpkin-world/src/chunk/io/file_manager.rs b/pumpkin-world/src/chunk/io/file_manager.rs index 77266eb8e..81bbfbf87 100644 --- a/pumpkin-world/src/chunk/io/file_manager.rs +++ b/pumpkin-world/src/chunk/io/file_manager.rs @@ -365,7 +365,7 @@ where log::debug!("Writing file for {}", path.display()); serializer - .write(path.clone()) + .write(&path) .await .map_err(|err| ChunkWritingError::IoError(err.kind()))?; diff --git a/pumpkin-world/src/chunk/io/mod.rs b/pumpkin-world/src/chunk/io/mod.rs index 439663fa5..b217c72a7 100644 --- a/pumpkin-world/src/chunk/io/mod.rs +++ b/pumpkin-world/src/chunk/io/mod.rs @@ -109,7 +109,7 @@ pub trait ChunkSerializer: Send + Sync + Default { /// Serialize the data to bytes. fn write( &self, - backend: Self::WriteBackend, + backend: &Self::WriteBackend, ) -> impl Future> + Send; /// Create a new instance from bytes diff --git a/pumpkin-world/src/generation/aquifer_sampler.rs b/pumpkin-world/src/generation/aquifer_sampler.rs index 1031db285..676ba5005 100644 --- a/pumpkin-world/src/generation/aquifer_sampler.rs +++ b/pumpkin-world/src/generation/aquifer_sampler.rs @@ -49,7 +49,7 @@ pub enum FluidLevelSampler { } impl FluidLevelSamplerImpl for FluidLevelSampler { - fn get_fluid_level(&self, x: i32, y: i32, z: i32) -> FluidLevel { + fn get_fluid_level(&self, x: i32, y: i32, z: i32) -> &FluidLevel { match self { FluidLevelSampler::Static(sampler) => sampler.get_fluid_level(x, y, z), FluidLevelSampler::Chunk(sampler) => sampler.get_fluid_level(x, y, z), @@ -58,24 +58,25 @@ impl FluidLevelSamplerImpl for FluidLevelSampler { } pub struct StaticFluidLevelSampler { - y: i32, - block: &'static Block, + fluid_level: FluidLevel, } impl StaticFluidLevelSampler { pub fn new(y: i32, block: &'static Block) -> Self { - Self { y, block } + Self { + fluid_level: FluidLevel::new(y, block), + } } } impl FluidLevelSamplerImpl for StaticFluidLevelSampler { - fn get_fluid_level(&self, _x: i32, _y: i32, _z: i32) -> FluidLevel { - FluidLevel::new(self.y, self.block) + fn get_fluid_level(&self, _x: i32, _y: i32, _z: i32) -> &FluidLevel { + &self.fluid_level } } pub trait FluidLevelSamplerImpl { - fn get_fluid_level(&self, x: i32, y: i32, z: i32) -> FluidLevel; + fn get_fluid_level(&self, x: i32, y: i32, z: i32) -> &FluidLevel; } #[enum_dispatch(AquiferSamplerImpl)] @@ -103,8 +104,7 @@ macro_rules! local_y { } pub struct WorldAquiferSampler { - random_deriver: RandomDeriver, - fluid_level: FluidLevelSampler, + fluid_level_sampler: FluidLevelSampler, start_x: i32, start_y: i8, start_z: i32, @@ -134,7 +134,7 @@ impl WorldAquiferSampler { #[allow(clippy::too_many_arguments)] pub fn new( chunk_pos: Vector2, - random_deriver: RandomDeriver, + random_deriver: &RandomDeriver, minimum_y: i8, height: u16, fluid_level: FluidLevelSampler, @@ -176,8 +176,7 @@ impl WorldAquiferSampler { } Self { - random_deriver, - fluid_level, + fluid_level_sampler: fluid_level, start_x, start_y, start_z, @@ -230,13 +229,12 @@ impl WorldAquiferSampler { } fn calculate_density( - &mut self, barrier_sample: &mut Option, pos: &impl NoisePos, router: &mut ChunkNoiseRouter, sample_options: &ChunkNoiseFunctionSampleOptions, - level_1: FluidLevel, - level_2: FluidLevel, + level_1: &FluidLevel, + level_2: &FluidLevel, ) -> f64 { let y = pos.y(); let block_state1 = level_1.get_block(y); @@ -280,7 +278,7 @@ impl WorldAquiferSampler { router: &mut ChunkNoiseRouter, height_estimator: &mut SurfaceHeightEstimateSampler, sample_options: &ChunkNoiseFunctionSampleOptions, - ) -> FluidLevel { + ) -> &FluidLevel { let x = block_pos::unpack_x(packed_pos); let y = block_pos::unpack_y(packed_pos); let z = block_pos::unpack_z(packed_pos); @@ -290,18 +288,26 @@ impl WorldAquiferSampler { let local_z = local_xz!(z); let index = self.packed_position_index(local_x, local_y, local_z); - if let Some(level) = &self.levels[index] { - level.clone() - } else { - let fluid_level = - self.get_fluid_level(x, y, z, router, height_estimator, sample_options); - self.levels[index] = Some(fluid_level.clone()); - fluid_level - } + let entry = self + .levels + .get_mut(index) + .expect("Index calculated by packed_position_index is out of bounds for self.levels"); + let fluid_level = &self.fluid_level_sampler; + entry.get_or_insert_with(|| { + Self::get_fluid_level( + fluid_level, + x, + y, + z, + router, + height_estimator, + sample_options, + ) + }) } fn get_fluid_level( - &mut self, + fluid_level_sampler: &FluidLevelSampler, block_x: i32, block_y: i32, block_z: i32, @@ -309,7 +315,7 @@ impl WorldAquiferSampler { height_estimator: &mut SurfaceHeightEstimateSampler, sample_options: &ChunkNoiseFunctionSampleOptions, ) -> FluidLevel { - let fluid_level = self.fluid_level.get_fluid_level(block_x, block_y, block_z); + let fluid_level = fluid_level_sampler.get_fluid_level(block_x, block_y, block_z); let j = block_y + 12; let k = block_y - 12; let mut bl = false; @@ -324,19 +330,19 @@ impl WorldAquiferSampler { let bl2 = offset.x == 0 && offset.y == 0; if bl2 && k > o { - return fluid_level; + return fluid_level.clone(); } let bl3 = j > o; if bl3 || bl2 { - let fluid_level = self.fluid_level.get_fluid_level(x, o, z); + let fluid_level = fluid_level_sampler.get_fluid_level(x, o, z); if !fluid_level.get_block(o).default_state.is_air() { if bl2 { bl = true; } if bl3 { - return fluid_level; + return fluid_level.clone(); } } } @@ -344,11 +350,11 @@ impl WorldAquiferSampler { min_surface_estimate = min_surface_estimate.min(n); } - let p = self.get_fluid_block_y( + let p = Self::get_fluid_block_y( block_x, block_y, block_z, - fluid_level.clone(), + fluid_level, min_surface_estimate, bl, router, @@ -356,7 +362,7 @@ impl WorldAquiferSampler { ); FluidLevel::new( p, - self.get_fluid_block_state( + WorldAquiferSampler::get_fluid_block_state( block_x, block_y, block_z, @@ -370,11 +376,10 @@ impl WorldAquiferSampler { #[allow(clippy::too_many_arguments)] fn get_fluid_block_y( - &mut self, block_x: i32, block_y: i32, block_z: i32, - default_level: FluidLevel, + default_level: &FluidLevel, surface_height_estimate: i32, map_y: bool, router: &mut ChunkNoiseRouter, @@ -407,7 +412,7 @@ impl WorldAquiferSampler { if e > 0f64 { default_level.max_y } else if d > 0f64 { - self.get_noise_based_fluid_level( + Self::get_noise_based_fluid_level( block_x, block_y, block_z, @@ -421,7 +426,6 @@ impl WorldAquiferSampler { } fn get_noise_based_fluid_level( - &mut self, block_x: i32, block_y: i32, block_z: i32, @@ -446,11 +450,10 @@ impl WorldAquiferSampler { #[allow(clippy::too_many_arguments)] fn get_fluid_block_state( - &mut self, block_x: i32, block_y: i32, block_z: i32, - default_level: FluidLevel, + default_level: &FluidLevel, level: i32, router: &mut ChunkNoiseRouter, sample_options: &ChunkNoiseFunctionSampleOptions, @@ -486,7 +489,7 @@ impl WorldAquiferSampler { let sample_z = pos.z(); let fluid_level = self - .fluid_level + .fluid_level_sampler .get_fluid_level(sample_x, sample_y, sample_z); if fluid_level.get_block(sample_y) == &LAVA_BLOCK { Some(LAVA_BLOCK.default_state) @@ -521,13 +524,14 @@ impl WorldAquiferSampler { random_positions_and_hypot[0] = (packed_random, hypot_squared); } } - - let fluid_level2 = self.get_water_level( - random_positions_and_hypot[0].0, - router, - height_estimator, - sample_options, - ); + let fluid_level2 = self + .get_water_level( + random_positions_and_hypot[0].0, + router, + height_estimator, + sample_options, + ) + .clone(); let d = Self::max_distance( random_positions_and_hypot[0].1, random_positions_and_hypot[1].1, @@ -540,7 +544,7 @@ impl WorldAquiferSampler { Some(block_state.default_state) } else if block_state == &WATER_BLOCK && self - .fluid_level + .fluid_level_sampler .get_fluid_level(sample_x, sample_y - 1, sample_z) .get_block(sample_y - 1) == &LAVA_BLOCK @@ -548,19 +552,21 @@ impl WorldAquiferSampler { Some(block_state.default_state) } else { let mut barrier_sample = None; - let fluid_level3 = self.get_water_level( - random_positions_and_hypot[1].0, - router, - height_estimator, - sample_options, - ); - let e = d * self.calculate_density( + let fluid_level3 = self + .get_water_level( + random_positions_and_hypot[1].0, + router, + height_estimator, + sample_options, + ) + .clone(); + let e = d * Self::calculate_density( &mut barrier_sample, pos, router, sample_options, - fluid_level2.clone(), - fluid_level3.clone(), + &fluid_level2, + &fluid_level3, ); if density + e > 0f64 { @@ -579,13 +585,13 @@ impl WorldAquiferSampler { if f > 0f64 { let g = d * f - * self.calculate_density( + * Self::calculate_density( &mut barrier_sample, pos, router, sample_options, - fluid_level2, - fluid_level4.clone(), + &fluid_level2, + fluid_level4, ); if density + g > 0f64 { return None; @@ -599,12 +605,12 @@ impl WorldAquiferSampler { if g > 0f64 { let h = d * g - * self.calculate_density( + * Self::calculate_density( &mut barrier_sample, pos, router, sample_options, - fluid_level3, + &fluid_level3, fluid_level4, ); if density + h > 0f64 { @@ -794,7 +800,7 @@ mod random_positions_and_hypot { #[test] fn test_get_fluid_block_state() { - let (mut aquifer, mut router, _, options) = create_aquifer(&PROTO_ROUTER); + let (_, mut router, _, options) = create_aquifer(&PROTO_ROUTER); let level = FluidLevel::new(0, &WATER_BLOCK); let values = [ @@ -927,7 +933,15 @@ mod random_positions_and_hypot { for ((x, y, z), result) in values { assert_eq!( - aquifer.get_fluid_block_state(x, y, z, level.clone(), -10, &mut router, &options), + WorldAquiferSampler::get_fluid_block_state( + x, + y, + z, + &level, + -10, + &mut router, + &options + ), &result ); } @@ -935,7 +949,7 @@ mod random_positions_and_hypot { #[test] fn test_get_noise_based_fluid_level() { - let (mut aquifer, mut router, _, options) = create_aquifer(&PROTO_ROUTER); + let (_, mut router, _, options) = create_aquifer(&PROTO_ROUTER); let values = [ ((-100, -100, -100), -103), @@ -1067,7 +1081,14 @@ mod random_positions_and_hypot { for ((x, y, z), result) in values { assert_eq!( - aquifer.get_noise_based_fluid_level(x, y, z, 200, &mut router, &options), + WorldAquiferSampler::get_noise_based_fluid_level( + x, + y, + z, + 200, + &mut router, + &options + ), result ); } @@ -1075,7 +1096,7 @@ mod random_positions_and_hypot { #[test] fn test_get_fluid_block_y() { - let (mut aquifer, mut router, _, env) = create_aquifer(&PROTO_ROUTER); + let (_, mut router, _, env) = create_aquifer(&PROTO_ROUTER); let level = FluidLevel::new(0, &WATER_BLOCK); let values = [ ((-100, -100, -100), -32512), @@ -1207,7 +1228,16 @@ mod random_positions_and_hypot { for ((x, y, z), result) in values { assert_eq!( - aquifer.get_fluid_block_y(x, y, z, level.clone(), 80, true, &mut router, &env), + WorldAquiferSampler::get_fluid_block_y( + x, + y, + z, + &level, + 80, + true, + &mut router, + &env + ), result ); } @@ -1342,7 +1372,16 @@ mod random_positions_and_hypot { for ((x, y, z), result) in values { assert_eq!( - aquifer.get_fluid_block_y(x, y, z, level.clone(), 80, false, &mut router, &env), + WorldAquiferSampler::get_fluid_block_y( + x, + y, + z, + &level, + 80, + false, + &mut router, + &env + ), result ); } @@ -1350,7 +1389,7 @@ mod random_positions_and_hypot { #[test] fn test_get_fluid_level() { - let (mut aquifer, mut router, mut height_estimator, env) = create_aquifer(&PROTO_ROUTER); + let (aquifer, mut router, mut height_estimator, env) = create_aquifer(&PROTO_ROUTER); let values = [ ((-100, -100, -100), (-32512, LAVA_BLOCK)), ((-100, -100, -50), (-32512, LAVA_BLOCK)), @@ -1479,8 +1518,17 @@ mod random_positions_and_hypot { ((100, 100, 100), (63, WATER_BLOCK)), ]; + let fluid_level_sampler = &aquifer.fluid_level_sampler; for ((x, y, z), (y1, state)) in values { - let level = aquifer.get_fluid_level(x, y, z, &mut router, &mut height_estimator, &env); + let level = WorldAquiferSampler::get_fluid_level( + fluid_level_sampler, + x, + y, + z, + &mut router, + &mut height_estimator, + &env, + ); assert_eq!(level.max_y, y1); assert_eq!(level.block, &state); } @@ -1488,7 +1536,7 @@ mod random_positions_and_hypot { #[test] fn test_calculate_density() { - let (mut aquifer, mut router, _, env) = create_aquifer(&PROTO_ROUTER); + let (_, mut router, _, env) = create_aquifer(&PROTO_ROUTER); let values = [ ((-100, -100, -100, 0, 0), 0.0), @@ -1625,7 +1673,14 @@ mod random_positions_and_hypot { let mut sample = None; assert_eq!( - aquifer.calculate_density(&mut sample, &pos, &mut router, &env, level1, level2), + WorldAquiferSampler::calculate_density( + &mut sample, + &pos, + &mut router, + &env, + &level1, + &level2 + ), result ); } diff --git a/pumpkin-world/src/generation/block_state_provider.rs b/pumpkin-world/src/generation/block_state_provider.rs index 56a26c8f7..2e7df1b25 100644 --- a/pumpkin-world/src/generation/block_state_provider.rs +++ b/pumpkin-world/src/generation/block_state_provider.rs @@ -106,7 +106,11 @@ impl DualNoiseBlockStateProvider { &BlockPos(pos.0.add(&Vector3::new(i * 54545, 0, i * 34234))), &sampler, ); - list.push(self.base.get_state_by_value(&self.base.states, value)); + list.push( + self.base + .get_state_by_value(&self.base.states, value) + .clone(), + ); } let value = self.base.base.get_noise(pos); self.base.get_state_by_value(&list, value).get_state() @@ -184,9 +188,13 @@ impl NoiseBlockStateProvider { self.get_state_by_value(&self.states, value).get_state() } - fn get_state_by_value(&self, states: &[BlockStateCodec], value: f64) -> BlockStateCodec { + fn get_state_by_value<'a>( + &self, + states: &'a [BlockStateCodec], + value: f64, + ) -> &'a BlockStateCodec { let val = ((1.0 + value) / 2.0).clamp(0.0, 0.9999); - states[(val * states.len() as f64) as usize].clone() + &states[(val * states.len() as f64) as usize] } } diff --git a/pumpkin-world/src/generation/chunk_noise.rs b/pumpkin-world/src/generation/chunk_noise.rs index 85027c53c..c74f6f15f 100644 --- a/pumpkin-world/src/generation/chunk_noise.rs +++ b/pumpkin-world/src/generation/chunk_noise.rs @@ -210,7 +210,7 @@ impl<'a> ChunkNoiseGenerator<'a> { let section_z = section_coords::block_to_section(start_block_z); AquiferSampler::Aquifer(WorldAquiferSampler::new( Vector2::new(section_x, section_z), - random_config.aquifer_random_deriver.clone(), + &random_config.aquifer_random_deriver, generation_shape.min_y, generation_shape.height, level_sampler, diff --git a/pumpkin-world/src/generation/feature/features/spring_feature.rs b/pumpkin-world/src/generation/feature/features/spring_feature.rs index caddeac8e..bc7ffd6be 100644 --- a/pumpkin-world/src/generation/feature/features/spring_feature.rs +++ b/pumpkin-world/src/generation/feature/features/spring_feature.rs @@ -21,6 +21,15 @@ enum BlockWrapper { Multi(Vec), } +impl BlockWrapper { + fn contains(&self, name: &str) -> bool { + match self { + Self::Single(s) => s == name, + Self::Multi(h) => h.contains(&name.to_string()), + } + } +} + impl SpringFeatureFeature { pub fn generate( &self, @@ -29,91 +38,80 @@ impl SpringFeatureFeature { _random: &mut RandomGenerator, pos: BlockPos, ) -> bool { - // i don't think this is the most efficient way, but it works - let valid_blocks = match self.valid_blocks.clone() { - BlockWrapper::Single(item) => vec![item], - BlockWrapper::Multi(items) => items, - }; + let valid_blocks = &self.valid_blocks; + if !valid_blocks.contains( - &GenerationCache::get_block_state(chunk, &pos.up().0) + GenerationCache::get_block_state(chunk, &pos.up().0) .to_block() - .name - .to_string(), + .name, ) { return false; } if self.requires_block_below && !valid_blocks.contains( - &GenerationCache::get_block_state( + GenerationCache::get_block_state( chunk, &pos.offset(BlockDirection::Down.to_offset()).0, ) .to_block() - .name - .to_string(), + .name, ) { return false; } let state = GenerationCache::get_block_state(chunk, &pos.0); - if !state.to_state().is_air() && !valid_blocks.contains(&state.to_block().name.to_string()) - { + if !state.to_state().is_air() && !valid_blocks.contains(state.to_block().name) { return false; } let mut valid = 0; if valid_blocks.contains( - &GenerationCache::get_block_state( + GenerationCache::get_block_state( chunk, &pos.offset(BlockDirection::West.to_offset()).0, ) .to_block() - .name - .to_string(), + .name, ) { valid += 1; } if valid_blocks.contains( - &GenerationCache::get_block_state( + GenerationCache::get_block_state( chunk, &pos.offset(BlockDirection::East.to_offset()).0, ) .to_block() - .name - .to_string(), + .name, ) { valid += 1; } if valid_blocks.contains( - &GenerationCache::get_block_state( + GenerationCache::get_block_state( chunk, &pos.offset(BlockDirection::North.to_offset()).0, ) .to_block() - .name - .to_string(), + .name, ) { valid += 1; } if valid_blocks.contains( - &GenerationCache::get_block_state( + GenerationCache::get_block_state( chunk, &pos.offset(BlockDirection::South.to_offset()).0, ) .to_block() - .name - .to_string(), + .name, ) { valid += 1; } if valid_blocks.contains( - &GenerationCache::get_block_state( + GenerationCache::get_block_state( chunk, &pos.offset(BlockDirection::Down.to_offset()).0, ) .to_block() - .name - .to_string(), + .name, ) { valid += 1; } diff --git a/pumpkin-world/src/generation/proto_chunk.rs b/pumpkin-world/src/generation/proto_chunk.rs index ea2875278..c4162dd87 100644 --- a/pumpkin-world/src/generation/proto_chunk.rs +++ b/pumpkin-world/src/generation/proto_chunk.rs @@ -82,11 +82,11 @@ impl StandardChunkFluidLevelSampler { } impl FluidLevelSamplerImpl for StandardChunkFluidLevelSampler { - fn get_fluid_level(&self, _x: i32, y: i32, _z: i32) -> FluidLevel { + fn get_fluid_level(&self, _x: i32, y: i32, _z: i32) -> &FluidLevel { if y < self.bottom_y { - self.bottom_fluid.clone() + &self.bottom_fluid } else { - self.top_fluid.clone() + &self.top_fluid } } } diff --git a/pumpkin-world/src/level.rs b/pumpkin-world/src/level.rs index 442c9cbf1..bb7661da9 100644 --- a/pumpkin-world/src/level.rs +++ b/pumpkin-world/src/level.rs @@ -842,7 +842,7 @@ impl Level { .await; let mut chunk = chunk.write().await; chunk.block_ticks.schedule_tick( - ScheduledTick { + &ScheduledTick { delay, position: block_pos, priority, @@ -865,7 +865,7 @@ impl Level { .await; let mut chunk = chunk.write().await; chunk.fluid_ticks.schedule_tick( - ScheduledTick { + &ScheduledTick { delay, position: block_pos, priority, diff --git a/pumpkin-world/src/tick/scheduler.rs b/pumpkin-world/src/tick/scheduler.rs index 8c04910bd..506bfebad 100644 --- a/pumpkin-world/src/tick/scheduler.rs +++ b/pumpkin-world/src/tick/scheduler.rs @@ -24,7 +24,7 @@ impl<'a, T: std::hash::Hash + Eq> ChunkTickScheduler<&'a T> { res } - pub fn schedule_tick(&mut self, tick: ScheduledTick<&'a T>, sub_tick_order: u64) { + pub fn schedule_tick(&mut self, tick: &ScheduledTick<&'a T>, sub_tick_order: u64) { if self.queued_ticks.insert((tick.position, tick.value)) { let index = (self.offset + tick.delay as usize) % MAX_TICK_DELAY; self.tick_queue[index].push(OrderedTick { @@ -57,7 +57,7 @@ impl<'a, T: std::hash::Hash + Eq> ChunkTickScheduler<&'a T> { pub fn from_vec(ticks: &[ScheduledTick<&'a T>]) -> Self { let mut scheduler = Self::default(); for tick in ticks { - scheduler.schedule_tick(tick.clone(), 0); + scheduler.schedule_tick(tick, 0); } scheduler } diff --git a/pumpkin-world/src/world_info/anvil.rs b/pumpkin-world/src/world_info/anvil.rs index 768a68d1f..6b0da2746 100644 --- a/pumpkin-world/src/world_info/anvil.rs +++ b/pumpkin-world/src/world_info/anvil.rs @@ -112,9 +112,7 @@ impl WorldInfoWriter for AnvilLevelInfo { .expect("Time went backwards"); let mut level_data = info.clone(); level_data.last_played = since_the_epoch.as_millis() as i64; - let level = LevelDat { - data: level_data.clone(), - }; + let level = LevelDat { data: level_data }; // open file let path = level_folder.join(LEVEL_DAT_FILE_NAME); diff --git a/pumpkin/Cargo.toml b/pumpkin/Cargo.toml index 9e57ccfee..dba8ae68e 100644 --- a/pumpkin/Cargo.toml +++ b/pumpkin/Cargo.toml @@ -41,7 +41,6 @@ tokio = { workspace = true, features = [ "io-util", "time", ] } -rayon.workspace = true thiserror.workspace = true futures.workspace = true @@ -60,13 +59,14 @@ rustyline-async = "0.4.7" # encryption rsa = { version = "=0.10.0-rc.10", features = ["sha1"] } -rsa-der = "0.3" +pkcs8 = "=0.11.0-rc.8" # authentication ureq = { version = "3.1.4", features = [ "json", ] } + sha1 = "=0.11.0-rc.3" # velocity en @@ -79,7 +79,7 @@ base64 = "0.22.1" simplelog = { version = "0.12.2", features = ["ansi_term"] } # Remove time in favor of chrono? -time = "0.3" +time = { version = "0.3", features = ["parsing", "macros"] } # plugins libloading = "0.9" @@ -88,18 +88,12 @@ rustc-hash = "2.1.1" # Task handling tokio-util = { version = "0.7.17", features = ["rt"] } -# Memory profiling -dhat = { version = "0.3.3", optional = true } - -flate2 = "1.1.7" -console-subscriber = { version = "0.5.0", optional = true } +flate2 = "1.1.5" +console-subscriber = { version = "0.5.0", default-features= false, optional = true } signature = "2.2.0" [dev-dependencies] tempfile.workspace = true [features] -#https://nnethercote.github.io/dh_view/dh_view.html -#https://valgrind.org/docs/manual/dh-manual.html -dhat-heap = ["dep:dhat"] console-subscriber = ["dep:console-subscriber"] tokio_taskdump = ["pumpkin-world/tokio_taskdump"] diff --git a/pumpkin/src/block/mod.rs b/pumpkin/src/block/mod.rs index b8427d967..2785ee2e5 100644 --- a/pumpkin/src/block/mod.rs +++ b/pumpkin/src/block/mod.rs @@ -52,7 +52,7 @@ pub trait BlockBehaviour: Send + Sync { } fn on_entity_collision<'a>(&'a self, _args: OnEntityCollisionArgs<'a>) -> BlockFuture<'a, ()> { - Box::pin(async move {}) + Box::pin(async {}) } fn should_drop_items_on_explosion(&self) -> bool { @@ -60,7 +60,7 @@ pub trait BlockBehaviour: Send + Sync { } fn explode<'a>(&'a self, _args: ExplodeArgs<'a>) -> BlockFuture<'a, ()> { - Box::pin(async move {}) + Box::pin(async {}) } /// Handles the block event, which is an event specific to a block with an integer ID and data. @@ -79,7 +79,7 @@ pub trait BlockBehaviour: Send + Sync { } fn random_tick<'a>(&'a self, _args: RandomTickArgs<'a>) -> BlockFuture<'a, ()> { - Box::pin(async move {}) + Box::pin(async {}) } fn can_place_at<'a>(&'a self, _args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> { @@ -92,24 +92,24 @@ pub trait BlockBehaviour: Send + Sync { /// onBlockAdded in source code fn placed<'a>(&'a self, _args: PlacedArgs<'a>) -> BlockFuture<'a, ()> { - Box::pin(async move {}) + Box::pin(async {}) } fn player_placed<'a>(&'a self, _args: PlayerPlacedArgs<'a>) -> BlockFuture<'a, ()> { - Box::pin(async move {}) + Box::pin(async {}) } fn broken<'a>(&'a self, _args: BrokenArgs<'a>) -> BlockFuture<'a, ()> { - Box::pin(async move {}) + Box::pin(async {}) } fn on_neighbor_update<'a>(&'a self, _args: OnNeighborUpdateArgs<'a>) -> BlockFuture<'a, ()> { - Box::pin(async move {}) + Box::pin(async {}) } /// Called if a block state is replaced or it replaces another state fn prepare<'a>(&'a self, _args: PrepareArgs<'a>) -> BlockFuture<'a, ()> { - Box::pin(async move {}) + Box::pin(async {}) } fn get_state_for_neighbor_update<'a>( @@ -120,11 +120,11 @@ pub trait BlockBehaviour: Send + Sync { } fn on_scheduled_tick<'a>(&'a self, _args: OnScheduledTickArgs<'a>) -> BlockFuture<'a, ()> { - Box::pin(async move {}) + Box::pin(async {}) } fn on_state_replaced<'a>(&'a self, _args: OnStateReplacedArgs<'a>) -> BlockFuture<'a, ()> { - Box::pin(async move {}) + Box::pin(async {}) } // --- Redstone/Comparator Methods --- diff --git a/pumpkin/src/command/commands/mod.rs b/pumpkin/src/command/commands/mod.rs index 485cdf97e..4efa52329 100644 --- a/pumpkin/src/command/commands/mod.rs +++ b/pumpkin/src/command/commands/mod.rs @@ -56,9 +56,6 @@ mod weather; mod whitelist; mod worldborder; -#[cfg(feature = "dhat-heap")] -mod profile; - #[must_use] pub async fn default_dispatcher(basic_config: &BasicConfiguration) -> CommandDispatcher { let mut dispatcher = CommandDispatcher::default(); @@ -144,9 +141,6 @@ pub async fn default_dispatcher(basic_config: &BasicConfiguration) -> CommandDis // Four dispatcher.register(stop::init_command_tree(), "minecraft:command.stop"); - #[cfg(feature = "dhat-heap")] - dispatcher.register(profile::init_command_tree(), "pumpkin:command.profile"); - dispatcher } @@ -510,13 +504,4 @@ fn register_level_4_permissions(registry: &mut PermissionRegistry) { PermissionDefault::Op(PermissionLvl::Four), )) .unwrap(); - - #[cfg(feature = "dhat-heap")] - registry - .register_permission(Permission::new( - "pumpkin:command.profile", - "Controls heap profiling", - PermissionDefault::Op(PermissionLvl::Four), - )) - .unwrap(); } diff --git a/pumpkin/src/command/commands/profile.rs b/pumpkin/src/command/commands/profile.rs deleted file mode 100644 index e76726f4c..000000000 --- a/pumpkin/src/command/commands/profile.rs +++ /dev/null @@ -1,45 +0,0 @@ -use pumpkin_util::text::TextComponent; -use pumpkin_util::text::color::NamedColor; - -use crate::command::CommandResult; - -use crate::command::args::ConsumedArgs; -use crate::command::tree::CommandTree; -use crate::command::{CommandExecutor, CommandSender}; -use crate::{HEAP_PROFILER, stop_server}; - -const NAMES: [&str; 1] = ["mem_profile"]; - -const DESCRIPTION: &str = "Stop the server and dump a memory profile."; - -struct Executor; - -impl CommandExecutor for Executor { - fn execute<'a>( - &'a self, - sender: &'a CommandSender, - _server: &'a crate::server::Server, - _args: &'a ConsumedArgs<'a>, - ) -> CommandResult<'a> { - Box::pin(async move { - sender - .send_message( - TextComponent::translate("commands.stop.stopping", []) - .color_named(NamedColor::Red), - ) - .await; - - let mut profiler = HEAP_PROFILER.lock().await; - let p = profiler.take().unwrap(); - drop(p); - - stop_server(); - - Ok(()) - }) - } -} - -pub fn init_command_tree() -> CommandTree { - CommandTree::new(NAMES, DESCRIPTION).execute(Executor) -} diff --git a/pumpkin/src/data/banlist_serializer.rs b/pumpkin/src/data/banlist_serializer.rs index b3c9ae60e..d041e061e 100644 --- a/pumpkin/src/data/banlist_serializer.rs +++ b/pumpkin/src/data/banlist_serializer.rs @@ -67,9 +67,8 @@ impl BannedIpEntry { } mod format { - use simplelog::FormatItem; - const DATE_FORMAT: &[FormatItem<'static>] = time::macros::format_description!( + const DATE_FORMAT: &[time::format_description::FormatItem<'static>] = time::macros::format_description!( "[year]-[month]-[day] [hour]:[minute]:[second][offset_hour sign:mandatory]:[offset_minute]" ); diff --git a/pumpkin/src/item/mod.rs b/pumpkin/src/item/mod.rs index 4222e4457..f5ff0f31b 100644 --- a/pumpkin/src/item/mod.rs +++ b/pumpkin/src/item/mod.rs @@ -25,7 +25,7 @@ pub trait ItemBehaviour: Send + Sync { _item: &'a Item, _player: &'a Player, ) -> Pin + Send + 'a>> { - Box::pin(async move {}) + Box::pin(async {}) } fn use_on_block<'a>( @@ -37,7 +37,7 @@ pub trait ItemBehaviour: Send + Sync { _block: &'a Block, _server: &'a Server, ) -> Pin + Send + 'a>> { - Box::pin(async move {}) + Box::pin(async {}) } fn use_on_entity<'a>( @@ -46,7 +46,7 @@ pub trait ItemBehaviour: Send + Sync { _player: &'a Player, _entity: Arc, ) -> Pin + Send + 'a>> { - Box::pin(async move {}) + Box::pin(async {}) } fn can_mine(&self, _player: &Player) -> bool { diff --git a/pumpkin/src/lib.rs b/pumpkin/src/lib.rs index 30ac99d4c..a0f2ded2e 100644 --- a/pumpkin/src/lib.rs +++ b/pumpkin/src/lib.rs @@ -42,10 +42,6 @@ pub mod plugin; pub mod server; pub mod world; -#[cfg(feature = "dhat-heap")] -pub static HEAP_PROFILER: LazyLock>> = - LazyLock::new(|| Mutex::new(None)); - pub static PLUGIN_MANAGER: LazyLock> = LazyLock::new(|| Arc::new(PluginManager::new())); diff --git a/pumpkin/src/main.rs b/pumpkin/src/main.rs index 002c115fc..9aa0991fe 100644 --- a/pumpkin/src/main.rs +++ b/pumpkin/src/main.rs @@ -53,7 +53,7 @@ use tokio::signal::ctrl_c; use tokio::signal::unix::{SignalKind, signal}; use tokio::sync::RwLock; -use pumpkin::{LOGGER_IMPL, PumpkinServer, SHOULD_STOP, STOP_INTERRUPT, init_log, stop_server}; +use pumpkin::{PumpkinServer, SHOULD_STOP, STOP_INTERRUPT, init_log, stop_server}; use pumpkin_config::{AdvancedConfiguration, BasicConfiguration, LoadConfiguration}; use pumpkin_util::{ @@ -74,13 +74,6 @@ pub mod plugin; pub mod server; pub mod world; -#[cfg(feature = "dhat-heap")] -#[global_allocator] -static ALLOC: dhat::Alloc = dhat::Alloc; - -#[cfg(feature = "dhat-heap")] -use pumpkin::HEAP_PROFILER; - pub static PLUGIN_MANAGER: LazyLock> = LazyLock::new(|| Arc::new(PluginManager::new())); @@ -102,13 +95,6 @@ const CARGO_PKG_VERSION: &str = env!("CARGO_PKG_VERSION"); async fn main() { #[cfg(feature = "console-subscriber")] console_subscriber::init(); - #[cfg(feature = "dhat-heap")] - { - let profiler = dhat::Profiler::new_heap(); - let mut static_loc = HEAP_PROFILER.lock().await; - *static_loc = Some(profiler); - }; - let time = Instant::now(); let exec_dir = std::env::current_dir().unwrap(); @@ -123,10 +109,6 @@ async fn main() { let default_panic = std::panic::take_hook(); std::panic::set_hook(Box::new(move |info| { - if let Some((wrapper, _)) = LOGGER_IMPL.wait() { - // Drop readline to reset terminal state - let _ = wrapper.take_readline(); - } default_panic(info); // TODO: Gracefully exit? // We need to abide by the panic rules here. diff --git a/pumpkin/src/net/mod.rs b/pumpkin/src/net/mod.rs index 0bcdada69..5af4c47d3 100644 --- a/pumpkin/src/net/mod.rs +++ b/pumpkin/src/net/mod.rs @@ -19,7 +19,6 @@ use pumpkin_util::{Hand, ProfileAction, text::TextComponent}; use serde::Deserialize; use sha1::Digest; use sha2::Sha256; -use simplelog::FormatItem; use tokio::task::JoinHandle; use thiserror::Error; @@ -180,7 +179,7 @@ pub async fn can_not_join( address: &SocketAddr, server: &Server, ) -> Option { - const FORMAT_DESCRIPTION: &[FormatItem<'_>] = time::macros::format_description!( + const FORMAT_DESCRIPTION: &[time::format_description::FormatItem<'static>] = time::macros::format_description!( "[year]-[month]-[day] at [hour]:[minute]:[second] [offset_hour sign:mandatory]:[offset_minute]" ); diff --git a/pumpkin/src/plugin/mod.rs b/pumpkin/src/plugin/mod.rs index 1e790e728..1fa6684d1 100644 --- a/pumpkin/src/plugin/mod.rs +++ b/pumpkin/src/plugin/mod.rs @@ -52,7 +52,7 @@ pub trait DynEventHandler: Send + Sync { /// /// # Returns /// The priority of the event handler. - fn get_priority(&self) -> EventPriority; + fn get_priority(&self) -> &EventPriority; } /// A trait for handling specific events. @@ -72,7 +72,7 @@ pub trait EventHandler: Send + Sync { /// # Arguments /// - `event`: A mutable reference to the event to handle. fn handle_blocking(&self, _server: &Arc, _event: &mut E) -> BoxFuture<'_, ()> { - Box::pin(async move {}) + Box::pin(async {}) } } @@ -129,8 +129,8 @@ where } /// Retrieves the priority of the handler. - fn get_priority(&self) -> EventPriority { - self.priority.clone() + fn get_priority(&self) -> &EventPriority { + &self.priority } } diff --git a/pumpkin/src/server/key_store.rs b/pumpkin/src/server/key_store.rs index 5fe67446e..78909b32e 100644 --- a/pumpkin/src/server/key_store.rs +++ b/pumpkin/src/server/key_store.rs @@ -1,6 +1,7 @@ use num_bigint::BigInt; +use pkcs8::EncodePublicKey; use pumpkin_protocol::java::client::login::CEncryptionRequest; -use rsa::{Pkcs1v15Encrypt, RsaPrivateKey, traits::PublicKeyParts as _}; +use rsa::{Pkcs1v15Encrypt, RsaPrivateKey}; use sha1::Sha1; use sha2::Digest; @@ -17,11 +18,15 @@ impl KeyStore { log::debug!("Creating encryption keys..."); let private_key = Self::generate_private_key(); - let public_key_der = rsa_der::public_key_to_der( - &private_key.n().to_be_bytes(), - &private_key.e().to_be_bytes(), - ) - .into_boxed_slice(); + let public_key = private_key.to_public_key(); + + let public_key_der = public_key + .to_public_key_der() + .expect("Failed to encode public key to SPKI DER") + .as_bytes() + .to_vec() + .into_boxed_slice(); + Self { private_key, public_key_der,