From 32bb060adc5eb8a9c41fc4c94f138f2d083ea8f9 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 9 Nov 2023 15:29:22 +0100 Subject: [PATCH 01/89] First look --- minecraft-entities/Cargo.toml | 1 + minecraft-entities/src/animals/cow.rs | 60 +++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/minecraft-entities/Cargo.toml b/minecraft-entities/Cargo.toml index 4d13a269..d3c140cc 100644 --- a/minecraft-entities/Cargo.toml +++ b/minecraft-entities/Cargo.toml @@ -9,3 +9,4 @@ edition = "2021" minecraft-protocol = { path = "../minecraft-protocol" } minecraft-positions = { path = "../minecraft-positions" } minecraft-entities-derive = { path="../minecraft-entities-derive" } +tokio = { version = "1.33.0", features = ["full"] } diff --git a/minecraft-entities/src/animals/cow.rs b/minecraft-entities/src/animals/cow.rs index c89b8f81..0a671c40 100644 --- a/minecraft-entities/src/animals/cow.rs +++ b/minecraft-entities/src/animals/cow.rs @@ -1,3 +1,5 @@ +use std::{pin::Pin, future::Future, sync::{Mutex, Arc}}; + use super::*; #[derive(Default)] @@ -14,3 +16,61 @@ pub struct Mooshroom { pub cow: Cow, pub variant: u8, // In the doc it is a string } + +// Function that returns a pinned boxed future +type CallBack = fn(O, I) -> Pin>>; + +pub struct AnimalMethods { + pub on_hit: CallBack, + pub on_dies: CallBack, +} + +trait AnimalExt: Sized + AnimalDescendant + Into { + fn methods() -> AnimalMethods; + + fn on_hit(self, damage: f32) -> Pin>> { + (Self::methods().on_hit)(self.into(), damage) + } + + fn on_dies(self) -> Pin>> { + (Self::methods().on_dies)(self.into(), ()) + } +} + +impl AnimalExt for Animal { + fn methods() -> AnimalMethods { + AnimalMethods { + on_hit: |animal, damage| Box::pin(async { + println!("Animal was hit"); + }), + on_dies: |animal, ()| Box::pin(async { + println!("Animal died"); + }), + } + } +} + +impl From for Animal { + fn from(val: Cow) -> Self { + val.animal + } +} + +impl AnimalExt for Cow { + fn methods() -> AnimalMethods { + AnimalMethods { + on_hit: |animal, damage| Box::pin(async { + println!("Cow was hit"); + }), + ..Animal::methods() + } + } +} + +#[tokio::test] +async fn test() { + let cow = Cow::default(); + cow.on_hit(1.0).await; + let cow = Cow::default(); + cow.on_dies().await; +} From dbb3c008ca387e0ca09d9862f78defbac085c481 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 9 Nov 2023 15:40:22 +0100 Subject: [PATCH 02/89] Add another layer --- minecraft-entities/src/animals/cow.rs | 56 ++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/minecraft-entities/src/animals/cow.rs b/minecraft-entities/src/animals/cow.rs index 0a671c40..309e69fe 100644 --- a/minecraft-entities/src/animals/cow.rs +++ b/minecraft-entities/src/animals/cow.rs @@ -20,6 +20,18 @@ pub struct Mooshroom { // Function that returns a pinned boxed future type CallBack = fn(O, I) -> Pin>>; +pub struct EntityMethods { + pub on_jump: CallBack, +} + +trait EntityExt: Sized + EntityDescendant + Into { + fn methods() -> EntityMethods; + + fn on_jump(self) -> Pin>> { + (Self::methods().on_jump)(self.into(), ()) + } +} + pub struct AnimalMethods { pub on_hit: CallBack, pub on_dies: CallBack, @@ -50,19 +62,59 @@ impl AnimalExt for Animal { } } +impl EntityExt for Entity { + fn methods() -> EntityMethods { + EntityMethods { + on_jump: |entity, ()| Box::pin(async { + println!("Entity jumped"); + }), + } + } +} + +impl From for Entity { + fn from(val: Animal) -> Self { + val.ageable_mob.pathfinder_mob.mob.living_entity.entity + } +} + +impl EntityExt for Animal { + fn methods() -> EntityMethods { + EntityMethods { + on_jump: |entity, ()| Box::pin(async { + println!("Animal jumped"); + }), + } + } +} + impl From for Animal { fn from(val: Cow) -> Self { val.animal } } +impl From for Entity { + fn from(val: Cow) -> Self { + val.animal.ageable_mob.pathfinder_mob.mob.living_entity.entity + } +} + impl AnimalExt for Cow { fn methods() -> AnimalMethods { AnimalMethods { on_hit: |animal, damage| Box::pin(async { println!("Cow was hit"); }), - ..Animal::methods() + ..::methods() + } + } +} + +impl EntityExt for Cow { + fn methods() -> EntityMethods { + EntityMethods { + ..::methods() } } } @@ -73,4 +125,6 @@ async fn test() { cow.on_hit(1.0).await; let cow = Cow::default(); cow.on_dies().await; + let cow = Cow::default(); + cow.on_jump().await; } From 9754d3d7cdf1fc9885f374c6702cc4eed4e762fa Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 9 Nov 2023 15:42:19 +0100 Subject: [PATCH 03/89] Reorder --- minecraft-entities/src/animals/cow.rs | 50 +++++++++++++++------------ 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/minecraft-entities/src/animals/cow.rs b/minecraft-entities/src/animals/cow.rs index 309e69fe..079512c2 100644 --- a/minecraft-entities/src/animals/cow.rs +++ b/minecraft-entities/src/animals/cow.rs @@ -20,6 +20,8 @@ pub struct Mooshroom { // Function that returns a pinned boxed future type CallBack = fn(O, I) -> Pin>>; +// Entity: + pub struct EntityMethods { pub on_jump: CallBack, } @@ -32,6 +34,18 @@ trait EntityExt: Sized + EntityDescendant + Into { } } +impl EntityExt for Entity { + fn methods() -> EntityMethods { + EntityMethods { + on_jump: |entity, ()| Box::pin(async { + println!("Entity jumped"); + }), + } + } +} + +// Animal: + pub struct AnimalMethods { pub on_hit: CallBack, pub on_dies: CallBack, @@ -62,16 +76,6 @@ impl AnimalExt for Animal { } } -impl EntityExt for Entity { - fn methods() -> EntityMethods { - EntityMethods { - on_jump: |entity, ()| Box::pin(async { - println!("Entity jumped"); - }), - } - } -} - impl From for Entity { fn from(val: Animal) -> Self { val.ageable_mob.pathfinder_mob.mob.living_entity.entity @@ -88,15 +92,25 @@ impl EntityExt for Animal { } } -impl From for Animal { +// Cow: + +impl From for Entity { fn from(val: Cow) -> Self { - val.animal + val.animal.ageable_mob.pathfinder_mob.mob.living_entity.entity } } -impl From for Entity { +impl EntityExt for Cow { + fn methods() -> EntityMethods { + EntityMethods { + ..::methods() + } + } +} + +impl From for Animal { fn from(val: Cow) -> Self { - val.animal.ageable_mob.pathfinder_mob.mob.living_entity.entity + val.animal } } @@ -111,14 +125,6 @@ impl AnimalExt for Cow { } } -impl EntityExt for Cow { - fn methods() -> EntityMethods { - EntityMethods { - ..::methods() - } - } -} - #[tokio::test] async fn test() { let cow = Cow::default(); From 8743ad3c9d12752ae97386aeb21650ddfb69ad28 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 9 Nov 2023 15:53:11 +0100 Subject: [PATCH 04/89] Switch to handler --- minecraft-entities/src/animals/cow.rs | 72 ++++++++++++++++++--------- 1 file changed, 48 insertions(+), 24 deletions(-) diff --git a/minecraft-entities/src/animals/cow.rs b/minecraft-entities/src/animals/cow.rs index 079512c2..9decf8d0 100644 --- a/minecraft-entities/src/animals/cow.rs +++ b/minecraft-entities/src/animals/cow.rs @@ -20,13 +20,37 @@ pub struct Mooshroom { // Function that returns a pinned boxed future type CallBack = fn(O, I) -> Pin>>; +pub struct Handler { + uuid: UUID, + world: Arc>, + entity: std::marker::PhantomData, +} + +impl Handler { + fn assume(uuid: UUID, world: Arc>) -> Self { + Self { + uuid, + world, + entity: std::marker::PhantomData, + } + } + + fn assume_other(self) -> Handler { + Handler { + uuid: self.uuid, + world: self.world, + entity: std::marker::PhantomData, + } + } +} + // Entity: pub struct EntityMethods { - pub on_jump: CallBack, + pub on_jump: CallBack, ()>, } -trait EntityExt: Sized + EntityDescendant + Into { +trait EntityExt: Sized + Into> { fn methods() -> EntityMethods; fn on_jump(self) -> Pin>> { @@ -34,7 +58,7 @@ trait EntityExt: Sized + EntityDescendant + Into { } } -impl EntityExt for Entity { +impl EntityExt for Handler { fn methods() -> EntityMethods { EntityMethods { on_jump: |entity, ()| Box::pin(async { @@ -47,11 +71,11 @@ impl EntityExt for Entity { // Animal: pub struct AnimalMethods { - pub on_hit: CallBack, - pub on_dies: CallBack, + pub on_hit: CallBack, f32>, + pub on_dies: CallBack, ()>, } -trait AnimalExt: Sized + AnimalDescendant + Into { +trait AnimalExt: Sized + Into> { fn methods() -> AnimalMethods; fn on_hit(self, damage: f32) -> Pin>> { @@ -63,7 +87,7 @@ trait AnimalExt: Sized + AnimalDescendant + Into { } } -impl AnimalExt for Animal { +impl AnimalExt for Handler { fn methods() -> AnimalMethods { AnimalMethods { on_hit: |animal, damage| Box::pin(async { @@ -76,13 +100,13 @@ impl AnimalExt for Animal { } } -impl From for Entity { - fn from(val: Animal) -> Self { - val.ageable_mob.pathfinder_mob.mob.living_entity.entity +impl From> for Handler { + fn from(val: Handler) -> Self { + val.assume_other() } } -impl EntityExt for Animal { +impl EntityExt for Handler { fn methods() -> EntityMethods { EntityMethods { on_jump: |entity, ()| Box::pin(async { @@ -94,43 +118,43 @@ impl EntityExt for Animal { // Cow: -impl From for Entity { - fn from(val: Cow) -> Self { - val.animal.ageable_mob.pathfinder_mob.mob.living_entity.entity +impl From> for Handler { + fn from(val: Handler) -> Self { + val.assume_other() } } -impl EntityExt for Cow { +impl EntityExt for Handler { fn methods() -> EntityMethods { EntityMethods { - ..::methods() + ..>::methods() } } } -impl From for Animal { - fn from(val: Cow) -> Self { - val.animal +impl From> for Handler { + fn from(val: Handler) -> Self { + val.assume_other() } } -impl AnimalExt for Cow { +impl AnimalExt for Handler { fn methods() -> AnimalMethods { AnimalMethods { on_hit: |animal, damage| Box::pin(async { println!("Cow was hit"); }), - ..::methods() + .. as AnimalExt>::methods() } } } #[tokio::test] async fn test() { - let cow = Cow::default(); + let cow = Handler::::assume(0, Arc::new(Mutex::new(()))); cow.on_hit(1.0).await; - let cow = Cow::default(); + let cow = Handler::::assume(0, Arc::new(Mutex::new(()))); cow.on_dies().await; - let cow = Cow::default(); + let cow = Handler::::assume(0, Arc::new(Mutex::new(()))); cow.on_jump().await; } From 85bde6d8c6c89770c70a073113b5e8021c977bec Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 9 Nov 2023 16:04:40 +0100 Subject: [PATCH 05/89] Move implementations --- minecraft-entities/src/animals/cow.rs | 32 +++++++++++++++++---------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/minecraft-entities/src/animals/cow.rs b/minecraft-entities/src/animals/cow.rs index 9decf8d0..2fd13aaf 100644 --- a/minecraft-entities/src/animals/cow.rs +++ b/minecraft-entities/src/animals/cow.rs @@ -87,15 +87,21 @@ trait AnimalExt: Sized + Into> { } } +impl Handler { + async fn on_hit(self, damage: f32) { + println!("Animal was hit"); + } + + async fn on_dies(self) { + println!("Animal died"); + } +} + impl AnimalExt for Handler { fn methods() -> AnimalMethods { AnimalMethods { - on_hit: |animal, damage| Box::pin(async { - println!("Animal was hit"); - }), - on_dies: |animal, ()| Box::pin(async { - println!("Animal died"); - }), + on_hit: |animal, damage| Box::pin(animal.on_hit(damage)), + on_dies: |animal, ()| Box::pin(animal.on_dies()), } } } @@ -109,9 +115,7 @@ impl From> for Handler { impl EntityExt for Handler { fn methods() -> EntityMethods { EntityMethods { - on_jump: |entity, ()| Box::pin(async { - println!("Animal jumped"); - }), + on_jump: |entity, ()| Box::pin(entity.assume_other::().on_jump()), } } } @@ -138,12 +142,16 @@ impl From> for Handler { } } +impl Handler { + async fn on_hit(self, damage: f32) { + println!("Cow was hit"); + } +} + impl AnimalExt for Handler { fn methods() -> AnimalMethods { AnimalMethods { - on_hit: |animal, damage| Box::pin(async { - println!("Cow was hit"); - }), + on_hit: |animal, damage| Box::pin(animal.assume_other::().on_hit(damage)), .. as AnimalExt>::methods() } } From 3158a80d6ae722085ab460f6d6d2084b91c05a2c Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 9 Nov 2023 16:21:53 +0100 Subject: [PATCH 06/89] Make goal clearer --- minecraft-entities/src/animals/cow.rs | 90 +++++++++++++++++++-------- 1 file changed, 63 insertions(+), 27 deletions(-) diff --git a/minecraft-entities/src/animals/cow.rs b/minecraft-entities/src/animals/cow.rs index 2fd13aaf..30860352 100644 --- a/minecraft-entities/src/animals/cow.rs +++ b/minecraft-entities/src/animals/cow.rs @@ -17,8 +17,25 @@ pub struct Mooshroom { pub variant: u8, // In the doc it is a string } +impl Handler { + async fn on_hit(self, damage: f32) { + println!("Animal was hit"); + } + + async fn on_dies(self) { + println!("Animal died"); + } +} + +impl Handler { + async fn on_hit(self, damage: f32) { + println!("Cow was hit"); + } +} + // Function that returns a pinned boxed future -type CallBack = fn(O, I) -> Pin>>; +type CallBack = fn(O) -> Pin>>; +type CallBack1 = fn(O, I) -> Pin>>; pub struct Handler { uuid: UUID, @@ -47,32 +64,52 @@ impl Handler { // Entity: pub struct EntityMethods { - pub on_jump: CallBack, ()>, + pub on_jump: CallBack>, } trait EntityExt: Sized + Into> { fn methods() -> EntityMethods; fn on_jump(self) -> Pin>> { - (Self::methods().on_jump)(self.into(), ()) + (Self::methods().on_jump)(self.into()) } } impl EntityExt for Handler { fn methods() -> EntityMethods { EntityMethods { - on_jump: |entity, ()| Box::pin(async { + on_jump: |entity| Box::pin(async { println!("Entity jumped"); }), } } } -// Animal: +/// Animal: +/// +/// ``` +/// #[inheritable( +/// on_hit(self, damage: f32); +/// on_dies(self); +/// )] +/// struct Animal { +/// pub entity: Entity, +/// } +/// +/// impl Handler { +/// async fn on_hit(self, damage: f32) { +/// println!("Animal was hit"); +/// } +/// +/// async fn on_dies(self) { +/// println!("Animal died"); +/// } +/// } +/// ``` pub struct AnimalMethods { - pub on_hit: CallBack, f32>, - pub on_dies: CallBack, ()>, + pub on_hit: CallBack1, f32>, + pub on_dies: CallBack>, } trait AnimalExt: Sized + Into> { @@ -83,17 +120,7 @@ trait AnimalExt: Sized + Into> { } fn on_dies(self) -> Pin>> { - (Self::methods().on_dies)(self.into(), ()) - } -} - -impl Handler { - async fn on_hit(self, damage: f32) { - println!("Animal was hit"); - } - - async fn on_dies(self) { - println!("Animal died"); + (Self::methods().on_dies)(self.into()) } } @@ -101,7 +128,7 @@ impl AnimalExt for Handler { fn methods() -> AnimalMethods { AnimalMethods { on_hit: |animal, damage| Box::pin(animal.on_hit(damage)), - on_dies: |animal, ()| Box::pin(animal.on_dies()), + on_dies: |animal| Box::pin(animal.on_dies()), } } } @@ -115,12 +142,27 @@ impl From> for Handler { impl EntityExt for Handler { fn methods() -> EntityMethods { EntityMethods { - on_jump: |entity, ()| Box::pin(entity.assume_other::().on_jump()), + ..>::methods() } } } -// Cow: +/// Cow: +/// +/// ```rust +/// #[override( +/// animal.on_hit(self, damage: f32); +/// )] +/// struct Cow { +/// pub animal: Animal, +/// } +/// +/// impl Handler { +/// async fn on_hit(self, damage: f32) { +/// println!("Cow was hit"); +/// } +/// } +/// ``` impl From> for Handler { fn from(val: Handler) -> Self { @@ -142,12 +184,6 @@ impl From> for Handler { } } -impl Handler { - async fn on_hit(self, damage: f32) { - println!("Cow was hit"); - } -} - impl AnimalExt for Handler { fn methods() -> AnimalMethods { AnimalMethods { From 0f1d5f0ca19ddddfbdb2f3ddfbb7f4acf8090266 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 9 Nov 2023 17:25:32 +0100 Subject: [PATCH 07/89] Start new macro --- Cargo.toml | 1 + minecraft-entities-derive/Cargo.toml | 1 + minecraft-entities-derive/examples/main.rs | 44 +++++++++++++++++++++ minecraft-entities-derive/src/lib.rs | 45 ++++++++++++++++++++++ minecraft-entities/src/animals/cow.rs | 11 ++++-- 5 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 minecraft-entities-derive/examples/main.rs diff --git a/Cargo.toml b/Cargo.toml index b6ee776b..b92aa048 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "minecraft-protocol-derive", "minecraft-server", "minecraft-entities", + "minecraft-entities-derive", "minecraft-positions", "tags-macros" ] diff --git a/minecraft-entities-derive/Cargo.toml b/minecraft-entities-derive/Cargo.toml index a65a0c22..7b504bbe 100644 --- a/minecraft-entities-derive/Cargo.toml +++ b/minecraft-entities-derive/Cargo.toml @@ -8,3 +8,4 @@ proc-macro = true [dependencies] convert_case = "0.6" +proc-macro-error = "1.0.4" diff --git a/minecraft-entities-derive/examples/main.rs b/minecraft-entities-derive/examples/main.rs new file mode 100644 index 00000000..4f4e9e25 --- /dev/null +++ b/minecraft-entities-derive/examples/main.rs @@ -0,0 +1,44 @@ +use minecraft_entities_derive::*; + +#[MinecraftEntity( + parents { }, + inheritable, + defines { + on_moved(self, from: Position, to: Position); + on_spawned(self); + } +)] +struct Entity { + +} + +#[MinecraftEntity( + parents { Entity }, + inheritable, + defines { + Entity.on_spawned(self); + on_hit(self, damage: usize); + on_jump(self); + } +)] +struct Animal { + entity: Entity, +} + +#[MinecraftEntity( + parents { Animal, Entity }, + defines { + Entity.on_spawned(self); + Animal.on_hit(self); + on_milked(self); + } +)] +struct Cow { + animal: Animal, +} + + + +fn main() { + +} diff --git a/minecraft-entities-derive/src/lib.rs b/minecraft-entities-derive/src/lib.rs index 2996c77b..a4af2384 100644 --- a/minecraft-entities-derive/src/lib.rs +++ b/minecraft-entities-derive/src/lib.rs @@ -2,6 +2,7 @@ use std::collections::HashMap; use proc_macro::{TokenStream, TokenTree, Ident, Group}; use convert_case::{Case, Casing}; +use proc_macro_error::*; fn replace_idents(token: &mut TokenTree, to_replace: &HashMap<&'static str, Ident>) { match token { @@ -186,3 +187,47 @@ pub fn inheritable(_attr: TokenStream, item: TokenStream) -> TokenStream { final_code.extend(code); final_code } + +#[allow(non_snake_case)] +#[proc_macro_attribute] +#[proc_macro_error] +pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { + println!("{:?}", attr); + + let mut parents = Vec::new(); + let mut inheritable = false; + //let mut defines = Vec::new(); + + let mut attrs = attr.into_iter().peekable(); + while let Some(ident) = attrs.next() { + let TokenTree::Ident(ident) = ident else { abort!(ident.span(), "expected ident") }; + match ident.to_string().as_str() { + "parents" => { + let Some(token_tree) = attrs.next() else { abort!(ident.span(), "expected group after") }; + let TokenTree::Group(group) = token_tree else { abort!(token_tree.span(), "expected group") }; + let mut group_attrs = group.stream().into_iter().peekable(); + while let Some(ident) = group_attrs.next() { + let TokenTree::Ident(ident) = ident else { abort!(ident.span(), "expected ident") }; + parents.push(ident); + if matches!(group_attrs.peek(), Some(TokenTree::Punct(punct)) if punct.as_char() == ',') { + group_attrs.next(); + } + } + } + "inheritable" => inheritable = true, + "defines" => { + let Some(token_tree) = attrs.next() else { abort!(ident.span(), "expected group after") }; + let TokenTree::Group(group) = token_tree else { abort!(token_tree.span(), "expected group") }; + + } + other => abort!(ident.span(), "unrecognized identifier {}", other), + } + if matches!(attrs.peek(), Some(TokenTree::Punct(punct)) if punct.as_char() == ',') { + attrs.next(); + } + } + + println!("{inheritable} {parents:?}"); + + item +} diff --git a/minecraft-entities/src/animals/cow.rs b/minecraft-entities/src/animals/cow.rs index 30860352..e58e2c73 100644 --- a/minecraft-entities/src/animals/cow.rs +++ b/minecraft-entities/src/animals/cow.rs @@ -88,10 +88,13 @@ impl EntityExt for Handler { /// Animal: /// /// ``` -/// #[inheritable( -/// on_hit(self, damage: f32); -/// on_dies(self); -/// )] +/// #[ +/// inheritable, +/// methods( +/// on_hit(self, damage: f32); +/// on_dies(self); +/// ) +/// ] /// struct Animal { /// pub entity: Entity, /// } From 4a8971c59281bdf0bb15ab7f2ac212ed767e8acb Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 9 Nov 2023 17:33:53 +0100 Subject: [PATCH 08/89] Read defines --- minecraft-entities-derive/src/lib.rs | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/minecraft-entities-derive/src/lib.rs b/minecraft-entities-derive/src/lib.rs index a4af2384..7f3eac63 100644 --- a/minecraft-entities-derive/src/lib.rs +++ b/minecraft-entities-derive/src/lib.rs @@ -196,14 +196,14 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { let mut parents = Vec::new(); let mut inheritable = false; - //let mut defines = Vec::new(); + let mut defines = Vec::new(); let mut attrs = attr.into_iter().peekable(); while let Some(ident) = attrs.next() { let TokenTree::Ident(ident) = ident else { abort!(ident.span(), "expected ident") }; match ident.to_string().as_str() { "parents" => { - let Some(token_tree) = attrs.next() else { abort!(ident.span(), "expected group after") }; + let Some(token_tree) = attrs.next() else { abort!(ident.span(), "expected group after parents") }; let TokenTree::Group(group) = token_tree else { abort!(token_tree.span(), "expected group") }; let mut group_attrs = group.stream().into_iter().peekable(); while let Some(ident) = group_attrs.next() { @@ -218,7 +218,22 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { "defines" => { let Some(token_tree) = attrs.next() else { abort!(ident.span(), "expected group after") }; let TokenTree::Group(group) = token_tree else { abort!(token_tree.span(), "expected group") }; - + let mut group_attrs = group.stream().into_iter().peekable(); + while group_attrs.peek().is_some() { + let TokenTree::Ident(first_ident) = group_attrs.next().unwrap() else { abort!(ident.span(), "expected ident") }; + let mut second_ident = None; + if matches!(group_attrs.peek(), Some(TokenTree::Punct(punct)) if punct.as_char() == '.') { + let point = group_attrs.next().unwrap(); + let TokenTree::Ident(ident) = group_attrs.next().unwrap() else { abort!(point.span(), "expected method name") }; + second_ident = Some(ident); + } + let Some(group) = group_attrs.next() else { abort!(first_ident.span(), "expected group after method name") }; + let TokenTree::Group(params) = group else { abort!(group.span(), "expected group") }; + defines.push((first_ident, second_ident, params)); + if matches!(group_attrs.peek(), Some(TokenTree::Punct(punct)) if punct.as_char() == ';') { + group_attrs.next(); + } + } } other => abort!(ident.span(), "unrecognized identifier {}", other), } @@ -227,7 +242,7 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { } } - println!("{inheritable} {parents:?}"); + println!("{inheritable} {parents:?} {defines:?}"); item } From cbfd098675f3a88abb305b9f2aa0ff1b653f2b44 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 9 Nov 2023 17:50:48 +0100 Subject: [PATCH 09/89] Reimplement old features --- minecraft-entities-derive/examples/main.rs | 6 +- minecraft-entities-derive/src/lib.rs | 116 +++++++++++++++++++-- 2 files changed, 113 insertions(+), 9 deletions(-) diff --git a/minecraft-entities-derive/examples/main.rs b/minecraft-entities-derive/examples/main.rs index 4f4e9e25..154e2221 100644 --- a/minecraft-entities-derive/examples/main.rs +++ b/minecraft-entities-derive/examples/main.rs @@ -8,7 +8,7 @@ use minecraft_entities_derive::*; on_spawned(self); } )] -struct Entity { +pub struct Entity { } @@ -21,7 +21,7 @@ struct Entity { on_jump(self); } )] -struct Animal { +pub struct Animal { entity: Entity, } @@ -33,7 +33,7 @@ struct Animal { on_milked(self); } )] -struct Cow { +pub struct Cow { animal: Animal, } diff --git a/minecraft-entities-derive/src/lib.rs b/minecraft-entities-derive/src/lib.rs index 7f3eac63..197de75f 100644 --- a/minecraft-entities-derive/src/lib.rs +++ b/minecraft-entities-derive/src/lib.rs @@ -192,12 +192,12 @@ pub fn inheritable(_attr: TokenStream, item: TokenStream) -> TokenStream { #[proc_macro_attribute] #[proc_macro_error] pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { - println!("{:?}", attr); - - let mut parents = Vec::new(); + let mut inherited = Vec::new(); let mut inheritable = false; let mut defines = Vec::new(); + let mut codes = Vec::new(); + // Parse attributes let mut attrs = attr.into_iter().peekable(); while let Some(ident) = attrs.next() { let TokenTree::Ident(ident) = ident else { abort!(ident.span(), "expected ident") }; @@ -208,7 +208,7 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { let mut group_attrs = group.stream().into_iter().peekable(); while let Some(ident) = group_attrs.next() { let TokenTree::Ident(ident) = ident else { abort!(ident.span(), "expected ident") }; - parents.push(ident); + inherited.push(ident); if matches!(group_attrs.peek(), Some(TokenTree::Punct(punct)) if punct.as_char() == ',') { group_attrs.next(); } @@ -241,8 +241,112 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { attrs.next(); } } + + // Get struct name + let mut items = item.clone().into_iter(); + match items.next() { + Some(TokenTree::Ident(ident)) if ident.to_string() == "pub" => (), + Some(TokenTree::Punct(punct)) if punct.as_char() == '#' => { + items.next(); + match items.next() { + Some(TokenTree::Ident(ident)) if ident.to_string() == "pub" => (), + Some(other) => abort!(other.span(), "expected struct to be public"), + None => panic!("expected public struct, found nothing"), + } + } + Some(other) => abort!(other.span(), "expected struct to be public"), + None => panic!("expected public struct, found nothing"), + } + match items.next() { + Some(TokenTree::Ident(ident)) if ident.to_string() == "struct" => (), + Some(other) => abort!(other.span(), "expected struct, found {:?}"), + None => panic!("expected struct, found nothing"), + } + let struct_name = match items.next() { + Some(TokenTree::Ident(ident)) => ident, + Some(other) => abort!(other.span(), "expected struct name, found {:?}"), + None => panic!("expected struct name, found nothing"), + }; - println!("{inheritable} {parents:?} {defines:?}"); + if !inherited.is_empty() { + // Generate code for parent + let parent = inherited.remove(0); + let code: TokenStream = r#" + impl ParentDescendant for This { + fn get_parent(&self) -> &Parent { &self.parent } + fn get_parent_mut(&mut self) -> &mut Parent { &mut self.parent } + } + "#.parse().unwrap(); + let mut to_replace = HashMap::new(); + to_replace.insert("ParentDescendant", Ident::new(&format!("{}Descendant", parent), parent.span())); + to_replace.insert("Parent", parent.clone()); + to_replace.insert("This", struct_name.clone()); + to_replace.insert("get_parent", Ident::new(&format!("get_{}", parent.to_string().to_case(Case::Snake)), parent.span())); + to_replace.insert("get_parent_mut", Ident::new(&format!("get_{}_mut", parent.to_string().to_case(Case::Snake)), parent.span())); + to_replace.insert("parent", Ident::new(&parent.to_string().to_case(Case::Snake), parent.span())); + let mut code = code.clone().into_iter().collect::>(); + for element in &mut code { + replace_idents(element, &to_replace); + } + let code: TokenStream = code.into_iter().collect(); + println!("{}", code); + codes.push(code); + + // Generate code for higher inheritance levels + let code: TokenStream = r#" + impl InheritedDescendant for This { + fn get_inherited(&self) -> &Inherited { self.parent.get_inherited() } + fn get_inherited_mut(&mut self) -> &mut Inherited { self.parent.get_inherited_mut() } + } + "#.parse().unwrap(); + for inherited in inherited { + let mut to_replace = HashMap::new(); + to_replace.insert("InheritedDescendant", Ident::new(&format!("{}Descendant", inherited), inherited.span())); + to_replace.insert("Inherited", inherited.clone()); + to_replace.insert("This", struct_name.clone()); + to_replace.insert("get_inherited", Ident::new(&format!("get_{}", inherited.to_string().to_case(Case::Snake)), inherited.span())); + to_replace.insert("get_inherited_mut", Ident::new(&format!("get_{}_mut", inherited.to_string().to_case(Case::Snake)), inherited.span())); + to_replace.insert("parent", Ident::new(&parent.to_string().to_case(Case::Snake), parent.span())); - item + let mut code = code.clone().into_iter().collect::>(); + for element in &mut code { + replace_idents(element, &to_replace); + } + let code: TokenStream = code.into_iter().collect(); + codes.push(code); + } + } + + if inheritable { + // Generate descendant trait + let code: TokenStream = r#" + pub trait ThisDescendant { + fn get_this(&self) -> &This; + fn get_this_mut(&mut self) -> &mut This; + } + + impl ThisDescendant for This { + fn get_this(&self) -> &This { self } + fn get_this_mut(&mut self) -> &mut This { self } + } + "#.parse().unwrap(); + let mut to_replace = HashMap::new(); + to_replace.insert("This", struct_name.clone()); + to_replace.insert("ThisDescendant", Ident::new(&format!("{}Descendant", struct_name), struct_name.span())); + to_replace.insert("get_this", Ident::new(&format!("get_{}", struct_name.to_string().to_case(Case::Snake)), struct_name.span())); + to_replace.insert("get_this_mut", Ident::new(&format!("get_{}_mut", struct_name.to_string().to_case(Case::Snake)), struct_name.span())); + let mut code = code.clone().into_iter().collect::>(); + for element in &mut code { + replace_idents(element, &to_replace); + } + let code: TokenStream = code.into_iter().collect(); + codes.push(code); + } + + // Generate final code + let mut final_code = item; + for code in codes { + final_code.extend(code); + } + final_code } From 11d911fff170d3dc54e75655e63739f8f04a0c14 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 9 Nov 2023 18:28:57 +0100 Subject: [PATCH 10/89] Create methods struct --- minecraft-entities-derive/examples/main.rs | 45 +++++++++++++++ minecraft-entities-derive/src/lib.rs | 67 +++++++++++++++++----- minecraft-entities/src/animals/cow.rs | 2 +- 3 files changed, 98 insertions(+), 16 deletions(-) diff --git a/minecraft-entities-derive/examples/main.rs b/minecraft-entities-derive/examples/main.rs index 154e2221..fa1acc85 100644 --- a/minecraft-entities-derive/examples/main.rs +++ b/minecraft-entities-derive/examples/main.rs @@ -1,5 +1,50 @@ use minecraft_entities_derive::*; +struct Test { + test: fn(u8, u8) -> usize, + test2: fn(u8, u8) -> usize, +} + +const BOO: &Test = &Test { + test: |a, b| a as usize + b as usize, + test2: |a, b| a as usize + b as usize, +}; + +const BOO2: &Test = { + let mut t1 = BOO; + t1 +}; + +use std::{pin::Pin, future::Future, sync::{Mutex, Arc}}; +type CallBack = fn(O) -> Pin>>; +type CallBack1 = fn(O, I) -> Pin>>; +type UUID = u128; + +pub struct Handler { + uuid: UUID, + world: Arc>, + entity: std::marker::PhantomData, +} + +impl Handler { + fn assume(uuid: UUID, world: Arc>) -> Self { + Self { + uuid, + world, + entity: std::marker::PhantomData, + } + } + + fn assume_other(self) -> Handler { + Handler { + uuid: self.uuid, + world: self.world, + entity: std::marker::PhantomData, + } + } +} + + #[MinecraftEntity( parents { }, inheritable, diff --git a/minecraft-entities-derive/src/lib.rs b/minecraft-entities-derive/src/lib.rs index 197de75f..40601c68 100644 --- a/minecraft-entities-derive/src/lib.rs +++ b/minecraft-entities-derive/src/lib.rs @@ -220,16 +220,29 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { let TokenTree::Group(group) = token_tree else { abort!(token_tree.span(), "expected group") }; let mut group_attrs = group.stream().into_iter().peekable(); while group_attrs.peek().is_some() { - let TokenTree::Ident(first_ident) = group_attrs.next().unwrap() else { abort!(ident.span(), "expected ident") }; - let mut second_ident = None; + let TokenTree::Ident(mut method) = group_attrs.next().unwrap() else { abort!(ident.span(), "expected ident") }; + let mut ty = None; if matches!(group_attrs.peek(), Some(TokenTree::Punct(punct)) if punct.as_char() == '.') { let point = group_attrs.next().unwrap(); let TokenTree::Ident(ident) = group_attrs.next().unwrap() else { abort!(point.span(), "expected method name") }; - second_ident = Some(ident); + ty = Some(method); + method = ident; } - let Some(group) = group_attrs.next() else { abort!(first_ident.span(), "expected group after method name") }; + let Some(group) = group_attrs.next() else { abort!(method.span(), "expected group after method name") }; let TokenTree::Group(params) = group else { abort!(group.span(), "expected group") }; - defines.push((first_ident, second_ident, params)); + if params.delimiter() != proc_macro::Delimiter::Parenthesis { + abort!(params.span(), "expected parenthesis"); + } + let mut params = params.stream().into_iter().peekable(); + if matches!(params.peek(), Some(TokenTree::Ident(ident)) if ident.to_string() == "self") { + params.next(); + if matches!(params.peek(), Some(TokenTree::Punct(punct)) if punct.as_char() == ',') { + params.next(); + } + } else { + abort!(params.peek().unwrap().span(), "expected self as first parameter"); + } + defines.push((ty, method, params.into_iter().collect::())); if matches!(group_attrs.peek(), Some(TokenTree::Punct(punct)) if punct.as_char() == ';') { group_attrs.next(); } @@ -268,6 +281,13 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { None => panic!("expected struct name, found nothing"), }; + let mut to_replace = HashMap::new(); + to_replace.insert("This", struct_name.clone()); + to_replace.insert("ThisDescendant", Ident::new(&format!("{}Descendant", struct_name), struct_name.span())); + to_replace.insert("ThisMethods", Ident::new(&format!("{}Methods", struct_name), struct_name.span())); + to_replace.insert("get_this", Ident::new(&format!("get_{}", struct_name.to_string().to_case(Case::Snake)), struct_name.span())); + to_replace.insert("get_this_mut", Ident::new(&format!("get_{}_mut", struct_name.to_string().to_case(Case::Snake)), struct_name.span())); + if !inherited.is_empty() { // Generate code for parent let parent = inherited.remove(0); @@ -277,10 +297,8 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { fn get_parent_mut(&mut self) -> &mut Parent { &mut self.parent } } "#.parse().unwrap(); - let mut to_replace = HashMap::new(); to_replace.insert("ParentDescendant", Ident::new(&format!("{}Descendant", parent), parent.span())); to_replace.insert("Parent", parent.clone()); - to_replace.insert("This", struct_name.clone()); to_replace.insert("get_parent", Ident::new(&format!("get_{}", parent.to_string().to_case(Case::Snake)), parent.span())); to_replace.insert("get_parent_mut", Ident::new(&format!("get_{}_mut", parent.to_string().to_case(Case::Snake)), parent.span())); to_replace.insert("parent", Ident::new(&parent.to_string().to_case(Case::Snake), parent.span())); @@ -300,13 +318,10 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { } "#.parse().unwrap(); for inherited in inherited { - let mut to_replace = HashMap::new(); to_replace.insert("InheritedDescendant", Ident::new(&format!("{}Descendant", inherited), inherited.span())); to_replace.insert("Inherited", inherited.clone()); - to_replace.insert("This", struct_name.clone()); to_replace.insert("get_inherited", Ident::new(&format!("get_{}", inherited.to_string().to_case(Case::Snake)), inherited.span())); to_replace.insert("get_inherited_mut", Ident::new(&format!("get_{}_mut", inherited.to_string().to_case(Case::Snake)), inherited.span())); - to_replace.insert("parent", Ident::new(&parent.to_string().to_case(Case::Snake), parent.span())); let mut code = code.clone().into_iter().collect::>(); for element in &mut code { @@ -330,11 +345,6 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { fn get_this_mut(&mut self) -> &mut This { self } } "#.parse().unwrap(); - let mut to_replace = HashMap::new(); - to_replace.insert("This", struct_name.clone()); - to_replace.insert("ThisDescendant", Ident::new(&format!("{}Descendant", struct_name), struct_name.span())); - to_replace.insert("get_this", Ident::new(&format!("get_{}", struct_name.to_string().to_case(Case::Snake)), struct_name.span())); - to_replace.insert("get_this_mut", Ident::new(&format!("get_{}_mut", struct_name.to_string().to_case(Case::Snake)), struct_name.span())); let mut code = code.clone().into_iter().collect::>(); for element in &mut code { replace_idents(element, &to_replace); @@ -343,6 +353,33 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { codes.push(code); } + // Generate methods struct + let code: TokenStream = r#" + pub struct ThisMethods { + + } + "#.parse().unwrap(); + let mut code = code.clone().into_iter().collect::>(); + for element in &mut code { + replace_idents(element, &to_replace); + } + let mut inner_codes = TokenStream::new(); + for (ty, method, args) in defines { + let inner_code: TokenStream = r#"pub method: CallBack1, f32>,"#.parse().unwrap(); + to_replace.insert("method", method); + // TODO to_replace.insert("args", args); + let mut inner_code = inner_code.clone().into_iter().collect::>(); + for element in &mut inner_code { + replace_idents(element, &to_replace); + } + let inner_code: TokenStream = inner_code.into_iter().collect(); + inner_codes.extend(inner_code); + } + let TokenTree::Group(ref mut group) = code.last_mut().unwrap() else {unreachable!()}; + *group = Group::new(group.delimiter(), group.stream().into_iter().chain(inner_codes.into_iter()).collect()); + let code: TokenStream = code.into_iter().collect(); + codes.push(code); + // Generate final code let mut final_code = item; for code in codes { diff --git a/minecraft-entities/src/animals/cow.rs b/minecraft-entities/src/animals/cow.rs index e58e2c73..5cfe973b 100644 --- a/minecraft-entities/src/animals/cow.rs +++ b/minecraft-entities/src/animals/cow.rs @@ -176,7 +176,7 @@ impl From> for Handler { impl EntityExt for Handler { fn methods() -> EntityMethods { EntityMethods { - ..>::methods() + .. as EntityExt>::methods() } } } From 8300deb1cfda5fe65653ee7adc681764cb127049 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 9 Nov 2023 18:44:31 +0100 Subject: [PATCH 11/89] Finish methods struct --- minecraft-entities-derive/examples/main.rs | 3 ++- minecraft-entities-derive/src/lib.rs | 24 ++++++++++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/minecraft-entities-derive/examples/main.rs b/minecraft-entities-derive/examples/main.rs index fa1acc85..fe0ee220 100644 --- a/minecraft-entities-derive/examples/main.rs +++ b/minecraft-entities-derive/examples/main.rs @@ -18,6 +18,7 @@ const BOO2: &Test = { use std::{pin::Pin, future::Future, sync::{Mutex, Arc}}; type CallBack = fn(O) -> Pin>>; type CallBack1 = fn(O, I) -> Pin>>; +type CallBack2 = fn(O, I, J) -> Pin>>; type UUID = u128; pub struct Handler { @@ -49,7 +50,7 @@ impl Handler { parents { }, inheritable, defines { - on_moved(self, from: Position, to: Position); + on_moved(self, from: f32, to: f32); on_spawned(self); } )] diff --git a/minecraft-entities-derive/src/lib.rs b/minecraft-entities-derive/src/lib.rs index 40601c68..268b2460 100644 --- a/minecraft-entities-derive/src/lib.rs +++ b/minecraft-entities-derive/src/lib.rs @@ -242,7 +242,20 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { } else { abort!(params.peek().unwrap().span(), "expected self as first parameter"); } - defines.push((ty, method, params.into_iter().collect::())); + let mut args: Vec<(Ident, TokenStream)> = Vec::new(); + while params.peek().is_some() { + let TokenTree::Ident(name) = params.next().unwrap() else { abort!(params.peek().unwrap().span(), "expected ident") }; + if !matches!(params.next(), Some(TokenTree::Punct(punct)) if punct.as_char() == ':') { + abort!(name.span(), "expected colon after name"); + } + let mut ty = TokenStream::new(); + while params.peek().is_some() && !matches!(params.peek(), Some(TokenTree::Punct(punct)) if punct.as_char() == ',') { + ty.extend(params.next()); + } + params.next(); + args.push((name, ty)); + } + defines.push((ty, method, args)); if matches!(group_attrs.peek(), Some(TokenTree::Punct(punct)) if punct.as_char() == ';') { group_attrs.next(); } @@ -365,7 +378,14 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { } let mut inner_codes = TokenStream::new(); for (ty, method, args) in defines { - let inner_code: TokenStream = r#"pub method: CallBack1, f32>,"#.parse().unwrap(); + let inner_code: TokenStream = match args.len() { + 0 => String::from(r#"pub method: CallBack>,"#), + 1 => format!(r#"pub method: CallBack1, {}>,"#, args[0].1), + 2 => format!(r#"pub method: CallBack2, {}, {}>,"#, args[0].1, args[1].1), + 3 => format!(r#"pub method: CallBack3, {}, {}, {}>,"#, args[0].1, args[1].1, args[2].1), + 4 => format!(r#"pub method: CallBack4, {}, {}, {}, {}>,"#, args[0].1, args[1].1, args[2].1, args[3].1), + _ => abort!(method.span(), "too many arguments"), + }.parse().unwrap(); to_replace.insert("method", method); // TODO to_replace.insert("args", args); let mut inner_code = inner_code.clone().into_iter().collect::>(); From 42f639e6d899ff4dcabbc6f63ebdc9a78a3d1a77 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 9 Nov 2023 18:46:01 +0100 Subject: [PATCH 12/89] Fix warning --- minecraft-entities-derive/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/minecraft-entities-derive/src/lib.rs b/minecraft-entities-derive/src/lib.rs index 268b2460..cef9c147 100644 --- a/minecraft-entities-derive/src/lib.rs +++ b/minecraft-entities-derive/src/lib.rs @@ -377,7 +377,7 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { replace_idents(element, &to_replace); } let mut inner_codes = TokenStream::new(); - for (ty, method, args) in defines { + for (_, method, args) in defines.iter().filter(|(ty, _, _)| ty.is_none()) { let inner_code: TokenStream = match args.len() { 0 => String::from(r#"pub method: CallBack>,"#), 1 => format!(r#"pub method: CallBack1, {}>,"#, args[0].1), @@ -386,7 +386,7 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { 4 => format!(r#"pub method: CallBack4, {}, {}, {}, {}>,"#, args[0].1, args[1].1, args[2].1, args[3].1), _ => abort!(method.span(), "too many arguments"), }.parse().unwrap(); - to_replace.insert("method", method); + to_replace.insert("method", method.clone()); // TODO to_replace.insert("args", args); let mut inner_code = inner_code.clone().into_iter().collect::>(); for element in &mut inner_code { From 46ec1595e3daa5356640faedfcdf7466f778258f Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 9 Nov 2023 19:12:55 +0100 Subject: [PATCH 13/89] Start implementing defaults --- minecraft-entities-derive/src/lib.rs | 116 ++++++++++++++++++++------- 1 file changed, 87 insertions(+), 29 deletions(-) diff --git a/minecraft-entities-derive/src/lib.rs b/minecraft-entities-derive/src/lib.rs index cef9c147..f35eccfe 100644 --- a/minecraft-entities-derive/src/lib.rs +++ b/minecraft-entities-derive/src/lib.rs @@ -196,6 +196,32 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { let mut inheritable = false; let mut defines = Vec::new(); let mut codes = Vec::new(); + + // Get struct name + let mut items = item.clone().into_iter(); + match items.next() { + Some(TokenTree::Ident(ident)) if ident.to_string() == "pub" => (), + Some(TokenTree::Punct(punct)) if punct.as_char() == '#' => { + items.next(); + match items.next() { + Some(TokenTree::Ident(ident)) if ident.to_string() == "pub" => (), + Some(other) => abort!(other.span(), "expected struct to be public"), + None => panic!("expected public struct, found nothing"), + } + } + Some(other) => abort!(other.span(), "expected struct to be public"), + None => panic!("expected public struct, found nothing"), + } + match items.next() { + Some(TokenTree::Ident(ident)) if ident.to_string() == "struct" => (), + Some(other) => abort!(other.span(), "expected struct, found {:?}"), + None => panic!("expected struct, found nothing"), + } + let struct_name = match items.next() { + Some(TokenTree::Ident(ident)) => ident, + Some(other) => abort!(other.span(), "expected struct name, found {:?}"), + None => panic!("expected struct name, found nothing"), + }; // Parse attributes let mut attrs = attr.into_iter().peekable(); @@ -255,7 +281,7 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { params.next(); args.push((name, ty)); } - defines.push((ty, method, args)); + defines.push((ty.unwrap_or_else(|| struct_name.clone()), method, args)); if matches!(group_attrs.peek(), Some(TokenTree::Punct(punct)) if punct.as_char() == ';') { group_attrs.next(); } @@ -267,32 +293,8 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { attrs.next(); } } - - // Get struct name - let mut items = item.clone().into_iter(); - match items.next() { - Some(TokenTree::Ident(ident)) if ident.to_string() == "pub" => (), - Some(TokenTree::Punct(punct)) if punct.as_char() == '#' => { - items.next(); - match items.next() { - Some(TokenTree::Ident(ident)) if ident.to_string() == "pub" => (), - Some(other) => abort!(other.span(), "expected struct to be public"), - None => panic!("expected public struct, found nothing"), - } - } - Some(other) => abort!(other.span(), "expected struct to be public"), - None => panic!("expected public struct, found nothing"), - } - match items.next() { - Some(TokenTree::Ident(ident)) if ident.to_string() == "struct" => (), - Some(other) => abort!(other.span(), "expected struct, found {:?}"), - None => panic!("expected struct, found nothing"), - } - let struct_name = match items.next() { - Some(TokenTree::Ident(ident)) => ident, - Some(other) => abort!(other.span(), "expected struct name, found {:?}"), - None => panic!("expected struct name, found nothing"), - }; + let mut hierarchy = inherited.clone(); + hierarchy.insert(0, struct_name.clone()); let mut to_replace = HashMap::new(); to_replace.insert("This", struct_name.clone()); @@ -377,7 +379,7 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { replace_idents(element, &to_replace); } let mut inner_codes = TokenStream::new(); - for (_, method, args) in defines.iter().filter(|(ty, _, _)| ty.is_none()) { + for (_, method, args) in defines.iter().filter(|(ty, _, _)| ty.to_string() == struct_name.to_string()) { let inner_code: TokenStream = match args.len() { 0 => String::from(r#"pub method: CallBack>,"#), 1 => format!(r#"pub method: CallBack1, {}>,"#, args[0].1), @@ -387,7 +389,6 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { _ => abort!(method.span(), "too many arguments"), }.parse().unwrap(); to_replace.insert("method", method.clone()); - // TODO to_replace.insert("args", args); let mut inner_code = inner_code.clone().into_iter().collect::>(); for element in &mut inner_code { replace_idents(element, &to_replace); @@ -400,6 +401,63 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { let code: TokenStream = code.into_iter().collect(); codes.push(code); + // Generate default for methods struct + let mut hierarchy_iter = hierarchy.iter().peekable(); + while let Some(ascendant) = hierarchy_iter.next() { + let code: TokenStream = r#" + const ASCENDANT_METHODS_FOR_THIS: &AscendantMethods = &AscendantMethods { + + }; + "#.parse().unwrap(); + to_replace.insert("ASCENDANT_METHODS_FOR_THIS", Ident::new(&format!("{}_METHODS_FOR_{}", ascendant.to_string().to_case(Case::ScreamingSnake), struct_name.to_string().to_case(Case::ScreamingSnake)), ascendant.span())); + to_replace.insert("Ascendant", ascendant.clone()); + to_replace.insert("AscendantMethods", Ident::new(&format!("{}Methods", ascendant), ascendant.span())); + let mut code = code.clone().into_iter().collect::>(); + for element in &mut code { + replace_idents(element, &to_replace); + } + let mut inner_codes = TokenStream::new(); + for (_, method, args) in defines.iter().filter(|(ty, _, _)| ty.to_string() == ascendant.to_string()) { + let inner_code: TokenStream = match args.len() { + 0 => r#"method: |s| Box::pin(s.assume_other::().method()),"#, + 1 => r#"method: |s, arg1| Box::pin(s.assume_other::().method(arg1)),"#, + 2 => r#"method: |s, arg1, arg2| Box::pin(s.assume_other::().method(arg1, arg2)),"#, + 3 => r#"method: |s, arg1, arg2, arg3| Box::pin(s.assume_other::().method(arg1, arg2, arg3)),"#, + 4 => r#"method: |s, arg1, arg2, arg3, arg4| Box::pin(s.assume_other::().method(arg1, arg2, arg3, arg4)),"#, + _ => abort!(method.span(), "too many arguments"), + }.parse().unwrap(); + to_replace.insert("method", method.clone()); + for (i, (name, _)) in args.iter().enumerate() { + to_replace.insert(["arg1", "arg2", "arg3", "arg4"][i], name.clone()); + } + let mut inner_code = inner_code.clone().into_iter().collect::>(); + for element in &mut inner_code { + replace_idents(element, &to_replace); + } + let inner_code: TokenStream = inner_code.into_iter().collect(); + inner_codes.extend(inner_code); + } + let i = code.len() - 2; + let TokenTree::Group(ref mut group) = code.get_mut(i).unwrap() else {unreachable!()}; + *group = Group::new(group.delimiter(), group.stream().into_iter().chain(inner_codes.into_iter()).collect()); + + if ascendant.to_string() != struct_name.to_string() { + let inner_code: TokenStream = r#"..*ASCENDANT_METHODS_FOR_PARENT"#.parse().unwrap(); + to_replace.insert("ASCENDANT_METHODS_FOR_PARENT", Ident::new(&format!("{}_METHODS_FOR_{}", ascendant.to_string().to_case(Case::ScreamingSnake), hierarchy[1].to_string().to_case(Case::ScreamingSnake)), ascendant.span())); + let mut inner_code = inner_code.clone().into_iter().collect::>(); + for element in &mut inner_code { + replace_idents(element, &to_replace); + } + let inner_code: TokenStream = inner_code.into_iter().collect(); + let TokenTree::Group(ref mut group) = code.get_mut(i).unwrap() else {unreachable!()}; + *group = Group::new(group.delimiter(), group.stream().into_iter().chain(inner_code.into_iter()).collect()); + } + + let code: TokenStream = code.into_iter().collect(); + codes.push(code); + + } + // Generate final code let mut final_code = item; for code in codes { From 46adc8cd9a5a7806c490515168860db50cf275e0 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 9 Nov 2023 19:16:08 +0100 Subject: [PATCH 14/89] Fix warning --- minecraft-entities-derive/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/minecraft-entities-derive/src/lib.rs b/minecraft-entities-derive/src/lib.rs index f35eccfe..ef7675a6 100644 --- a/minecraft-entities-derive/src/lib.rs +++ b/minecraft-entities-derive/src/lib.rs @@ -402,8 +402,8 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { codes.push(code); // Generate default for methods struct - let mut hierarchy_iter = hierarchy.iter().peekable(); - while let Some(ascendant) = hierarchy_iter.next() { + let hierarchy_iter = hierarchy.iter().peekable(); + for ascendant in hierarchy_iter { let code: TokenStream = r#" const ASCENDANT_METHODS_FOR_THIS: &AscendantMethods = &AscendantMethods { From 1253794319662795761bf134383dfdee7e54181d Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 9 Nov 2023 19:18:20 +0100 Subject: [PATCH 15/89] Fix issue --- minecraft-entities-derive/examples/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/minecraft-entities-derive/examples/main.rs b/minecraft-entities-derive/examples/main.rs index fe0ee220..73836ca9 100644 --- a/minecraft-entities-derive/examples/main.rs +++ b/minecraft-entities-derive/examples/main.rs @@ -75,7 +75,7 @@ pub struct Animal { parents { Animal, Entity }, defines { Entity.on_spawned(self); - Animal.on_hit(self); + Animal.on_hit(self, damage: usize); on_milked(self); } )] From c1bf87ba269cdf0ebcd2aa920632b43c40c2fb59 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 9 Nov 2023 19:19:05 +0100 Subject: [PATCH 16/89] Add implementations --- minecraft-entities-derive/examples/main.rs | 26 +++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/minecraft-entities-derive/examples/main.rs b/minecraft-entities-derive/examples/main.rs index 73836ca9..16cad532 100644 --- a/minecraft-entities-derive/examples/main.rs +++ b/minecraft-entities-derive/examples/main.rs @@ -58,6 +58,16 @@ pub struct Entity { } +impl Handler { + async fn on_moved(self, from: f32, to: f32) { + println!("Entity moved from {} to {}", from, to); + } + + async fn on_spawned(self) { + println!("Entity spawned"); + } +} + #[MinecraftEntity( parents { Entity }, inheritable, @@ -71,6 +81,16 @@ pub struct Animal { entity: Entity, } +impl Handler { + async fn on_hit(self, damage: usize) { + println!("Animal hit with {} damage", damage); + } + + async fn on_jump(self) { + println!("Animal jumped"); + } +} + #[MinecraftEntity( parents { Animal, Entity }, defines { @@ -83,7 +103,11 @@ pub struct Cow { animal: Animal, } - +impl Handler { + async fn on_milked(self) { + println!("Cow milked"); + } +} fn main() { From 3019afb489f1ddc183e0e1fa3d076c06749bd96a Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 9 Nov 2023 19:49:00 +0100 Subject: [PATCH 17/89] Generate ext trait --- minecraft-entities-derive/src/lib.rs | 60 ++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/minecraft-entities-derive/src/lib.rs b/minecraft-entities-derive/src/lib.rs index ef7675a6..369aa84c 100644 --- a/minecraft-entities-derive/src/lib.rs +++ b/minecraft-entities-derive/src/lib.rs @@ -300,6 +300,7 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { to_replace.insert("This", struct_name.clone()); to_replace.insert("ThisDescendant", Ident::new(&format!("{}Descendant", struct_name), struct_name.span())); to_replace.insert("ThisMethods", Ident::new(&format!("{}Methods", struct_name), struct_name.span())); + to_replace.insert("ThisExt", Ident::new(&format!("{}Ext", struct_name), struct_name.span())); to_replace.insert("get_this", Ident::new(&format!("get_{}", struct_name.to_string().to_case(Case::Snake)), struct_name.span())); to_replace.insert("get_this_mut", Ident::new(&format!("get_{}_mut", struct_name.to_string().to_case(Case::Snake)), struct_name.span())); @@ -368,6 +369,59 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { codes.push(code); } + // Generate ext trait + let code: TokenStream = r#" + trait ThisExt: Sized + Into> { + fn methods() -> &'static ThisMethods; + } + "#.parse().unwrap(); + let mut code = code.clone().into_iter().collect::>(); + for element in &mut code { + replace_idents(element, &to_replace); + } + let mut inner_codes = TokenStream::new(); + for (_, method, args) in defines.iter().filter(|(ty, _, _)| ty.to_string() == struct_name.to_string()) { + let inner_code: TokenStream = match args.len() { + 0 => String::from(r#" + fn method(self) -> Pin>> {{ + (Self::methods().method)(self.into()) + }} + "#), + 1 => format!(r#" + fn method(self, arg1: {}) -> Pin>> {{ + (Self::methods().method)(self.into(), arg1) + }} + "#, args[0].1), + 2 => format!(r#" + fn method(self, arg1: {}, arg2: {}) -> Pin>> {{ + (Self::methods().method)(self.into(), arg1, arg2) + }} + "#, args[0].1, args[1].1), + 3 => format!(r#" + fn method(self, arg1: {}, arg2: {}, arg3: {}) -> Pin>> {{ + (Self::methods().method)(self.into(), arg1, arg2, arg3) + }} + "#, args[0].1, args[1].1, args[2].1), + 4 => format!(r#" + fn method(self, arg1: {}, arg2: {}, arg3: {}, arg4: {}) -> Pin>> {{ + (Self::methods().method)(self.into(), arg1, arg2, arg3, arg4) + }} + "#, args[0].1, args[1].1, args[2].1, args[3].1), + _ => abort!(method.span(), "too many arguments"), + }.parse().unwrap(); + to_replace.insert("method", method.clone()); + let mut inner_code = inner_code.clone().into_iter().collect::>(); + for element in &mut inner_code { + replace_idents(element, &to_replace); + } + let inner_code: TokenStream = inner_code.into_iter().collect(); + inner_codes.extend(inner_code); + } + let TokenTree::Group(ref mut group) = code.last_mut().unwrap() else {unreachable!()}; + *group = Group::new(group.delimiter(), group.stream().into_iter().chain(inner_codes.into_iter()).collect()); + let code: TokenStream = code.into_iter().collect(); + codes.push(code); + // Generate methods struct let code: TokenStream = r#" pub struct ThisMethods { @@ -402,8 +456,7 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { codes.push(code); // Generate default for methods struct - let hierarchy_iter = hierarchy.iter().peekable(); - for ascendant in hierarchy_iter { + for ascendant in hierarchy.iter().peekable() { let code: TokenStream = r#" const ASCENDANT_METHODS_FOR_THIS: &AscendantMethods = &AscendantMethods { @@ -455,9 +508,10 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { let code: TokenStream = code.into_iter().collect(); codes.push(code); - } + + // Generate final code let mut final_code = item; for code in codes { From 7931cb9a4d3d8358b5ccfdd3c9416608980c03bf Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 9 Nov 2023 19:52:52 +0100 Subject: [PATCH 18/89] Implement ext traits --- minecraft-entities-derive/src/lib.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/minecraft-entities-derive/src/lib.rs b/minecraft-entities-derive/src/lib.rs index 369aa84c..34cf5a29 100644 --- a/minecraft-entities-derive/src/lib.rs +++ b/minecraft-entities-derive/src/lib.rs @@ -510,7 +510,26 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { codes.push(code); } - + // Implement ext traits + for ascendant in hierarchy.iter().peekable() { + let code: TokenStream = r#" + impl AscendantExt for Handler { + fn methods() -> &'static AscendantMethods { + ASCENDANT_METHODS_FOR_THIS + } + } + "#.parse().unwrap(); + to_replace.insert("ASCENDANT_METHODS_FOR_THIS", Ident::new(&format!("{}_METHODS_FOR_{}", ascendant.to_string().to_case(Case::ScreamingSnake), struct_name.to_string().to_case(Case::ScreamingSnake)), ascendant.span())); + to_replace.insert("Ascendant", ascendant.clone()); + to_replace.insert("AscendantExt", Ident::new(&format!("{}Ext", ascendant), ascendant.span())); + to_replace.insert("AscendantMethods", Ident::new(&format!("{}Methods", ascendant), ascendant.span())); + let mut code = code.clone().into_iter().collect::>(); + for element in &mut code { + replace_idents(element, &to_replace); + } + let code: TokenStream = code.into_iter().collect(); + codes.push(code); + } // Generate final code let mut final_code = item; From b36e2b45f15b757f9300ed68557c9a35b2f43692 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 9 Nov 2023 19:56:32 +0100 Subject: [PATCH 19/89] Implement conversion traits --- minecraft-entities-derive/src/lib.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/minecraft-entities-derive/src/lib.rs b/minecraft-entities-derive/src/lib.rs index 34cf5a29..9bc73a39 100644 --- a/minecraft-entities-derive/src/lib.rs +++ b/minecraft-entities-derive/src/lib.rs @@ -531,6 +531,24 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { codes.push(code); } + // Implement conversion traits + for ascendant in hierarchy.iter().peekable() { + let code: TokenStream = r#" + impl From> for Handler { + fn from(val: Handler) -> Self { + val.assume_other() + } + } + "#.parse().unwrap(); + to_replace.insert("Ascendant", ascendant.clone()); + let mut code = code.clone().into_iter().collect::>(); + for element in &mut code { + replace_idents(element, &to_replace); + } + let code: TokenStream = code.into_iter().collect(); + codes.push(code); + } + // Generate final code let mut final_code = item; for code in codes { From 52e4497584ea5e8f5831d825243e84868aeb65e0 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Thu, 9 Nov 2023 19:57:08 +0100 Subject: [PATCH 20/89] Fix issue --- minecraft-entities-derive/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/minecraft-entities-derive/src/lib.rs b/minecraft-entities-derive/src/lib.rs index 9bc73a39..b15cdc33 100644 --- a/minecraft-entities-derive/src/lib.rs +++ b/minecraft-entities-derive/src/lib.rs @@ -532,7 +532,7 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { } // Implement conversion traits - for ascendant in hierarchy.iter().peekable() { + for ascendant in hierarchy.iter().skip(1) { let code: TokenStream = r#" impl From> for Handler { fn from(val: Handler) -> Self { From 51c80096fde3ab3ccf5f8a73b9db05b06b0bd328 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Fri, 10 Nov 2023 00:13:44 +0100 Subject: [PATCH 21/89] Fix mistake --- minecraft-entities-derive/examples/main.rs | 5 +++++ minecraft-entities-derive/src/lib.rs | 10 +++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/minecraft-entities-derive/examples/main.rs b/minecraft-entities-derive/examples/main.rs index 16cad532..cc63cfa1 100644 --- a/minecraft-entities-derive/examples/main.rs +++ b/minecraft-entities-derive/examples/main.rs @@ -45,6 +45,7 @@ impl Handler { } } +// Entity #[MinecraftEntity( parents { }, @@ -68,6 +69,8 @@ impl Handler { } } +// Animal + #[MinecraftEntity( parents { Entity }, inheritable, @@ -91,6 +94,8 @@ impl Handler { } } +// Cow + #[MinecraftEntity( parents { Animal, Entity }, defines { diff --git a/minecraft-entities-derive/src/lib.rs b/minecraft-entities-derive/src/lib.rs index b15cdc33..00054658 100644 --- a/minecraft-entities-derive/src/lib.rs +++ b/minecraft-entities-derive/src/lib.rs @@ -472,11 +472,11 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { let mut inner_codes = TokenStream::new(); for (_, method, args) in defines.iter().filter(|(ty, _, _)| ty.to_string() == ascendant.to_string()) { let inner_code: TokenStream = match args.len() { - 0 => r#"method: |s| Box::pin(s.assume_other::().method()),"#, - 1 => r#"method: |s, arg1| Box::pin(s.assume_other::().method(arg1)),"#, - 2 => r#"method: |s, arg1, arg2| Box::pin(s.assume_other::().method(arg1, arg2)),"#, - 3 => r#"method: |s, arg1, arg2, arg3| Box::pin(s.assume_other::().method(arg1, arg2, arg3)),"#, - 4 => r#"method: |s, arg1, arg2, arg3, arg4| Box::pin(s.assume_other::().method(arg1, arg2, arg3, arg4)),"#, + 0 => r#"method: |s| Box::pin(s.assume_other::().method()),"#, + 1 => r#"method: |s, arg1| Box::pin(s.assume_other::().method(arg1)),"#, + 2 => r#"method: |s, arg1, arg2| Box::pin(s.assume_other::().method(arg1, arg2)),"#, + 3 => r#"method: |s, arg1, arg2, arg3| Box::pin(s.assume_other::().method(arg1, arg2, arg3)),"#, + 4 => r#"method: |s, arg1, arg2, arg3, arg4| Box::pin(s.assume_other::().method(arg1, arg2, arg3, arg4)),"#, _ => abort!(method.span(), "too many arguments"), }.parse().unwrap(); to_replace.insert("method", method.clone()); From 84f5687d710378d5b9c068cf02774430a5fea3ca Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Fri, 10 Nov 2023 01:16:47 +0100 Subject: [PATCH 22/89] Fix infinite recursion --- minecraft-entities-derive/src/lib.rs | 30 +++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/minecraft-entities-derive/src/lib.rs b/minecraft-entities-derive/src/lib.rs index 00054658..96bb2b37 100644 --- a/minecraft-entities-derive/src/lib.rs +++ b/minecraft-entities-derive/src/lib.rs @@ -456,9 +456,10 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { codes.push(code); // Generate default for methods struct + let mut mod_codes = Vec::new(); for ascendant in hierarchy.iter().peekable() { let code: TokenStream = r#" - const ASCENDANT_METHODS_FOR_THIS: &AscendantMethods = &AscendantMethods { + pub(super) const ASCENDANT_METHODS_FOR_THIS: &AscendantMethods = &AscendantMethods { }; "#.parse().unwrap(); @@ -507,18 +508,29 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { } let code: TokenStream = code.into_iter().collect(); - codes.push(code); + mod_codes.push(code); } + let mod_codes: TokenStream = mod_codes.into_iter().collect(); + let mod_code: TokenStream = format!(r#" + mod {struct_name}_methods {{ + use super::{{ {} }}; + }} + "#, hierarchy.iter().map(|i| format!("{i}, {i}Methods")).chain(hierarchy.iter().skip(1).map(|i| format!("{i}_methods::*"))).collect::>().join(","), + ).parse().unwrap(); + let mut mod_code = mod_code.into_iter().collect::>(); + let TokenTree::Group(ref mut group) = mod_code.last_mut().unwrap() else {unreachable!()}; + *group = Group::new(group.delimiter(), group.stream().into_iter().chain(mod_codes.into_iter()).collect()); + codes.push(mod_code.into_iter().collect()); // Implement ext traits for ascendant in hierarchy.iter().peekable() { - let code: TokenStream = r#" - impl AscendantExt for Handler { - fn methods() -> &'static AscendantMethods { - ASCENDANT_METHODS_FOR_THIS - } - } - "#.parse().unwrap(); + let code: TokenStream = format!(r#" + impl AscendantExt for Handler {{ + fn methods() -> &'static AscendantMethods {{ + {struct_name}_methods::ASCENDANT_METHODS_FOR_THIS + }} + }} + "#).parse().unwrap(); to_replace.insert("ASCENDANT_METHODS_FOR_THIS", Ident::new(&format!("{}_METHODS_FOR_{}", ascendant.to_string().to_case(Case::ScreamingSnake), struct_name.to_string().to_case(Case::ScreamingSnake)), ascendant.span())); to_replace.insert("Ascendant", ascendant.clone()); to_replace.insert("AscendantExt", Ident::new(&format!("{}Ext", ascendant), ascendant.span())); From 16a62b2deac230ffe556173e1c7ab470fd390a94 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Fri, 10 Nov 2023 01:18:09 +0100 Subject: [PATCH 23/89] Fix missing methods --- minecraft-entities-derive/examples/main.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/minecraft-entities-derive/examples/main.rs b/minecraft-entities-derive/examples/main.rs index cc63cfa1..a1be6c76 100644 --- a/minecraft-entities-derive/examples/main.rs +++ b/minecraft-entities-derive/examples/main.rs @@ -92,6 +92,10 @@ impl Handler { async fn on_jump(self) { println!("Animal jumped"); } + + async fn on_spawned(self) { + println!("Animal spawned"); + } } // Cow @@ -112,8 +116,15 @@ impl Handler { async fn on_milked(self) { println!("Cow milked"); } + + async fn on_hit(self, damage: usize) { + println!("Cow hit with {} damage", damage); + } + + async fn on_spawned(self) { + println!("Cow spawned"); + } } fn main() { - } From c009dcd921bb80bf7c6f7469192e031a0e2d6af3 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Fri, 10 Nov 2023 10:55:03 +0100 Subject: [PATCH 24/89] Fix some issues --- minecraft-entities-derive/src/lib.rs | 207 +++------------------------ 1 file changed, 21 insertions(+), 186 deletions(-) diff --git a/minecraft-entities-derive/src/lib.rs b/minecraft-entities-derive/src/lib.rs index 96bb2b37..6022b034 100644 --- a/minecraft-entities-derive/src/lib.rs +++ b/minecraft-entities-derive/src/lib.rs @@ -23,171 +23,6 @@ fn replace_idents(token: &mut TokenTree, to_replace: &HashMap<&'static str, Iden } } -#[proc_macro_attribute] -pub fn inherit(attr: TokenStream, item: TokenStream) -> TokenStream { - // List inherited items - let mut inherited = Vec::new(); - let mut attrs = attr.into_iter(); - loop { - match attrs.next() { - Some(TokenTree::Ident(ident)) => inherited.push(ident), - Some(other) => panic!("unexpected token: {:?}", other), - None => break, - } - - match attrs.next() { - Some(TokenTree::Punct(punct)) => { - if punct.as_char() != ',' { - panic!("unexpected punct: {:?}", punct); - } - }, - Some(other) => panic!("unexpected token: {:?}", other), - None => break, - } - } - let parent = inherited.remove(0); - - // Get struct name - let mut items = item.clone().into_iter(); - match items.next() { - Some(TokenTree::Ident(ident)) if ident.to_string() == "pub" => (), - Some(TokenTree::Punct(punct)) if punct.as_char() == '#' => { - items.next(); - match items.next() { - Some(TokenTree::Ident(ident)) if ident.to_string() == "pub" => (), - Some(other) => panic!("expected struct to be public, found {:?}", other), - None => panic!("expected public struct, found nothing"), - } - } - Some(other) => panic!("expected struct to be public, found {:?}", other), - None => panic!("expected public struct, found nothing"), - } - match items.next() { - Some(TokenTree::Ident(ident)) if ident.to_string() == "struct" => (), - Some(other) => panic!("expected struct, found {:?}", other), - None => panic!("expected struct, found nothing"), - } - let struct_name = match items.next() { - Some(TokenTree::Ident(ident)) => ident, - Some(other) => panic!("expected struct name, found {:?}", other), - None => panic!("expected struct name, found nothing"), - }; - - let mut codes = Vec::new(); - - // Generate code for parent - let code: TokenStream = r#" - impl ParentDescendant for This { - fn get_parent(&self) -> &Parent { &self.parent } - fn get_parent_mut(&mut self) -> &mut Parent { &mut self.parent } - } - "#.parse().unwrap(); - let mut to_replace = HashMap::new(); - to_replace.insert("ParentDescendant", Ident::new(&format!("{}Descendant", parent), parent.span())); - to_replace.insert("Parent", parent.clone()); - to_replace.insert("This", struct_name.clone()); - to_replace.insert("get_parent", Ident::new(&format!("get_{}", parent.to_string().to_case(Case::Snake)), parent.span())); - to_replace.insert("get_parent_mut", Ident::new(&format!("get_{}_mut", parent.to_string().to_case(Case::Snake)), parent.span())); - to_replace.insert("parent", Ident::new(&parent.to_string().to_case(Case::Snake), parent.span())); - let mut code = code.clone().into_iter().collect::>(); - for element in &mut code { - replace_idents(element, &to_replace); - } - let code: TokenStream = code.into_iter().collect(); - println!("{}", code); - codes.push(code); - - // Generate code for higher inheritance levels - let code: TokenStream = r#" - impl InheritedDescendant for This { - fn get_inherited(&self) -> &Inherited { self.parent.get_inherited() } - fn get_inherited_mut(&mut self) -> &mut Inherited { self.parent.get_inherited_mut() } - } - "#.parse().unwrap(); - for inherited in inherited { - let mut to_replace = HashMap::new(); - to_replace.insert("InheritedDescendant", Ident::new(&format!("{}Descendant", inherited), inherited.span())); - to_replace.insert("Inherited", inherited.clone()); - to_replace.insert("This", struct_name.clone()); - to_replace.insert("get_inherited", Ident::new(&format!("get_{}", inherited.to_string().to_case(Case::Snake)), inherited.span())); - to_replace.insert("get_inherited_mut", Ident::new(&format!("get_{}_mut", inherited.to_string().to_case(Case::Snake)), inherited.span())); - to_replace.insert("parent", Ident::new(&parent.to_string().to_case(Case::Snake), parent.span())); - - let mut code = code.clone().into_iter().collect::>(); - for element in &mut code { - replace_idents(element, &to_replace); - } - let code: TokenStream = code.into_iter().collect(); - codes.push(code); - } - - // Generate final code - let mut final_code = item; - for code in codes { - final_code.extend(code); - } - final_code -} - -#[proc_macro_attribute] -pub fn inheritable(_attr: TokenStream, item: TokenStream) -> TokenStream { - println!("{:?}", item); - - // Get struct name - let mut items = item.clone().into_iter(); - match items.next() { - Some(TokenTree::Ident(ident)) if ident.to_string() == "pub" => (), - Some(TokenTree::Punct(punct)) if punct.as_char() == '#' => { - items.next(); - match items.next() { - Some(TokenTree::Ident(ident)) if ident.to_string() == "pub" => (), - Some(other) => panic!("expected struct to be public, found {:?}", other), - None => panic!("expected public struct, found nothing"), - } - } - Some(other) => panic!("expected struct to be public, found {:?}", other), - None => panic!("expected public struct, found nothing"), - } - match items.next() { - Some(TokenTree::Ident(ident)) if ident.to_string() == "struct" => (), - Some(other) => panic!("expected struct, found {:?}", other), - None => panic!("expected struct, found nothing"), - } - let struct_name = match items.next() { - Some(TokenTree::Ident(ident)) => ident, - Some(other) => panic!("expected struct name, found {:?}", other), - None => panic!("expected struct name, found nothing"), - }; - - // Generate implementation - let code: TokenStream = r#" - pub trait ThisDescendant { - fn get_this(&self) -> &This; - fn get_this_mut(&mut self) -> &mut This; - } - - impl ThisDescendant for This { - fn get_this(&self) -> &This { self } - fn get_this_mut(&mut self) -> &mut This { self } - } - "#.parse().unwrap(); - let mut to_replace = HashMap::new(); - to_replace.insert("This", struct_name.clone()); - to_replace.insert("ThisDescendant", Ident::new(&format!("{}Descendant", struct_name), struct_name.span())); - to_replace.insert("get_this", Ident::new(&format!("get_{}", struct_name.to_string().to_case(Case::Snake)), struct_name.span())); - to_replace.insert("get_this_mut", Ident::new(&format!("get_{}_mut", struct_name.to_string().to_case(Case::Snake)), struct_name.span())); - let mut code = code.clone().into_iter().collect::>(); - for element in &mut code { - replace_idents(element, &to_replace); - } - let code: TokenStream = code.into_iter().collect(); - - // Assemble final code - let mut final_code = item; - final_code.extend(code); - final_code -} - #[allow(non_snake_case)] #[proc_macro_attribute] #[proc_macro_error] @@ -325,27 +160,27 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { let code: TokenStream = code.into_iter().collect(); println!("{}", code); codes.push(code); + } - // Generate code for higher inheritance levels - let code: TokenStream = r#" - impl InheritedDescendant for This { - fn get_inherited(&self) -> &Inherited { self.parent.get_inherited() } - fn get_inherited_mut(&mut self) -> &mut Inherited { self.parent.get_inherited_mut() } - } - "#.parse().unwrap(); - for inherited in inherited { - to_replace.insert("InheritedDescendant", Ident::new(&format!("{}Descendant", inherited), inherited.span())); - to_replace.insert("Inherited", inherited.clone()); - to_replace.insert("get_inherited", Ident::new(&format!("get_{}", inherited.to_string().to_case(Case::Snake)), inherited.span())); - to_replace.insert("get_inherited_mut", Ident::new(&format!("get_{}_mut", inherited.to_string().to_case(Case::Snake)), inherited.span())); + // Generate code for higher inheritance levels + let code: TokenStream = r#" + impl InheritedDescendant for This { + fn get_inherited(&self) -> &Inherited { self.parent.get_inherited() } + fn get_inherited_mut(&mut self) -> &mut Inherited { self.parent.get_inherited_mut() } + } + "#.parse().unwrap(); + for inherited in inherited { + to_replace.insert("InheritedDescendant", Ident::new(&format!("{}Descendant", inherited), inherited.span())); + to_replace.insert("Inherited", inherited.clone()); + to_replace.insert("get_inherited", Ident::new(&format!("get_{}", inherited.to_string().to_case(Case::Snake)), inherited.span())); + to_replace.insert("get_inherited_mut", Ident::new(&format!("get_{}_mut", inherited.to_string().to_case(Case::Snake)), inherited.span())); - let mut code = code.clone().into_iter().collect::>(); - for element in &mut code { - replace_idents(element, &to_replace); - } - let code: TokenStream = code.into_iter().collect(); - codes.push(code); + let mut code = code.clone().into_iter().collect::>(); + for element in &mut code { + replace_idents(element, &to_replace); } + let code: TokenStream = code.into_iter().collect(); + codes.push(code); } if inheritable { @@ -371,7 +206,7 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { // Generate ext trait let code: TokenStream = r#" - trait ThisExt: Sized + Into> { + pub trait ThisExt: Sized + Into> { fn methods() -> &'static ThisMethods; } "#.parse().unwrap(); @@ -459,7 +294,7 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { let mut mod_codes = Vec::new(); for ascendant in hierarchy.iter().peekable() { let code: TokenStream = r#" - pub(super) const ASCENDANT_METHODS_FOR_THIS: &AscendantMethods = &AscendantMethods { + pub const ASCENDANT_METHODS_FOR_THIS: &AscendantMethods = &AscendantMethods { }; "#.parse().unwrap(); @@ -512,7 +347,7 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { } let mod_codes: TokenStream = mod_codes.into_iter().collect(); let mod_code: TokenStream = format!(r#" - mod {struct_name}_methods {{ + pub mod {struct_name}_methods {{ use super::{{ {} }}; }} "#, hierarchy.iter().map(|i| format!("{i}, {i}Methods")).chain(hierarchy.iter().skip(1).map(|i| format!("{i}_methods::*"))).collect::>().join(","), From e8bc5509f5bffd51b20183d0595029681c294b83 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Fri, 10 Nov 2023 13:28:36 +0100 Subject: [PATCH 25/89] First half --- minecraft-entities/src/animals/axolotl.rs | 4 +- minecraft-entities/src/animals/bee.rs | 4 +- minecraft-entities/src/animals/cat.rs | 4 +- minecraft-entities/src/animals/chicken.rs | 4 +- minecraft-entities/src/animals/cow.rs | 201 +----------------- minecraft-entities/src/animals/donkey.rs | 7 - minecraft-entities/src/animals/fishes.rs | 42 ---- minecraft-entities/src/animals/fox.rs | 4 +- minecraft-entities/src/animals/frog.rs | 4 +- minecraft-entities/src/animals/goat.rs | 4 +- minecraft-entities/src/animals/hoglin.rs | 4 +- minecraft-entities/src/animals/horses.rs | 79 ++++++- minecraft-entities/src/animals/llama.rs | 36 ---- minecraft-entities/src/animals/mod.rs | 16 +- minecraft-entities/src/animals/ocelot.rs | 4 +- minecraft-entities/src/animals/panda.rs | 4 +- minecraft-entities/src/animals/parrot.rs | 4 +- minecraft-entities/src/animals/pig.rs | 4 +- minecraft-entities/src/animals/polar_bear.rs | 4 +- minecraft-entities/src/animals/rabbit.rs | 4 +- minecraft-entities/src/animals/sheep.rs | 5 +- minecraft-entities/src/animals/sniffer.rs | 5 +- minecraft-entities/src/animals/strider.rs | 5 +- minecraft-entities/src/animals/turtle.rs | 4 +- .../src/animals/water_animal.rs | 60 +++++- minecraft-entities/src/arrow.rs | 17 +- minecraft-entities/src/block.rs | 4 +- minecraft-entities/src/boat.rs | 9 +- minecraft-entities/src/display.rs | 21 +- .../src/ecs/components/health.rs | 0 .../src/ecs/components/mod.rs | 0 .../src/ecs/components/positions.rs | 0 .../src/ecs/entities.rs | 0 .../src/ecs/mod.rs | 0 .../src/ecs/tags.rs | 0 minecraft-entities/src/entity.rs | 4 +- minecraft-entities/src/fire_entities.rs | 16 +- minecraft-entities/src/interaction.rs | 4 +- minecraft-entities/src/item.rs | 13 +- minecraft-entities/src/lib.rs | 35 ++- minecraft-entities/src/living_entity.rs | 9 +- minecraft-entities/src/mobs/mod.rs | 21 +- minecraft-entities/src/monsters/mod.rs | 5 +- minecraft-entities/src/particles.rs | 9 +- minecraft-entities/src/player.rs | 4 +- minecraft-entities/src/shulker.rs | 4 +- .../src/thrown_item_projectile.rs | 29 ++- 47 files changed, 344 insertions(+), 376 deletions(-) delete mode 100644 minecraft-entities/src/animals/donkey.rs delete mode 100644 minecraft-entities/src/animals/fishes.rs delete mode 100644 minecraft-entities/src/animals/llama.rs rename {minecraft-server => minecraft-entities}/src/ecs/components/health.rs (100%) rename {minecraft-server => minecraft-entities}/src/ecs/components/mod.rs (100%) rename {minecraft-server => minecraft-entities}/src/ecs/components/positions.rs (100%) rename {minecraft-server => minecraft-entities}/src/ecs/entities.rs (100%) rename {minecraft-server => minecraft-entities}/src/ecs/mod.rs (100%) rename {minecraft-server => minecraft-entities}/src/ecs/tags.rs (100%) diff --git a/minecraft-entities/src/animals/axolotl.rs b/minecraft-entities/src/animals/axolotl.rs index 876bc08a..e137a43d 100644 --- a/minecraft-entities/src/animals/axolotl.rs +++ b/minecraft-entities/src/animals/axolotl.rs @@ -1,7 +1,9 @@ use super::*; #[derive(Default)] -#[inherit(Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Axolotl { pub animal: Animal, pub variant: u8, diff --git a/minecraft-entities/src/animals/bee.rs b/minecraft-entities/src/animals/bee.rs index 4f6e32dc..5cf99082 100644 --- a/minecraft-entities/src/animals/bee.rs +++ b/minecraft-entities/src/animals/bee.rs @@ -1,7 +1,9 @@ use super::*; #[derive(Default)] -#[inherit(Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Bee { pub animal: Animal, pub flag: u8, diff --git a/minecraft-entities/src/animals/cat.rs b/minecraft-entities/src/animals/cat.rs index 8e111c4f..028c6f1f 100644 --- a/minecraft-entities/src/animals/cat.rs +++ b/minecraft-entities/src/animals/cat.rs @@ -1,6 +1,8 @@ use super::*; -#[inherit(TameableAnimal, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { TameableAnimal, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Cat { pub tameable_animal: TameableAnimal, pub variant: u8, diff --git a/minecraft-entities/src/animals/chicken.rs b/minecraft-entities/src/animals/chicken.rs index 4ecb19a6..57e25686 100644 --- a/minecraft-entities/src/animals/chicken.rs +++ b/minecraft-entities/src/animals/chicken.rs @@ -1,7 +1,9 @@ use super::*; #[derive(Default)] -#[inherit(Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Chicken { pub animal: Animal, } diff --git a/minecraft-entities/src/animals/cow.rs b/minecraft-entities/src/animals/cow.rs index 5cfe973b..9e79f206 100644 --- a/minecraft-entities/src/animals/cow.rs +++ b/minecraft-entities/src/animals/cow.rs @@ -1,207 +1,18 @@ -use std::{pin::Pin, future::Future, sync::{Mutex, Arc}}; - use super::*; #[derive(Default)] -#[inheritable] -#[inherit(Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + inheritable, parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Cow { pub animal: Animal, } #[derive(Default)] -#[inherit(Cow, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] - +#[MinecraftEntity( + parents { Cow, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Mooshroom { pub cow: Cow, pub variant: u8, // In the doc it is a string } - -impl Handler { - async fn on_hit(self, damage: f32) { - println!("Animal was hit"); - } - - async fn on_dies(self) { - println!("Animal died"); - } -} - -impl Handler { - async fn on_hit(self, damage: f32) { - println!("Cow was hit"); - } -} - -// Function that returns a pinned boxed future -type CallBack = fn(O) -> Pin>>; -type CallBack1 = fn(O, I) -> Pin>>; - -pub struct Handler { - uuid: UUID, - world: Arc>, - entity: std::marker::PhantomData, -} - -impl Handler { - fn assume(uuid: UUID, world: Arc>) -> Self { - Self { - uuid, - world, - entity: std::marker::PhantomData, - } - } - - fn assume_other(self) -> Handler { - Handler { - uuid: self.uuid, - world: self.world, - entity: std::marker::PhantomData, - } - } -} - -// Entity: - -pub struct EntityMethods { - pub on_jump: CallBack>, -} - -trait EntityExt: Sized + Into> { - fn methods() -> EntityMethods; - - fn on_jump(self) -> Pin>> { - (Self::methods().on_jump)(self.into()) - } -} - -impl EntityExt for Handler { - fn methods() -> EntityMethods { - EntityMethods { - on_jump: |entity| Box::pin(async { - println!("Entity jumped"); - }), - } - } -} - -/// Animal: -/// -/// ``` -/// #[ -/// inheritable, -/// methods( -/// on_hit(self, damage: f32); -/// on_dies(self); -/// ) -/// ] -/// struct Animal { -/// pub entity: Entity, -/// } -/// -/// impl Handler { -/// async fn on_hit(self, damage: f32) { -/// println!("Animal was hit"); -/// } -/// -/// async fn on_dies(self) { -/// println!("Animal died"); -/// } -/// } -/// ``` - -pub struct AnimalMethods { - pub on_hit: CallBack1, f32>, - pub on_dies: CallBack>, -} - -trait AnimalExt: Sized + Into> { - fn methods() -> AnimalMethods; - - fn on_hit(self, damage: f32) -> Pin>> { - (Self::methods().on_hit)(self.into(), damage) - } - - fn on_dies(self) -> Pin>> { - (Self::methods().on_dies)(self.into()) - } -} - -impl AnimalExt for Handler { - fn methods() -> AnimalMethods { - AnimalMethods { - on_hit: |animal, damage| Box::pin(animal.on_hit(damage)), - on_dies: |animal| Box::pin(animal.on_dies()), - } - } -} - -impl From> for Handler { - fn from(val: Handler) -> Self { - val.assume_other() - } -} - -impl EntityExt for Handler { - fn methods() -> EntityMethods { - EntityMethods { - ..>::methods() - } - } -} - -/// Cow: -/// -/// ```rust -/// #[override( -/// animal.on_hit(self, damage: f32); -/// )] -/// struct Cow { -/// pub animal: Animal, -/// } -/// -/// impl Handler { -/// async fn on_hit(self, damage: f32) { -/// println!("Cow was hit"); -/// } -/// } -/// ``` - -impl From> for Handler { - fn from(val: Handler) -> Self { - val.assume_other() - } -} - -impl EntityExt for Handler { - fn methods() -> EntityMethods { - EntityMethods { - .. as EntityExt>::methods() - } - } -} - -impl From> for Handler { - fn from(val: Handler) -> Self { - val.assume_other() - } -} - -impl AnimalExt for Handler { - fn methods() -> AnimalMethods { - AnimalMethods { - on_hit: |animal, damage| Box::pin(animal.assume_other::().on_hit(damage)), - .. as AnimalExt>::methods() - } - } -} - -#[tokio::test] -async fn test() { - let cow = Handler::::assume(0, Arc::new(Mutex::new(()))); - cow.on_hit(1.0).await; - let cow = Handler::::assume(0, Arc::new(Mutex::new(()))); - cow.on_dies().await; - let cow = Handler::::assume(0, Arc::new(Mutex::new(()))); - cow.on_jump().await; -} diff --git a/minecraft-entities/src/animals/donkey.rs b/minecraft-entities/src/animals/donkey.rs deleted file mode 100644 index 0e734fb3..00000000 --- a/minecraft-entities/src/animals/donkey.rs +++ /dev/null @@ -1,7 +0,0 @@ -use super::*; - -#[derive(Default)] -#[inherit(ChestedHorse, AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] -pub struct Donkey { - pub chested_horse: ChestedHorse, -} diff --git a/minecraft-entities/src/animals/fishes.rs b/minecraft-entities/src/animals/fishes.rs deleted file mode 100644 index 1e38a964..00000000 --- a/minecraft-entities/src/animals/fishes.rs +++ /dev/null @@ -1,42 +0,0 @@ -use super::*; - -#[derive(Default)] -#[inheritable] -#[inherit(WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity)] -pub struct AbstractFish { - pub water_animal: WaterAnimal, - pub from_bucket: bool, -} - - -#[derive(Default)] -#[inherit(AbstractFish, WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity)] -pub struct Cod { - pub abstract_fish: AbstractFish, -} - -#[derive(Default)] -#[inherit(AbstractFish, WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity)] -pub struct PufferFish { - pub abstract_fish: AbstractFish, - pub puff_state: usize, -} - -#[derive(Default)] -#[inherit(AbstractFish, WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity)] -pub struct Salmon { - pub abstract_fish: AbstractFish, -} - -#[derive(Default)] -#[inherit(AbstractFish, WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity)] -pub struct TropicalFish { - pub abstract_fish: AbstractFish, - pub variant: usize, -} - -#[derive(Default)] -#[inherit(AbstractFish, WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity)] -pub struct Tadpole { - pub abstract_fish: AbstractFish, -} diff --git a/minecraft-entities/src/animals/fox.rs b/minecraft-entities/src/animals/fox.rs index 678e0fc5..b07ed93f 100644 --- a/minecraft-entities/src/animals/fox.rs +++ b/minecraft-entities/src/animals/fox.rs @@ -2,7 +2,9 @@ use minecraft_protocol::packets::UUID; use super::*; #[derive(Default)] -#[inherit(Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Fox { pub animal: Animal, pub variant: u8, diff --git a/minecraft-entities/src/animals/frog.rs b/minecraft-entities/src/animals/frog.rs index 63115498..6c03506d 100644 --- a/minecraft-entities/src/animals/frog.rs +++ b/minecraft-entities/src/animals/frog.rs @@ -2,7 +2,9 @@ use minecraft_protocol::packets::UUID; use super::*; #[derive(Default)] -#[inherit(Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Frog { pub animal: Animal, pub variant: u8, diff --git a/minecraft-entities/src/animals/goat.rs b/minecraft-entities/src/animals/goat.rs index bcacdb3c..3dfcda58 100644 --- a/minecraft-entities/src/animals/goat.rs +++ b/minecraft-entities/src/animals/goat.rs @@ -1,6 +1,8 @@ use super::*; -#[inherit(Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Goat { pub animal: Animal, pub is_screaming: bool, diff --git a/minecraft-entities/src/animals/hoglin.rs b/minecraft-entities/src/animals/hoglin.rs index dfa35664..713b0eb8 100644 --- a/minecraft-entities/src/animals/hoglin.rs +++ b/minecraft-entities/src/animals/hoglin.rs @@ -2,7 +2,9 @@ use minecraft_protocol::packets::UUID; use super::*; #[derive(Default)] -#[inherit(Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Hoglin { pub animal: Animal, pub is_immune: bool, diff --git a/minecraft-entities/src/animals/horses.rs b/minecraft-entities/src/animals/horses.rs index fdaab191..3b506838 100644 --- a/minecraft-entities/src/animals/horses.rs +++ b/minecraft-entities/src/animals/horses.rs @@ -1,34 +1,43 @@ use super::*; #[derive(Default)] -#[inheritable] -#[inherit(Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + inheritable, parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct AbstractHorse { pub animal: Animal, pub mask: u8, } #[derive(Default)] -#[inherit(AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Horse { pub abstract_horse: AbstractHorse, pub variant: usize, } #[derive(Default)] -#[inherit(AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct ZombieHorse { pub abstract_horse: AbstractHorse, } #[derive(Default)] -#[inherit(AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct SkeletonHorse { pub abstract_horse: AbstractHorse, } #[derive(Default)] -#[inherit(AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Camel { pub abstract_horse: AbstractHorse, pub is_dashing: bool, @@ -36,16 +45,66 @@ pub struct Camel { } #[derive(Default)] -#[inheritable] -#[inherit(AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + inheritable, parents { AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct ChestedHorse { pub abstract_horse: AbstractHorse, pub has_chest: bool, } #[derive(Default)] -#[inheritable] -#[inherit(ChestedHorse, AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { ChestedHorse, AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Mule { pub chested_horse: ChestedHorse, } + +#[derive(Default)] +#[MinecraftEntity( + parents { ChestedHorse, AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] +pub struct Donkey { + pub chested_horse: ChestedHorse, +} + +#[MinecraftEntity( + inheritable, parents { ChestedHorse, AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] +pub struct Llama { + pub chested_horse: ChestedHorse, + /// Strength (number of columns of 3 slots in the llama's inventory once a chest is equipped) + pub stength: u8, + /// Carpet color (a dye color, or -1 if no carpet equipped) + pub carpet_color: i16, + pub variant: u8, +} + +impl Default for Llama { + fn default() -> Self { + Self { + chested_horse: ChestedHorse::default(), + stength: 0, + carpet_color: -1, + variant: 0, + } + } +} + +#[derive(Default)] +#[MinecraftEntity( + parents { Llama, ChestedHorse, AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] +pub struct TraderLlama { + pub llama: Llama, +} + + +#[derive(Default)] +#[MinecraftEntity( + parents { Entity }, +)] +pub struct LlamaSpit { + pub entity: Entity, +} diff --git a/minecraft-entities/src/animals/llama.rs b/minecraft-entities/src/animals/llama.rs deleted file mode 100644 index 3e814e75..00000000 --- a/minecraft-entities/src/animals/llama.rs +++ /dev/null @@ -1,36 +0,0 @@ -use super::*; - -#[inheritable] -#[inherit(ChestedHorse, AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] -pub struct Llama { - pub chested_horse: ChestedHorse, - /// Strength (number of columns of 3 slots in the llama's inventory once a chest is equipped) - pub stength: u8, - /// Carpet color (a dye color, or -1 if no carpet equipped) - pub carpet_color: i16, - pub variant: u8, -} - -impl Default for Llama { - fn default() -> Self { - Self { - chested_horse: ChestedHorse::default(), - stength: 0, - carpet_color: -1, - variant: 0, - } - } -} - -#[derive(Default)] -#[inherit(Llama, ChestedHorse, AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] -pub struct TraderLlama { - pub llama: Llama, -} - - -#[derive(Default)] -#[inherit(Entity)] -pub struct LlamaSpit { - pub entity: Entity, -} diff --git a/minecraft-entities/src/animals/mod.rs b/minecraft-entities/src/animals/mod.rs index 53f385f5..2ae75b5d 100644 --- a/minecraft-entities/src/animals/mod.rs +++ b/minecraft-entities/src/animals/mod.rs @@ -4,10 +4,6 @@ mod sniffer; pub use sniffer::*; mod horses; pub use horses::*; -mod donkey; -pub use donkey::*; -mod llama; -pub use llama::*; mod axolotl; pub use axolotl::*; mod bee; @@ -46,21 +42,21 @@ mod parrot; pub use parrot::*; mod goat; pub use goat::*; -mod fishes; -pub use fishes::*; mod water_animal; pub use water_animal::*; #[derive(Default)] -#[inheritable] -#[inherit(AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + inheritable, parents { AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Animal { pub ageable_mob: AgeableMob, } #[derive(Default)] -#[inheritable] -#[inherit(Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + inheritable, parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct TameableAnimal { pub animal: Animal, pub action_mask: u8, diff --git a/minecraft-entities/src/animals/ocelot.rs b/minecraft-entities/src/animals/ocelot.rs index 8fdf3bfb..735d539a 100644 --- a/minecraft-entities/src/animals/ocelot.rs +++ b/minecraft-entities/src/animals/ocelot.rs @@ -2,7 +2,9 @@ use minecraft_protocol::packets::UUID; use super::*; #[derive(Default)] -#[inherit(Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Ocelot { pub animal: Animal, pub is_trusting: bool, diff --git a/minecraft-entities/src/animals/panda.rs b/minecraft-entities/src/animals/panda.rs index eaf8f55b..ca0ce7f2 100644 --- a/minecraft-entities/src/animals/panda.rs +++ b/minecraft-entities/src/animals/panda.rs @@ -2,7 +2,9 @@ use minecraft_protocol::packets::UUID; use super::*; #[derive(Default)] -#[inherit(Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Panda { pub animal: Animal, pub breed_timer: u16, diff --git a/minecraft-entities/src/animals/parrot.rs b/minecraft-entities/src/animals/parrot.rs index 86aebd5b..8bfc97da 100644 --- a/minecraft-entities/src/animals/parrot.rs +++ b/minecraft-entities/src/animals/parrot.rs @@ -1,7 +1,9 @@ use super::*; #[derive(Default)] -#[inherit(TameableAnimal, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { TameableAnimal, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Parrot { pub tameable_animal: TameableAnimal, pub variant: u8, diff --git a/minecraft-entities/src/animals/pig.rs b/minecraft-entities/src/animals/pig.rs index 2f209af3..15b373b2 100644 --- a/minecraft-entities/src/animals/pig.rs +++ b/minecraft-entities/src/animals/pig.rs @@ -1,7 +1,9 @@ use super::*; #[derive(Default)] -#[inherit(Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Pig { pub animal: Animal, pub has_saddle: bool, diff --git a/minecraft-entities/src/animals/polar_bear.rs b/minecraft-entities/src/animals/polar_bear.rs index 23c933d8..737428bc 100644 --- a/minecraft-entities/src/animals/polar_bear.rs +++ b/minecraft-entities/src/animals/polar_bear.rs @@ -1,7 +1,9 @@ use super::*; #[derive(Default)] -#[inherit(Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct PolarBear { pub animal: Animal, pub is_standing: bool, diff --git a/minecraft-entities/src/animals/rabbit.rs b/minecraft-entities/src/animals/rabbit.rs index 2d39d9c1..696cb18d 100644 --- a/minecraft-entities/src/animals/rabbit.rs +++ b/minecraft-entities/src/animals/rabbit.rs @@ -1,7 +1,9 @@ use super::*; #[derive(Default)] -#[inherit(Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Rabbit { pub animal: Animal, pub variant: u16, diff --git a/minecraft-entities/src/animals/sheep.rs b/minecraft-entities/src/animals/sheep.rs index ef16d152..537a17a9 100644 --- a/minecraft-entities/src/animals/sheep.rs +++ b/minecraft-entities/src/animals/sheep.rs @@ -1,8 +1,9 @@ use super::*; #[derive(Default)] -#[inheritable] -#[inherit(Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + inheritable, parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Sheep { pub animal: Animal, pub mask_style: u8, diff --git a/minecraft-entities/src/animals/sniffer.rs b/minecraft-entities/src/animals/sniffer.rs index e34235a0..77144da3 100644 --- a/minecraft-entities/src/animals/sniffer.rs +++ b/minecraft-entities/src/animals/sniffer.rs @@ -1,8 +1,9 @@ use super::*; #[derive(Default)] -#[inheritable] -#[inherit(Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Sniffer { pub animal: Animal, pub sniffer_state: u8, diff --git a/minecraft-entities/src/animals/strider.rs b/minecraft-entities/src/animals/strider.rs index 91f95a5c..0ed64600 100644 --- a/minecraft-entities/src/animals/strider.rs +++ b/minecraft-entities/src/animals/strider.rs @@ -1,8 +1,9 @@ use super::*; #[derive(Default)] -#[inheritable] -#[inherit(Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Strider { pub animal: Animal, pub boost_time: u16, diff --git a/minecraft-entities/src/animals/turtle.rs b/minecraft-entities/src/animals/turtle.rs index 75fb2028..b6554b06 100644 --- a/minecraft-entities/src/animals/turtle.rs +++ b/minecraft-entities/src/animals/turtle.rs @@ -1,7 +1,9 @@ use super::*; #[derive(Default)] -#[inherit(Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Turtle { pub animal: Animal, pub block_position: BlockPosition, diff --git a/minecraft-entities/src/animals/water_animal.rs b/minecraft-entities/src/animals/water_animal.rs index 22783dbe..676e521d 100644 --- a/minecraft-entities/src/animals/water_animal.rs +++ b/minecraft-entities/src/animals/water_animal.rs @@ -1,17 +1,71 @@ use super::*; #[derive(Default)] -#[inheritable] -#[inherit(PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + inheritable, parents { PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct WaterAnimal { pub pathfinder_mob: PathfinderMob, } #[derive(Default)] -#[inherit(WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Dolphin { pub water_animal: WaterAnimal, pub treasure_position: Option, pub has_fish: bool, pub moisture_level: usize, } + +#[derive(Default)] +#[MinecraftEntity( + inheritable, parents { WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, +)] +pub struct AbstractFish { + pub water_animal: WaterAnimal, + pub from_bucket: bool, +} + +#[derive(Default)] +#[MinecraftEntity( + parents { AbstractFish, WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, +)] +pub struct Cod { + pub abstract_fish: AbstractFish, +} + +#[derive(Default)] +#[MinecraftEntity( + parents { AbstractFish, WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, +)] +pub struct PufferFish { + pub abstract_fish: AbstractFish, + pub puff_state: usize, +} + +#[derive(Default)] +#[MinecraftEntity( + parents { AbstractFish, WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, +)] +pub struct Salmon { + pub abstract_fish: AbstractFish, +} + +#[derive(Default)] +#[MinecraftEntity( + parents { AbstractFish, WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, +)] +pub struct TropicalFish { + pub abstract_fish: AbstractFish, + pub variant: usize, +} + +#[derive(Default)] +#[MinecraftEntity( + parents { AbstractFish, WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, +)] +pub struct Tadpole { + pub abstract_fish: AbstractFish, +} diff --git a/minecraft-entities/src/arrow.rs b/minecraft-entities/src/arrow.rs index b3636c95..18d67460 100644 --- a/minecraft-entities/src/arrow.rs +++ b/minecraft-entities/src/arrow.rs @@ -1,7 +1,8 @@ use super::*; -#[inheritable] -#[inherit(Entity)] +#[MinecraftEntity( + inheritable, parents { Entity }, +)] pub struct AbstractArrow { pub entity: Entity, pub is_critical: bool, @@ -20,7 +21,9 @@ impl Default for AbstractArrow { } } -#[inherit(AbstractArrow, Entity)] +#[MinecraftEntity( + parents { AbstractArrow, Entity }, +)] pub struct Arrow { pub abstract_arrow: AbstractArrow, pub color: isize, @@ -35,7 +38,9 @@ impl Default for Arrow { } } -#[inherit(AbstractArrow, Entity)] +#[MinecraftEntity( + parents { AbstractArrow, Entity }, +)] pub struct SpectralArrow { pub abstract_arrow: AbstractArrow, pub loyalty_level: isize, @@ -52,7 +57,9 @@ impl Default for SpectralArrow { } } -#[inherit(AbstractArrow, Entity)] +#[MinecraftEntity( + parents { AbstractArrow, Entity }, +)] pub struct ThrownTrident { pub abstract_arrow: AbstractArrow, pub loyalty_level: isize, diff --git a/minecraft-entities/src/block.rs b/minecraft-entities/src/block.rs index 4be25b34..a097d7dd 100644 --- a/minecraft-entities/src/block.rs +++ b/minecraft-entities/src/block.rs @@ -1,7 +1,9 @@ use super::*; #[derive(Default)] -#[inherit(Entity)] +#[MinecraftEntity( + parents { Entity }, +)] pub struct FallingBlock { pub entity: Entity, pub spawn_position: BlockPosition, diff --git a/minecraft-entities/src/boat.rs b/minecraft-entities/src/boat.rs index 4cd33694..ce92a5f4 100644 --- a/minecraft-entities/src/boat.rs +++ b/minecraft-entities/src/boat.rs @@ -1,7 +1,8 @@ use super::*; -#[inheritable] -#[inherit(Entity)] +#[MinecraftEntity( + inheritable, parents { Entity }, +)] pub struct Boat { pub entity: Entity, pub time_since_last_hit: usize, @@ -30,7 +31,9 @@ impl Default for Boat { } #[derive(Default)] -#[inherit(Boat, Entity)] +#[MinecraftEntity( + parents { Boat, Entity }, +)] pub struct ChestBoat { pub boat: Boat, } diff --git a/minecraft-entities/src/display.rs b/minecraft-entities/src/display.rs index 12ee1515..f1450ada 100644 --- a/minecraft-entities/src/display.rs +++ b/minecraft-entities/src/display.rs @@ -1,8 +1,9 @@ use super::*; use minecraft_protocol::components::paintings::Painting as PaintingType; -#[inherit(Entity)] -#[inheritable] +#[MinecraftEntity( + inheritable, parents { Entity }, +)] pub struct Display { pub entity: Entity, pub interpolation_delay: u32, @@ -51,7 +52,9 @@ impl Default for Display { } } -#[inherit(Display, Entity)] +#[MinecraftEntity( + parents { Display, Entity }, +)] pub struct BlockDisplay { pub display: Display, pub block: BlockWithState, @@ -66,7 +69,9 @@ impl Default for BlockDisplay { } } -#[inherit(Display, Entity)] +#[MinecraftEntity( + parents { Display, Entity }, +)] pub struct ItemDisplay { pub display: Display, pub item: Slot, @@ -83,7 +88,9 @@ impl Default for ItemDisplay { } } -#[inherit(Display, Entity)] +#[MinecraftEntity( + parents { Display, Entity }, +)] pub struct TextDisplay { pub display: Display, pub text: String, @@ -113,7 +120,9 @@ impl Default for TextDisplay { } #[derive(Default)] -#[inherit(Entity)] +#[MinecraftEntity( + parents { Entity }, +)] pub struct Painting { pub entity: Entity, pub painting_type: PaintingType, diff --git a/minecraft-server/src/ecs/components/health.rs b/minecraft-entities/src/ecs/components/health.rs similarity index 100% rename from minecraft-server/src/ecs/components/health.rs rename to minecraft-entities/src/ecs/components/health.rs diff --git a/minecraft-server/src/ecs/components/mod.rs b/minecraft-entities/src/ecs/components/mod.rs similarity index 100% rename from minecraft-server/src/ecs/components/mod.rs rename to minecraft-entities/src/ecs/components/mod.rs diff --git a/minecraft-server/src/ecs/components/positions.rs b/minecraft-entities/src/ecs/components/positions.rs similarity index 100% rename from minecraft-server/src/ecs/components/positions.rs rename to minecraft-entities/src/ecs/components/positions.rs diff --git a/minecraft-server/src/ecs/entities.rs b/minecraft-entities/src/ecs/entities.rs similarity index 100% rename from minecraft-server/src/ecs/entities.rs rename to minecraft-entities/src/ecs/entities.rs diff --git a/minecraft-server/src/ecs/mod.rs b/minecraft-entities/src/ecs/mod.rs similarity index 100% rename from minecraft-server/src/ecs/mod.rs rename to minecraft-entities/src/ecs/mod.rs diff --git a/minecraft-server/src/ecs/tags.rs b/minecraft-entities/src/ecs/tags.rs similarity index 100% rename from minecraft-server/src/ecs/tags.rs rename to minecraft-entities/src/ecs/tags.rs diff --git a/minecraft-entities/src/entity.rs b/minecraft-entities/src/entity.rs index e9b62b43..8c1ee3bc 100644 --- a/minecraft-entities/src/entity.rs +++ b/minecraft-entities/src/entity.rs @@ -1,6 +1,8 @@ use super::*; -#[inheritable] +#[MinecraftEntity( + inheritable, parents {}, +)] pub struct Entity { pub position: Position, pub is_on_fire: bool, diff --git a/minecraft-entities/src/fire_entities.rs b/minecraft-entities/src/fire_entities.rs index 5525f929..eef22f51 100644 --- a/minecraft-entities/src/fire_entities.rs +++ b/minecraft-entities/src/fire_entities.rs @@ -1,27 +1,35 @@ use super::*; #[derive(Default)] -#[inherit(Entity)] +#[MinecraftEntity( + inheritable, parents { Entity }, +)] pub struct DragonFireball { pub entity: Entity, } #[derive(Default)] -#[inherit(Entity)] +#[MinecraftEntity( + inheritable, parents { Entity }, +)] pub struct SmallFireball { pub entity: Entity, pub item: Slot, } #[derive(Default)] -#[inherit(Entity)] +#[MinecraftEntity( + inheritable, parents { Entity }, +)] pub struct Fireball { pub entity: Entity, pub item: Slot, } #[derive(Default)] -#[inherit(Entity)] +#[MinecraftEntity( + inheritable, parents { Entity }, +)] pub struct FireworkRocket { pub entity: Entity, pub item: Slot, diff --git a/minecraft-entities/src/interaction.rs b/minecraft-entities/src/interaction.rs index 5ceaeaa9..c7e31469 100644 --- a/minecraft-entities/src/interaction.rs +++ b/minecraft-entities/src/interaction.rs @@ -1,6 +1,8 @@ use super::*; -#[inherit(Entity)] +#[MinecraftEntity( + parents { Entity }, +)] pub struct Interaction { pub entity: Entity, pub width: f32, diff --git a/minecraft-entities/src/item.rs b/minecraft-entities/src/item.rs index b80e3b29..86ce6fcd 100644 --- a/minecraft-entities/src/item.rs +++ b/minecraft-entities/src/item.rs @@ -1,8 +1,9 @@ use super::*; #[derive(Default)] -#[inheritable] -#[inherit(Entity)] +#[MinecraftEntity( + inheritable, parents { Entity }, +)] pub struct ItemFrame { pub entity: Entity, pub item: Slot, @@ -10,13 +11,17 @@ pub struct ItemFrame { } #[derive(Default)] -#[inherit(ItemFrame, Entity)] +#[MinecraftEntity( + parents { ItemFrame, Entity }, +)] pub struct GlowingItemFrame { pub item_frame: ItemFrame, } #[derive(Default)] -#[inherit(Entity)] +#[MinecraftEntity( + parents { Entity }, +)] pub struct ItemEntity { pub entity: Entity, pub item: Slot, diff --git a/minecraft-entities/src/lib.rs b/minecraft-entities/src/lib.rs index 97591a3f..eee3bcbd 100644 --- a/minecraft-entities/src/lib.rs +++ b/minecraft-entities/src/lib.rs @@ -33,8 +33,11 @@ pub use fire_entities::*; mod item; pub use item::*; +mod ecs; +pub use ecs::*; + pub(crate) use minecraft_positions::*; -pub(crate) use minecraft_entities_derive::{inherit, inheritable}; +pub(crate) use minecraft_entities_derive::MinecraftEntity; pub(crate) use minecraft_protocol::{ components::{ entity::Pose, @@ -47,6 +50,36 @@ pub(crate) use minecraft_protocol::{ pub type Eid = u32; + +use std::{pin::Pin, future::Future, sync::{Mutex, Arc}}; +type CallBack = fn(O) -> Pin>>; +type CallBack1 = fn(O, I) -> Pin>>; +type CallBack2 = fn(O, I, J) -> Pin>>; + +pub struct Handler { + uuid: UUID, + world: Arc>, + entity: std::marker::PhantomData, +} + +impl Handler { + fn assume(uuid: UUID, world: Arc>) -> Self { + Self { + uuid, + world, + entity: std::marker::PhantomData, + } + } + + fn assume_other(self) -> Handler { + Handler { + uuid: self.uuid, + world: self.world, + entity: std::marker::PhantomData, + } + } +} + pub enum AnyEntity { Entity(Entity), Display(Display), diff --git a/minecraft-entities/src/living_entity.rs b/minecraft-entities/src/living_entity.rs index 41cb45f8..2a9c68f9 100644 --- a/minecraft-entities/src/living_entity.rs +++ b/minecraft-entities/src/living_entity.rs @@ -1,7 +1,8 @@ use super::*; -#[inheritable] -#[inherit(Entity)] +#[MinecraftEntity( + inheritable, parents { Entity }, +)] pub struct LivingEntity { pub entity: Entity, pub is_hand_active: bool, @@ -32,7 +33,9 @@ impl Default for LivingEntity { } } -#[inherit(LivingEntity, Entity)] +#[MinecraftEntity( + parents { LivingEntity, Entity }, +)] pub struct ArmorStand { pub living_entity: LivingEntity, pub apparence_mask: u8, diff --git a/minecraft-entities/src/mobs/mod.rs b/minecraft-entities/src/mobs/mod.rs index a6c30697..1f8c758a 100644 --- a/minecraft-entities/src/mobs/mod.rs +++ b/minecraft-entities/src/mobs/mod.rs @@ -16,8 +16,9 @@ mod bat; pub use bat::*; #[derive(Default)] -#[inheritable] -#[inherit(LivingEntity, Entity)] +#[MinecraftEntity( + inheritable, parents { LivingEntity, Entity }, +)] pub struct Mob { pub living_entity: LivingEntity, pub no_ai: bool, @@ -26,22 +27,26 @@ pub struct Mob { } #[derive(Default)] -#[inheritable] -#[inherit(Mob, LivingEntity, Entity)] +#[MinecraftEntity( + inheritable, parents { Mob, LivingEntity, Entity }, +)] pub struct AmbientCreature { pub mob: Mob, } #[derive(Default)] -#[inheritable] -#[inherit(Mob, LivingEntity, Entity)] +#[MinecraftEntity( + inheritable, parents { Mob, LivingEntity, Entity }, +)] pub struct PathfinderMob { pub mob: Mob, } #[derive(Default)] -#[inheritable] -#[inherit(PathfinderMob, Mob, LivingEntity, Entity)] +#[derive(Default)] +#[MinecraftEntity( + inheritable, parents { PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct AgeableMob { pub pathfinder_mob: PathfinderMob, pub is_baby: bool, diff --git a/minecraft-entities/src/monsters/mod.rs b/minecraft-entities/src/monsters/mod.rs index b6e28897..6f83120b 100644 --- a/minecraft-entities/src/monsters/mod.rs +++ b/minecraft-entities/src/monsters/mod.rs @@ -40,8 +40,9 @@ mod enderman; pub use enderman::*; #[derive(Default)] -#[inheritable] -#[inherit(PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + inheritable, parents { PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Monster { pub pathfinder_mob: PathfinderMob, } diff --git a/minecraft-entities/src/particles.rs b/minecraft-entities/src/particles.rs index 479f1fbc..0cbc7095 100644 --- a/minecraft-entities/src/particles.rs +++ b/minecraft-entities/src/particles.rs @@ -1,8 +1,9 @@ use minecraft_protocol::components::particle::Particle; - use super::*; -#[inherit(Entity)] +#[MinecraftEntity( + parents { Entity }, +)] pub struct AreaEffectCloud { pub entity: Entity, pub radius: f32, @@ -24,7 +25,9 @@ impl Default for AreaEffectCloud { } #[derive(Default)] -#[inherit(Entity)] +#[MinecraftEntity( + parents { Entity }, +)] pub struct FishingHook{ pub entity: Entity, pub hooked_entity: Option, diff --git a/minecraft-entities/src/player.rs b/minecraft-entities/src/player.rs index fbd2b690..194895ea 100644 --- a/minecraft-entities/src/player.rs +++ b/minecraft-entities/src/player.rs @@ -1,6 +1,8 @@ use super::*; -#[inherit(LivingEntity, Entity)] +#[MinecraftEntity( + parents { LivingEntity, Entity }, +)] pub struct Player { pub living_entity: LivingEntity, pub additional_hearts: f32, diff --git a/minecraft-entities/src/shulker.rs b/minecraft-entities/src/shulker.rs index c26c56f4..6d69b5bf 100644 --- a/minecraft-entities/src/shulker.rs +++ b/minecraft-entities/src/shulker.rs @@ -1,7 +1,9 @@ use super::*; #[derive(Default)] -#[inherit(AbstractGolem, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { AbstractGolem, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Shulker { pub abstract_golem: AbstractGolem, pub attach_face: u8, diff --git a/minecraft-entities/src/thrown_item_projectile.rs b/minecraft-entities/src/thrown_item_projectile.rs index f45fb5b3..f62e6b34 100644 --- a/minecraft-entities/src/thrown_item_projectile.rs +++ b/minecraft-entities/src/thrown_item_projectile.rs @@ -1,7 +1,8 @@ use super::*; -#[inheritable] -#[inherit(Entity)] +#[MinecraftEntity( + inheritable, parents { LivingEntity, Entity }, +)] pub struct ThrownItemProjectile { pub entity: Entity, pub item: Slot, @@ -16,7 +17,9 @@ impl Default for ThrownItemProjectile { } } -#[inherit(ThrownItemProjectile, Entity)] +#[MinecraftEntity( + parents { ThrownItemProjectile, Entity }, +)] pub struct ThrownEgg { pub thrown_item_projectile: ThrownItemProjectile, } @@ -36,7 +39,9 @@ impl Default for ThrownEgg { } } -#[inherit(ThrownItemProjectile, Entity)] +#[MinecraftEntity( + parents { ThrownItemProjectile, Entity }, +)] pub struct ThrownEnderPearl { pub thrown_item_projectile: ThrownItemProjectile, } @@ -56,7 +61,9 @@ impl Default for ThrownEnderPearl { } } -#[inherit(ThrownItemProjectile, Entity)] +#[MinecraftEntity( + parents { ThrownItemProjectile, Entity }, +)] pub struct ThrownExperienceBottle { pub thrown_item_projectile: ThrownItemProjectile, } @@ -76,7 +83,9 @@ impl Default for ThrownExperienceBottle { } } -#[inherit(ThrownItemProjectile, Entity)] +#[MinecraftEntity( + parents { ThrownItemProjectile, Entity }, +)] pub struct ThrownPotion { pub thrown_item_projectile: ThrownItemProjectile, } @@ -96,7 +105,9 @@ impl Default for ThrownPotion { } } -#[inherit(ThrownItemProjectile, Entity)] +#[MinecraftEntity( + parents { ThrownItemProjectile, Entity }, +)] pub struct Snowball { pub thrown_item_projectile: ThrownItemProjectile, } @@ -117,7 +128,9 @@ impl Default for Snowball { } #[derive(Default)] -#[inherit(Entity)] +#[MinecraftEntity( + parents { Entity }, +)] pub struct EyeOfEnder { pub entity: Entity, pub item: Slot, From 0354f8321169bbefe3c56ea9437eb3be79523583 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Fri, 10 Nov 2023 14:21:40 +0100 Subject: [PATCH 26/89] Second half --- .../src/animals/water_animal.rs | 8 +++ minecraft-entities/src/animals/wolf.rs | 4 +- minecraft-entities/src/mobs/bat.rs | 4 +- minecraft-entities/src/mobs/ender_dragon.rs | 8 ++- minecraft-entities/src/mobs/flying.rs | 13 ++-- minecraft-entities/src/mobs/golems.rs | 14 ++-- minecraft-entities/src/mobs/mod.rs | 3 - minecraft-entities/src/mobs/slime.rs | 5 +- minecraft-entities/src/mobs/squid.rs | 7 -- minecraft-entities/src/mobs/villagers.rs | 13 ++-- .../src/monsters/base_piglin.rs | 7 -- minecraft-entities/src/monsters/blaze.rs | 4 +- minecraft-entities/src/monsters/creeper.rs | 4 +- minecraft-entities/src/monsters/enderman.rs | 4 +- minecraft-entities/src/monsters/endermite.rs | 4 +- minecraft-entities/src/monsters/giant.rs | 4 +- minecraft-entities/src/monsters/guardian.rs | 10 +-- minecraft-entities/src/monsters/mod.rs | 2 - minecraft-entities/src/monsters/piglin.rs | 17 ++++- minecraft-entities/src/monsters/raider.rs | 68 +++++++++++++++++-- minecraft-entities/src/monsters/silverfish.rs | 4 +- minecraft-entities/src/monsters/skeleton.rs | 24 +++---- .../src/monsters/spellcaster_illager.rs | 33 --------- minecraft-entities/src/monsters/spider.rs | 4 +- minecraft-entities/src/monsters/vex.rs | 4 +- minecraft-entities/src/monsters/warden.rs | 4 +- minecraft-entities/src/monsters/witch.rs | 6 -- minecraft-entities/src/monsters/wither.rs | 13 +++- minecraft-entities/src/monsters/zoglin.rs | 4 +- minecraft-entities/src/monsters/zombies.rs | 21 ++++-- .../src/thrown_item_projectile.rs | 2 +- 31 files changed, 203 insertions(+), 119 deletions(-) delete mode 100644 minecraft-entities/src/mobs/squid.rs delete mode 100644 minecraft-entities/src/monsters/spellcaster_illager.rs diff --git a/minecraft-entities/src/animals/water_animal.rs b/minecraft-entities/src/animals/water_animal.rs index 676e521d..905700f5 100644 --- a/minecraft-entities/src/animals/water_animal.rs +++ b/minecraft-entities/src/animals/water_animal.rs @@ -19,6 +19,14 @@ pub struct Dolphin { pub moisture_level: usize, } +#[derive(Default)] +#[MinecraftEntity( + parents { WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, +)] +pub struct Squid { + pub water_animal: WaterAnimal, +} + #[derive(Default)] #[MinecraftEntity( inheritable, parents { WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, diff --git a/minecraft-entities/src/animals/wolf.rs b/minecraft-entities/src/animals/wolf.rs index 9fc0a3a4..c920068c 100644 --- a/minecraft-entities/src/animals/wolf.rs +++ b/minecraft-entities/src/animals/wolf.rs @@ -1,6 +1,8 @@ use super::*; -#[inherit(TameableAnimal, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { TameableAnimal, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Wolf { pub tameable_animal: TameableAnimal, pub is_begging: bool, diff --git a/minecraft-entities/src/mobs/bat.rs b/minecraft-entities/src/mobs/bat.rs index bb16f7e7..5e852840 100644 --- a/minecraft-entities/src/mobs/bat.rs +++ b/minecraft-entities/src/mobs/bat.rs @@ -1,7 +1,9 @@ use super::*; #[derive(Default)] -#[inherit(AmbientCreature, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { AmbientCreature, Mob, LivingEntity, Entity }, +)] pub struct Bat { pub ambient_creature: AmbientCreature, pub is_hanging: bool, diff --git a/minecraft-entities/src/mobs/ender_dragon.rs b/minecraft-entities/src/mobs/ender_dragon.rs index 73163c98..bc8f3121 100644 --- a/minecraft-entities/src/mobs/ender_dragon.rs +++ b/minecraft-entities/src/mobs/ender_dragon.rs @@ -1,6 +1,8 @@ use super::*; -#[inherit(Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Mob, LivingEntity, Entity }, +)] pub struct EnderDragon { pub mob: Mob, pub phase: usize, @@ -15,7 +17,9 @@ impl Default for EnderDragon { } } -#[inherit(Entity)] +#[MinecraftEntity( + parents { Entity }, +)] pub struct EndCrystal { pub entity: Entity, pub block_position: Option, diff --git a/minecraft-entities/src/mobs/flying.rs b/minecraft-entities/src/mobs/flying.rs index 5d72ef48..7983cf1b 100644 --- a/minecraft-entities/src/mobs/flying.rs +++ b/minecraft-entities/src/mobs/flying.rs @@ -1,21 +1,26 @@ use super::*; #[derive(Default)] -#[inheritable] -#[inherit(Mob, LivingEntity, Entity)] +#[MinecraftEntity( + inheritable, parents { Mob, LivingEntity, Entity }, +)] pub struct Flying { pub mob: Mob, } #[derive(Default)] -#[inherit(Flying, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Flying, Mob, LivingEntity, Entity }, +)] pub struct Ghast { pub flying: Flying, pub is_attacking: bool, } #[derive(Default)] -#[inherit(Flying, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Flying, Mob, LivingEntity, Entity }, +)] pub struct Phantom { pub flying: Flying, pub size: usize, diff --git a/minecraft-entities/src/mobs/golems.rs b/minecraft-entities/src/mobs/golems.rs index cd2b3934..229c561b 100644 --- a/minecraft-entities/src/mobs/golems.rs +++ b/minecraft-entities/src/mobs/golems.rs @@ -1,23 +1,27 @@ use super::*; #[derive(Default)] -#[inheritable] -#[inherit(PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + inheritable, parents { PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct AbstractGolem { pub pathfinder_mob: PathfinderMob, } #[derive(Default)] -#[inherit(AbstractGolem, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { AbstractGolem, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct IronGolem { pub abstract_golem: AbstractGolem, pub is_player_created: bool, } #[derive(Default)] -#[inherit(AbstractGolem, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { AbstractGolem, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct SnowGolem { pub abstract_golem: AbstractGolem, pub has_pumpkin_hat: bool, } - diff --git a/minecraft-entities/src/mobs/mod.rs b/minecraft-entities/src/mobs/mod.rs index 1f8c758a..96e425de 100644 --- a/minecraft-entities/src/mobs/mod.rs +++ b/minecraft-entities/src/mobs/mod.rs @@ -1,7 +1,5 @@ use super::*; -mod squid; -pub use squid::*; mod villagers; pub use villagers::*; mod golems; @@ -42,7 +40,6 @@ pub struct PathfinderMob { pub mob: Mob, } -#[derive(Default)] #[derive(Default)] #[MinecraftEntity( inheritable, parents { PathfinderMob, Mob, LivingEntity, Entity }, diff --git a/minecraft-entities/src/mobs/slime.rs b/minecraft-entities/src/mobs/slime.rs index 6fadb29b..5ce9839e 100644 --- a/minecraft-entities/src/mobs/slime.rs +++ b/minecraft-entities/src/mobs/slime.rs @@ -1,8 +1,9 @@ use super::*; #[derive(Default)] -#[inheritable] -#[inherit(Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Mob, LivingEntity, Entity }, +)] pub struct Slime { pub mob: Mob, pub size: usize, diff --git a/minecraft-entities/src/mobs/squid.rs b/minecraft-entities/src/mobs/squid.rs deleted file mode 100644 index 2afeb889..00000000 --- a/minecraft-entities/src/mobs/squid.rs +++ /dev/null @@ -1,7 +0,0 @@ -use super::*; - -#[derive(Default)] -#[inherit(WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity)] -pub struct Squid { - pub water_animal: WaterAnimal, -} diff --git a/minecraft-entities/src/mobs/villagers.rs b/minecraft-entities/src/mobs/villagers.rs index 696971f4..9f856a5a 100644 --- a/minecraft-entities/src/mobs/villagers.rs +++ b/minecraft-entities/src/mobs/villagers.rs @@ -1,22 +1,27 @@ use super::*; #[derive(Default)] -#[inheritable] -#[inherit(AgeableMob, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + inheritable, parents { AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct AbstractVillager { pub ageable_mob: AgeableMob, pub head_shake_timer: u32, } #[derive(Default)] -#[inherit(AbstractVillager, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { AbstractVillager, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Villager { pub abstract_villager: AbstractVillager, pub villager_data: Vec, } #[derive(Default)] -#[inherit(AbstractVillager, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { AbstractVillager, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct WanderingTrader { pub abstract_villager: AbstractVillager, } diff --git a/minecraft-entities/src/monsters/base_piglin.rs b/minecraft-entities/src/monsters/base_piglin.rs index b72ef2e7..c5d584ae 100644 --- a/minecraft-entities/src/monsters/base_piglin.rs +++ b/minecraft-entities/src/monsters/base_piglin.rs @@ -1,9 +1,2 @@ use super::*; -#[derive(Default)] -#[inheritable] -#[inherit(Monster, PathfinderMob, Mob, LivingEntity, Entity)] -pub struct BasePiglin { - pub monster: Monster, - pub is_immune: bool, -} diff --git a/minecraft-entities/src/monsters/blaze.rs b/minecraft-entities/src/monsters/blaze.rs index 94b9a585..edd5d3c6 100644 --- a/minecraft-entities/src/monsters/blaze.rs +++ b/minecraft-entities/src/monsters/blaze.rs @@ -1,7 +1,9 @@ use super::*; #[derive(Default)] -#[inherit(Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Blaze { pub monster: Monster, pub is_on_fire: bool, diff --git a/minecraft-entities/src/monsters/creeper.rs b/minecraft-entities/src/monsters/creeper.rs index f9ef9f1a..2eea2131 100644 --- a/minecraft-entities/src/monsters/creeper.rs +++ b/minecraft-entities/src/monsters/creeper.rs @@ -1,6 +1,8 @@ use super::*; -#[inherit(Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Creeper { pub monster: Monster, pub state: i8, diff --git a/minecraft-entities/src/monsters/enderman.rs b/minecraft-entities/src/monsters/enderman.rs index c14ecdb3..1432a5ad 100644 --- a/minecraft-entities/src/monsters/enderman.rs +++ b/minecraft-entities/src/monsters/enderman.rs @@ -2,7 +2,9 @@ use minecraft_protocol::ids::blocks::Block; use super::*; -#[inherit(Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Enderman { pub monster: Monster, pub block_id: Option, diff --git a/minecraft-entities/src/monsters/endermite.rs b/minecraft-entities/src/monsters/endermite.rs index b5da89cc..82317fce 100644 --- a/minecraft-entities/src/monsters/endermite.rs +++ b/minecraft-entities/src/monsters/endermite.rs @@ -1,7 +1,9 @@ use super::*; #[derive(Default)] -#[inherit(Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Endermite { pub monster: Monster, } diff --git a/minecraft-entities/src/monsters/giant.rs b/minecraft-entities/src/monsters/giant.rs index f773f6a1..60c4bbbf 100644 --- a/minecraft-entities/src/monsters/giant.rs +++ b/minecraft-entities/src/monsters/giant.rs @@ -1,7 +1,9 @@ use super::*; #[derive(Default)] -#[inherit(Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Giant { pub monster: Monster, } diff --git a/minecraft-entities/src/monsters/guardian.rs b/minecraft-entities/src/monsters/guardian.rs index f408a98f..b5503551 100644 --- a/minecraft-entities/src/monsters/guardian.rs +++ b/minecraft-entities/src/monsters/guardian.rs @@ -1,8 +1,9 @@ use super::*; #[derive(Default)] -#[inheritable] -#[inherit(Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + inheritable, parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Guardian { pub monster: Monster, pub is_retracting_spikes: bool, @@ -10,8 +11,9 @@ pub struct Guardian { } #[derive(Default)] -#[inheritable] -#[inherit(Guardian, Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Guardian, Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct ElderGuardian { pub guardian: Guardian, } diff --git a/minecraft-entities/src/monsters/mod.rs b/minecraft-entities/src/monsters/mod.rs index 6f83120b..9a0ea762 100644 --- a/minecraft-entities/src/monsters/mod.rs +++ b/minecraft-entities/src/monsters/mod.rs @@ -18,8 +18,6 @@ mod silverfish; pub use silverfish::*; mod raider; pub use raider::*; -mod spellcaster_illager; -pub use spellcaster_illager::*; mod witch; pub use witch::*; mod vex; diff --git a/minecraft-entities/src/monsters/piglin.rs b/minecraft-entities/src/monsters/piglin.rs index b5e97192..91f407b5 100644 --- a/minecraft-entities/src/monsters/piglin.rs +++ b/minecraft-entities/src/monsters/piglin.rs @@ -1,7 +1,18 @@ use super::*; #[derive(Default)] -#[inherit(BasePiglin, Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + inheritable, parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] +pub struct BasePiglin { + pub monster: Monster, + pub is_immune: bool, +} + +#[derive(Default)] +#[MinecraftEntity( + parents { BasePiglin, Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Piglin { pub base_piglin: BasePiglin, pub is_baby: bool, @@ -10,7 +21,9 @@ pub struct Piglin { } #[derive(Default)] -#[inherit(BasePiglin, Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { BasePiglin, Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct PiglinBrute { pub base_piglin: BasePiglin, } diff --git a/minecraft-entities/src/monsters/raider.rs b/minecraft-entities/src/monsters/raider.rs index 6999f62a..33e19fbd 100644 --- a/minecraft-entities/src/monsters/raider.rs +++ b/minecraft-entities/src/monsters/raider.rs @@ -1,29 +1,85 @@ use super::*; #[derive(Default)] -#[inheritable] -#[inherit(Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + inheritable, parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Raider { pub monster: Monster, pub is_celebrating: bool, } #[derive(Default)] -#[inheritable] -#[inherit(Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] +pub struct Witch { + pub raider: Raider, + pub is_drinking_potion: bool, +} + +#[derive(Default)] +#[MinecraftEntity( + inheritable, parents { Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct AbstractIllager { pub raider: Raider, } #[derive(Default)] -#[inherit(AbstractIllager, Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { AbstractIllager, Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Vindicator { pub abstract_illager: AbstractIllager, } #[derive(Default)] -#[inherit(AbstractIllager, Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { AbstractIllager, Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Pillager { pub abstract_illager: AbstractIllager, pub is_charging: bool, } + +#[derive(Default)] +#[MinecraftEntity( + inheritable, parents { AbstractIllager, Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] +pub struct SpellcasterIllager { + pub abstract_illager: AbstractIllager, + pub spell: u8, +} + +#[derive(Default)] +#[MinecraftEntity( + parents { SpellcasterIllager, AbstractIllager, Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] +pub struct Illusioner { + pub spellcaster_illager: SpellcasterIllager, +} + +#[derive(Default)] +#[MinecraftEntity( + parents { SpellcasterIllager, AbstractIllager, Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] +pub struct Ravager { + pub spellcaster_illager: SpellcasterIllager, +} + +#[derive(Default)] +#[MinecraftEntity( + parents { SpellcasterIllager, AbstractIllager, Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] +pub struct Evoker { + pub spellcaster_illager: SpellcasterIllager, +} + +#[derive(Default)] +#[MinecraftEntity( + parents { Entity }, +)] +pub struct EvokerFangs { + pub entity: Entity, +} diff --git a/minecraft-entities/src/monsters/silverfish.rs b/minecraft-entities/src/monsters/silverfish.rs index 59be1aec..dd2dfdf5 100644 --- a/minecraft-entities/src/monsters/silverfish.rs +++ b/minecraft-entities/src/monsters/silverfish.rs @@ -1,7 +1,9 @@ use super::*; #[derive(Default)] -#[inherit(Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Silverfish { pub monster: Monster, } diff --git a/minecraft-entities/src/monsters/skeleton.rs b/minecraft-entities/src/monsters/skeleton.rs index c9acc7d9..13792990 100644 --- a/minecraft-entities/src/monsters/skeleton.rs +++ b/minecraft-entities/src/monsters/skeleton.rs @@ -1,33 +1,33 @@ use super::*; #[derive(Default)] -#[inheritable] -#[inherit(Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + inheritable, parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct AbstractSkeleton { pub monster: Monster, } #[derive(Default)] -#[inherit(AbstractSkeleton, Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { AbstractSkeleton, Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Skeleton { pub abstract_skeleton: AbstractSkeleton, } #[derive(Default)] -#[inherit(AbstractSkeleton, Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { AbstractSkeleton, Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct WitherSkeleton { pub abstract_skeleton: AbstractSkeleton, } #[derive(Default)] -#[inherit(AbstractSkeleton, Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { AbstractSkeleton, Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Stray { pub abstract_skeleton: AbstractSkeleton, } - -#[derive(Default)] -#[inherit(Entity)] -pub struct WitherSkull { - pub entity: Entity, - pub is_invulnerable: bool, -} diff --git a/minecraft-entities/src/monsters/spellcaster_illager.rs b/minecraft-entities/src/monsters/spellcaster_illager.rs deleted file mode 100644 index b04aba35..00000000 --- a/minecraft-entities/src/monsters/spellcaster_illager.rs +++ /dev/null @@ -1,33 +0,0 @@ -use super::*; - -#[derive(Default)] -#[inheritable] -#[inherit(AbstractIllager, Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity)] -pub struct SpellcasterIllager { - pub abstract_illager: AbstractIllager, - pub spell: u8, -} - -#[derive(Default)] -#[inherit(SpellcasterIllager, AbstractIllager, Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity)] -pub struct Evoker { - pub spellcaster_illager: SpellcasterIllager, -} - -#[derive(Default)] -#[inherit(Entity)] -pub struct EvokerFangs { - pub entity: Entity, -} - -#[derive(Default)] -#[inherit(SpellcasterIllager, AbstractIllager, Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity)] -pub struct Illusioner { - pub spellcaster_illager: SpellcasterIllager, -} - -#[derive(Default)] -#[inherit(SpellcasterIllager, AbstractIllager, Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity)] -pub struct Ravager { - pub spellcaster_illager: SpellcasterIllager, -} diff --git a/minecraft-entities/src/monsters/spider.rs b/minecraft-entities/src/monsters/spider.rs index f77f5f11..4f6d0b01 100644 --- a/minecraft-entities/src/monsters/spider.rs +++ b/minecraft-entities/src/monsters/spider.rs @@ -1,6 +1,8 @@ use super::*; -#[inherit(Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Spider { pub monster: Monster, pub is_climbing_mask: u8, diff --git a/minecraft-entities/src/monsters/vex.rs b/minecraft-entities/src/monsters/vex.rs index f8f63b08..883c6290 100644 --- a/minecraft-entities/src/monsters/vex.rs +++ b/minecraft-entities/src/monsters/vex.rs @@ -1,7 +1,9 @@ use super::*; #[derive(Default)] -#[inherit(Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Vex { pub monster: Monster, } diff --git a/minecraft-entities/src/monsters/warden.rs b/minecraft-entities/src/monsters/warden.rs index ad99afaa..b6b29629 100644 --- a/minecraft-entities/src/monsters/warden.rs +++ b/minecraft-entities/src/monsters/warden.rs @@ -1,7 +1,9 @@ use super::*; #[derive(Default)] -#[inherit(Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Warden { pub monster: Monster, pub anger_level: usize, diff --git a/minecraft-entities/src/monsters/witch.rs b/minecraft-entities/src/monsters/witch.rs index 9b3d2076..c5d584ae 100644 --- a/minecraft-entities/src/monsters/witch.rs +++ b/minecraft-entities/src/monsters/witch.rs @@ -1,8 +1,2 @@ use super::*; -#[derive(Default)] -#[inherit(Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity)] -pub struct Witch { - pub raider: Raider, - pub is_drinking_potion: bool, -} diff --git a/minecraft-entities/src/monsters/wither.rs b/minecraft-entities/src/monsters/wither.rs index 89c219ae..6e8fbe3e 100644 --- a/minecraft-entities/src/monsters/wither.rs +++ b/minecraft-entities/src/monsters/wither.rs @@ -1,6 +1,8 @@ use super::*; -#[inherit(Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Wither { pub monster: Monster, pub center_head_target: Option, @@ -8,3 +10,12 @@ pub struct Wither { pub right_head: Option, pub invulnerable_time: usize, } + +#[derive(Default)] +#[MinecraftEntity( + parents { Entity }, +)] +pub struct WitherSkull { + pub entity: Entity, + pub is_invulnerable: bool, +} diff --git a/minecraft-entities/src/monsters/zoglin.rs b/minecraft-entities/src/monsters/zoglin.rs index a59b7365..0a85aabd 100644 --- a/minecraft-entities/src/monsters/zoglin.rs +++ b/minecraft-entities/src/monsters/zoglin.rs @@ -1,7 +1,9 @@ use super::*; #[derive(Default)] -#[inherit(Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Zoglin { pub monster: Monster, pub is_baby: bool, diff --git a/minecraft-entities/src/monsters/zombies.rs b/minecraft-entities/src/monsters/zombies.rs index b8153662..61f7c6d0 100644 --- a/minecraft-entities/src/monsters/zombies.rs +++ b/minecraft-entities/src/monsters/zombies.rs @@ -1,8 +1,9 @@ use super::*; #[derive(Default)] -#[inheritable] -#[inherit(Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + inheritable, parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Zombie { pub monster: Monster, pub is_baby: bool, @@ -11,7 +12,9 @@ pub struct Zombie { } #[derive(Default)] -#[inherit(Zombie, Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Zombie, Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct ZombieVillager { pub zombie: Zombie, pub is_converting: bool, @@ -19,19 +22,25 @@ pub struct ZombieVillager { } #[derive(Default)] -#[inherit(Zombie, Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Zombie, Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Husk { pub zombie: Zombie, } #[derive(Default)] -#[inherit(Zombie, Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Zombie, Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct Drowned { pub zombie: Zombie, } #[derive(Default)] -#[inherit(Zombie, Monster, PathfinderMob, Mob, LivingEntity, Entity)] +#[MinecraftEntity( + parents { Zombie, Monster, PathfinderMob, Mob, LivingEntity, Entity }, +)] pub struct ZombifiedPiglin { pub zombie: Zombie, } diff --git a/minecraft-entities/src/thrown_item_projectile.rs b/minecraft-entities/src/thrown_item_projectile.rs index f62e6b34..7ab40c85 100644 --- a/minecraft-entities/src/thrown_item_projectile.rs +++ b/minecraft-entities/src/thrown_item_projectile.rs @@ -1,7 +1,7 @@ use super::*; #[MinecraftEntity( - inheritable, parents { LivingEntity, Entity }, + inheritable, parents { Entity }, )] pub struct ThrownItemProjectile { pub entity: Entity, From ef8409171fb36812e31add60be2dc07a1f7012d5 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Fri, 10 Nov 2023 14:31:07 +0100 Subject: [PATCH 27/89] Fix ECS --- Cargo.toml | 3 +- .../src/{ecs/entities.rs => ecs.rs} | 5 +- .../src/ecs/components/health.rs | 51 ------- minecraft-entities/src/ecs/components/mod.rs | 13 -- .../src/ecs/components/positions.rs | 69 --------- minecraft-entities/src/ecs/mod.rs | 7 - minecraft-entities/src/ecs/tags.rs | 12 -- minecraft-server/Cargo.toml | 1 - tags-macros/Cargo.toml | 12 -- tags-macros/src/lib.rs | 136 ------------------ 10 files changed, 4 insertions(+), 305 deletions(-) rename minecraft-entities/src/{ecs/entities.rs => ecs.rs} (95%) delete mode 100644 minecraft-entities/src/ecs/components/health.rs delete mode 100644 minecraft-entities/src/ecs/components/mod.rs delete mode 100644 minecraft-entities/src/ecs/components/positions.rs delete mode 100644 minecraft-entities/src/ecs/mod.rs delete mode 100644 minecraft-entities/src/ecs/tags.rs delete mode 100644 tags-macros/Cargo.toml delete mode 100644 tags-macros/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index b92aa048..6181c714 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,8 +5,7 @@ members = [ "minecraft-server", "minecraft-entities", "minecraft-entities-derive", - "minecraft-positions", - "tags-macros" + "minecraft-positions" ] workspace.resolver = "2" diff --git a/minecraft-entities/src/ecs/entities.rs b/minecraft-entities/src/ecs.rs similarity index 95% rename from minecraft-entities/src/ecs/entities.rs rename to minecraft-entities/src/ecs.rs index c71c6447..b0d1c482 100644 --- a/minecraft-entities/src/ecs/entities.rs +++ b/minecraft-entities/src/ecs.rs @@ -1,6 +1,7 @@ -use crate::{prelude::*, entities::AnyEntity}; +use std::collections::{HashMap, HashSet}; +use crate::*; use minecraft_protocol::packets::UUID; -use super::tags::Tag; +use tokio::sync::RwLock; pub struct Entities { pub entities: RwLock>, diff --git a/minecraft-entities/src/ecs/components/health.rs b/minecraft-entities/src/ecs/components/health.rs deleted file mode 100644 index fc7fb617..00000000 --- a/minecraft-entities/src/ecs/components/health.rs +++ /dev/null @@ -1,51 +0,0 @@ -use crate::prelude::*; - -#[derive(Clone)] -pub struct HealthComponent { - pub health: f32, - pub max_health: f32, -} - -impl HealthComponent { - /// Returns true if the entity is dead.s - pub async fn is_dead(&self) -> bool { - self.health <= 0.0 - } - - pub async fn get_health(&self) -> f32{ - self.health - } - - /// Heals the entity by the given amount. - pub async fn heal(&mut self, amount: f32) { - self.health = (self.health + amount).min(self.max_health); - } - - /// Fully heals the entity. - pub async fn full_heal(&mut self) { - self.health = self.max_health; - } - - /// Damages the entity by the given amount. - pub async fn damage(&mut self, amount: f32) -> Option<()> { - self.health -= amount; - self.health = self.health.max(0.0); - Some(()) - } -} - -impl Entities { - /// Set the health of an entity. - pub async fn set_health(&self, id: Eid, health: HealthComponent) -> Option<()> { - //let mut health_components = self.health_components.write().await; - //health_components.insert(id, health); - //Some(()) - unimplemented!() - } - - /// Get the health of an entity. - pub async fn get_health(&self, id: Eid) -> Option { - //self.health_components.read().await.get(&id).cloned() - unimplemented!() - } -} diff --git a/minecraft-entities/src/ecs/components/mod.rs b/minecraft-entities/src/ecs/components/mod.rs deleted file mode 100644 index d26fd92f..00000000 --- a/minecraft-entities/src/ecs/components/mod.rs +++ /dev/null @@ -1,13 +0,0 @@ -pub use super::*; - -pub mod health; -pub mod positions; - -pub use health::HealthComponent; -pub use positions::PositionComponent; - -#[derive(Clone, Eq, Hash, PartialEq)] -pub enum Component { - Health, - Position, -} diff --git a/minecraft-entities/src/ecs/components/positions.rs b/minecraft-entities/src/ecs/components/positions.rs deleted file mode 100644 index 17a377eb..00000000 --- a/minecraft-entities/src/ecs/components/positions.rs +++ /dev/null @@ -1,69 +0,0 @@ -use std::ops::{Deref, DerefMut}; - -use crate::prelude::*; - -#[derive(Clone)] -pub struct PositionComponent { - position: Position, -} - -impl Entities { - pub async fn get_position(&self, id: Eid) -> Option { - // we don't check if the entity has a position component because the hashmap will return None if the entity doesn't have it - //self.position_components.read().await.get(&id).cloned() - unimplemented!() - } - - pub async fn set_position(&self, id: Eid, position: PositionComponent) -> Option<()> { -// let new_chunk = position.get_chunk(); -// let mut position_components = self.position_components.write().await; -// let old_chunk = position_components.get(&id).cloned(); -// -// // Update the position component -// let pos = position_components.get_mut(&id)?; -// *pos = position; -// drop(position_components); -// -// if let Some(old_chunk) = old_chunk { -// let old_chunk = old_chunk.get_chunk(); -// if old_chunk != new_chunk { -// // Remove the entity from the old chunk -// let mut chunks = self.chunks.write().await; -// let old_chunk_entities = chunks.get_mut(&old_chunk)?; -// old_chunk_entities.remove(&id); -// -// // Add the entity to the new chunk -// let new_chunk_entities = chunks.get_mut(&new_chunk)?; -// new_chunk_entities.insert(id); -// -// } -// } else { -// // Add the entity to the new chunk -// let mut chunks = self.chunks.write().await; -// let new_chunk_entities = chunks.get_mut(&new_chunk)?; -// new_chunk_entities.insert(id); -// } -// -// Some(()) - unimplemented!() - } -} - -impl PositionComponent { - pub async fn set_position(&mut self, position: Position) -> Option<()> { - self.position = position; - Some(()) - } - - pub fn get_position(&self) -> Position { - self.position.clone() - } - - pub fn move_entity(&mut self, delta: Position) { - self.position += delta; - } - - pub fn get_chunk(&self) -> ChunkPosition { - self.position.chunk() - } -} diff --git a/minecraft-entities/src/ecs/mod.rs b/minecraft-entities/src/ecs/mod.rs deleted file mode 100644 index 1ea05e63..00000000 --- a/minecraft-entities/src/ecs/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub mod entities; -pub mod tags; -pub mod components; - -pub use entities::*; -pub use tags::*; -pub use components::*; diff --git a/minecraft-entities/src/ecs/tags.rs b/minecraft-entities/src/ecs/tags.rs deleted file mode 100644 index 5cf8afb6..00000000 --- a/minecraft-entities/src/ecs/tags.rs +++ /dev/null @@ -1,12 +0,0 @@ -use crate::ecs::components::*; -use tags_macros::tags; - -tags! { - Player { - Position, - Health, - } - Enemy { - Health - } -} diff --git a/minecraft-server/Cargo.toml b/minecraft-server/Cargo.toml index 4a329bf8..c2526501 100644 --- a/minecraft-server/Cargo.toml +++ b/minecraft-server/Cargo.toml @@ -13,5 +13,4 @@ futures = "0.3.29" minecraft-protocol = { path="../minecraft-protocol" } minecraft-entities = { path="../minecraft-entities" } minecraft-positions = { path="../minecraft-positions" } -tags-macros = { path = "../tags-macros"} rand = "0.8.4" diff --git a/tags-macros/Cargo.toml b/tags-macros/Cargo.toml deleted file mode 100644 index a35c9fac..00000000 --- a/tags-macros/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "tags-macros" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -[lib] -proc-macro = true - -[dependencies] -quote = "1.0" -syn = { version = "2.0", features = ["full"] } diff --git a/tags-macros/src/lib.rs b/tags-macros/src/lib.rs deleted file mode 100644 index 40e32b6a..00000000 --- a/tags-macros/src/lib.rs +++ /dev/null @@ -1,136 +0,0 @@ -#[macro_use] -extern crate quote; -extern crate proc_macro; - -use std::collections::HashMap; - -use proc_macro::TokenStream; -use syn::{parse_macro_input, Token, Ident, parse}; - -struct MultipleTags { - tags: Vec<(Ident, Vec)>, - components: HashMap>, -} - -impl parse::Parse for MultipleTags { - fn parse(input: syn::parse::ParseStream) -> parse::Result { - let mut tags = Vec::new(); - let mut components_table: HashMap> = HashMap::new(); - while !input.is_empty() { - let tag_name: Ident = input.parse()?; - let content; - syn::braced!(content in input); - - let components = content - .parse_terminated(Ident::parse, Token![,])?; - for component in components.iter() { - // We add the tag to the component - let tags_of_component = components_table.get_mut(component); - if let Some(tags_of_component) = tags_of_component { - tags_of_component.push(tag_name.clone()); - } else { - components_table.insert(component.clone(), vec![tag_name.clone()]); - } - } - tags.push((tag_name, components.into_iter().collect())); - } - - Ok(Self { tags, components: components_table }) - } -} - - -#[proc_macro] -pub fn tags(input: TokenStream) -> TokenStream { - /* - We have something like that: - tags! { - Player { - HealthComponent, - PositionComponent, - } - } - */ - let items = parse_macro_input!(input as MultipleTags); - - let tags = items.tags.iter().map(|t| t.0.clone()); - - // We write an enum with all tags - let mut output = quote! { - use std::collections::HashSet; - - /// All tags in the game - #[derive(Clone, PartialEq, Eq, Hash)] - pub enum Tag { - #( - #tags, - )* - } - - }; - - let tags_with_components = items.components; - let match_patterns = tags_with_components.iter().map(|(component, tags)| { - let tags = tags.iter().map(|t| { - let tag = Ident::new(&format!("{}", t), t.span()); - quote! { - Tag::#tag - } - }); - let component = Ident::new(&format!("{}", component), component.span()); - quote! { - Component::#component => vec![#(#tags),*], - } - }); - let map_tag_components = items.tags; - let map_tag_components = map_tag_components.iter().map(|(tag, components)| { - let tag = Ident::new(&format!("{}", tag), tag.span()); - let components = components.iter().map(|c| { - let component = Ident::new(&format!("{}", c), c.span()); - quote! { - Component::#component - } - }); - quote! { - Tag::#tag => vec![#(#components),*], - } - }); - // We write a function to get all tags from components - let get_tags_from_components = quote! { - impl Tag { - /// we get all components from a tag - pub fn get_components(&self) -> Vec { - match self { - #(#map_tag_components)* - } - } - - /// we get all tags from a component - pub fn get_tags_from_component(component: Component) -> Vec { - match component { - #(#match_patterns)* - _ => vec![], - } - } - - /// we get all tags that have the components - pub fn get_tags_from_components(components: HashSet) -> HashSet { - let mut tags = HashSet::new(); - for component in components.iter() { - for tag in Tag::get_tags_from_component(component.clone()) { - let components_of_tag = tag.get_components(); - if components_of_tag.iter().all(|c| components.contains(c)) { - tags.insert(tag); - } - } - } - tags - } - } - }; - - - output.extend(get_tags_from_components); - - output.into() -} From 7bbebc50c59364fc4a1693de99fe0ff67e07e3a3 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Fri, 10 Nov 2023 15:51:51 +0100 Subject: [PATCH 28/89] Start Implementing observer --- minecraft-entities/src/lib.rs | 40 ++++++++++++++----- .../src/ecs.rs | 0 2 files changed, 29 insertions(+), 11 deletions(-) rename {minecraft-entities => minecraft-server}/src/ecs.rs (100%) diff --git a/minecraft-entities/src/lib.rs b/minecraft-entities/src/lib.rs index eee3bcbd..e70ce69d 100644 --- a/minecraft-entities/src/lib.rs +++ b/minecraft-entities/src/lib.rs @@ -33,9 +33,6 @@ pub use fire_entities::*; mod item; pub use item::*; -mod ecs; -pub use ecs::*; - pub(crate) use minecraft_positions::*; pub(crate) use minecraft_entities_derive::MinecraftEntity; pub(crate) use minecraft_protocol::{ @@ -56,28 +53,49 @@ type CallBack = fn(O) -> Pin>>; type CallBack1 = fn(O, I) -> Pin>>; type CallBack2 = fn(O, I, J) -> Pin>>; -pub struct Handler { - uuid: UUID, - world: Arc>, +trait TryAsEntityRef { + fn try_as_entity_ref(&self) -> Option<&T> { + None + } + fn try_as_entity_mut(&mut self) -> Option<&mut T> { + None + } +} + +trait WorldTest { + fn observe_entity(&self, eid: Eid, observer: fn(&AnyEntity)) -> dyn std::future::Future; + fn mutate_entity(&self, eid: Eid, mutator: fn(&mut AnyEntity)) -> dyn std::future::Future; +} + +pub struct Handler where AnyEntity: TryAsEntityRef { + id: Eid, + world: &'static dyn WorldTest, entity: std::marker::PhantomData, } -impl Handler { - fn assume(uuid: UUID, world: Arc>) -> Self { +impl Handler where AnyEntity: TryAsEntityRef { + pub fn assume(id: Eid, world: &'static dyn WorldTest) -> Self { Self { - uuid, + id, world, entity: std::marker::PhantomData, } } - fn assume_other(self) -> Handler { + fn assume_other(self) -> Handler where AnyEntity: TryAsEntityRef { Handler { - uuid: self.uuid, + id: self.id, world: self.world, entity: std::marker::PhantomData, } } + + pub async fn observe(&self, observer: fn(&T)) { + let fut = self.world.observe_entity(self.id, |entity| { + + }); + fut.await; + } } pub enum AnyEntity { diff --git a/minecraft-entities/src/ecs.rs b/minecraft-server/src/ecs.rs similarity index 100% rename from minecraft-entities/src/ecs.rs rename to minecraft-server/src/ecs.rs From 9681c0148d7db4872c03fe118e809238d2c95674 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Fri, 10 Nov 2023 18:08:22 +0100 Subject: [PATCH 29/89] Start implementing TryAsEntityRef --- minecraft-entities-derive/src/lib.rs | 25 ++ minecraft-entities/src/animals/mod.rs | 22 ++ minecraft-entities/src/arrow.rs | 22 ++ minecraft-entities/src/boat.rs | 18 ++ minecraft-entities/src/display.rs | 22 ++ minecraft-entities/src/entity.rs | 272 ++++++++++++++++++ minecraft-entities/src/fire_entities.rs | 8 +- minecraft-entities/src/item.rs | 18 ++ minecraft-entities/src/lib.rs | 8 +- minecraft-entities/src/living_entity.rs | 24 ++ minecraft-entities/src/mobs/flying.rs | 20 ++ minecraft-entities/src/mobs/golems.rs | 20 ++ minecraft-entities/src/mobs/mod.rs | 98 +++++++ .../src/thrown_item_projectile.rs | 26 ++ 14 files changed, 593 insertions(+), 10 deletions(-) diff --git a/minecraft-entities-derive/src/lib.rs b/minecraft-entities-derive/src/lib.rs index 6022b034..0f9a99c7 100644 --- a/minecraft-entities-derive/src/lib.rs +++ b/minecraft-entities-derive/src/lib.rs @@ -202,6 +202,31 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { } let code: TokenStream = code.into_iter().collect(); codes.push(code); + } else { + // Implement TryAsEntityRef for this struct + let code: TokenStream = r#" + impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&This> { + match self { + AnyEntity::This(ref val) => Some(val), + _ => None, + } + } + + fn try_as_entity_mut(&mut self) -> Option<&mut This> { + match self { + AnyEntity::This(ref mut val) => Some(val), + _ => None, + } + } + } + "#.parse().unwrap(); + let mut code = code.clone().into_iter().collect::>(); + for element in &mut code { + replace_idents(element, &to_replace); + } + let code: TokenStream = code.into_iter().collect(); + codes.push(code); } // Generate ext trait diff --git a/minecraft-entities/src/animals/mod.rs b/minecraft-entities/src/animals/mod.rs index 2ae75b5d..4af770a2 100644 --- a/minecraft-entities/src/animals/mod.rs +++ b/minecraft-entities/src/animals/mod.rs @@ -53,6 +53,28 @@ pub struct Animal { pub ageable_mob: AgeableMob, } +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&Animal> { + match self { + AnyEntity::Animal(animal) => return Some(&animal), + _ => (), + } + if let Some(tameable_animal) = self.try_as_entity_ref::() { + return tameable_animal.animal.try_as_entity_ref(); + } + } + + fn try_as_entity_mut(&mut self) -> Option<&mut Animal> { + match self { + AnyEntity::Animal(animal) => return Some(animal), + _ => (), + } + if let Some(tameable_animal) = self.try_as_entity_mut::() { + return tameable_animal.animal.try_as_entity_mut(); + } + } +} + #[derive(Default)] #[MinecraftEntity( inheritable, parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, diff --git a/minecraft-entities/src/arrow.rs b/minecraft-entities/src/arrow.rs index 18d67460..efe507c3 100644 --- a/minecraft-entities/src/arrow.rs +++ b/minecraft-entities/src/arrow.rs @@ -21,6 +21,28 @@ impl Default for AbstractArrow { } } +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&AbstractArrow> { + match self { + AnyEntity::AbstractArrow(abstract_arrow) => Some(abstract_arrow), + AnyEntity::Arrow(arrow) => Some(&arrow.abstract_arrow), + AnyEntity::SpectralArrow(spectral_arrow) => Some(&spectral_arrow.abstract_arrow), + AnyEntity::ThrownTrident(thrown_trident) => Some(&thrown_trident.abstract_arrow), + _ => None, + } + } + + fn try_as_entity_mut(&mut self) -> Option<&mut AbstractArrow> { + match self { + AnyEntity::AbstractArrow(abstract_arrow) => Some(abstract_arrow), + AnyEntity::Arrow(arrow) => Some(&mut arrow.abstract_arrow), + AnyEntity::SpectralArrow(spectral_arrow) => Some(&mut spectral_arrow.abstract_arrow), + AnyEntity::ThrownTrident(thrown_trident) => Some(&mut thrown_trident.abstract_arrow), + _ => None, + } + } +} + #[MinecraftEntity( parents { AbstractArrow, Entity }, )] diff --git a/minecraft-entities/src/boat.rs b/minecraft-entities/src/boat.rs index ce92a5f4..b9a2a28e 100644 --- a/minecraft-entities/src/boat.rs +++ b/minecraft-entities/src/boat.rs @@ -30,6 +30,24 @@ impl Default for Boat { } } +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&Entity> { + match self { + AnyEntity::Boat(boat) => Some(&boat.entity), + AnyEntity::ChestBoat(chest_boat) => Some(&chest_boat.boat.entity), + _ => None, + } + } + + fn try_as_entity_mut(&mut self) -> Option<&mut Boat> { + match self { + AnyEntity::Boat(boat) => Some(boat), + AnyEntity::ChestBoat(chest_boat) => Some(&mut chest_boat.boat), + _ => None, + } + } +} + #[derive(Default)] #[MinecraftEntity( parents { Boat, Entity }, diff --git a/minecraft-entities/src/display.rs b/minecraft-entities/src/display.rs index f1450ada..679c7eeb 100644 --- a/minecraft-entities/src/display.rs +++ b/minecraft-entities/src/display.rs @@ -52,6 +52,28 @@ impl Default for Display { } } +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&Entity> { + match self { + AnyEntity::Display(display) => Some(&display.entity), + AnyEntity::BlockDisplay(block_display) => Some(&block_display.display.entity), + AnyEntity::ItemDisplay(item_display) => Some(&item_display.display.entity), + AnyEntity::TextDisplay(text_display) => Some(&text_display.display.entity), + _ => None, + } + } + + fn try_as_entity_mut(&mut self) -> Option<&mut Display> { + match self { + AnyEntity::Display(display) => Some(display), + AnyEntity::BlockDisplay(block_display) => Some(&mut block_display.display), + AnyEntity::ItemDisplay(item_display) => Some(&mut item_display.display), + AnyEntity::TextDisplay(text_display) => Some(&mut text_display.display), + _ => None, + } + } +} + #[MinecraftEntity( parents { Display, Entity }, )] diff --git a/minecraft-entities/src/entity.rs b/minecraft-entities/src/entity.rs index 8c1ee3bc..f8684788 100644 --- a/minecraft-entities/src/entity.rs +++ b/minecraft-entities/src/entity.rs @@ -42,3 +42,275 @@ impl Default for Entity { } } } + +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&Entity> { + Some(match self { + AnyEntity::Entity(entity) => entity, + AnyEntity::Display(display) => display.get_entity(), + AnyEntity::BlockDisplay(block_display) => block_display.get_entity(), + AnyEntity::ItemDisplay(item_display) => item_display.get_entity(), + AnyEntity::TextDisplay(text_display) => text_display.get_entity(), + AnyEntity::ThrownItemProjectile(throw_item_projectile) => throw_item_projectile.get_entity(), + AnyEntity::ThrownEgg(throw_egg) => throw_egg.get_entity(), + AnyEntity::ThrownEnderPearl(throw_ender_pearl) => throw_ender_pearl.get_entity(), + AnyEntity::ThrownExperienceBottle(throw_experience_bottle) => throw_experience_bottle.get_entity(), + AnyEntity::ThrownPotion(throw_potion) => throw_potion.get_entity(), + AnyEntity::Snowball(snowball) => snowball.get_entity(), + AnyEntity::AbstractArrow(abstract_arrow) => abstract_arrow.get_entity(), + AnyEntity::Arrow(arrow) => arrow.get_entity(), + AnyEntity::SpectralArrow(spectral_arrow) => spectral_arrow.get_entity(), + AnyEntity::ThrownTrident(throw_trident) => throw_trident.get_entity(), + AnyEntity::Boat(boat) => boat.get_entity(), + AnyEntity::ChestBoat(chest_boat) => chest_boat.get_entity(), + AnyEntity::LivingEntity(living_entity) => living_entity.get_entity(), + AnyEntity::Player(player) => player.get_entity(), + AnyEntity::Mob(mob) => mob.get_entity(), + AnyEntity::AmbientCreature(ambient_creature) => ambient_creature.get_entity(), + AnyEntity::Bat(bat) => bat.get_entity(), + AnyEntity::PathfinderMob(pathfinder_mob) => pathfinder_mob.get_entity(), + AnyEntity::WaterAnimal(water_animal) => water_animal.get_entity(), + AnyEntity::Squid(squid) => squid.get_entity(), + AnyEntity::AgeableMob(ageable_mob) => ageable_mob.get_entity(), + AnyEntity::Animal(animal) => animal.get_entity(), + AnyEntity::Sniffer(sniffer) => sniffer.get_entity(), + AnyEntity::AbstractHorse(abstract_horse) => abstract_horse.get_entity(), + AnyEntity::ZombieHorse(zombie_horse) => zombie_horse.get_entity(), + AnyEntity::Horse(horse) => horse.get_entity(), + AnyEntity::SkeletonHorse(skeleton_horse) => skeleton_horse.get_entity(), + AnyEntity::Camel(camel) => camel.get_entity(), + AnyEntity::ChestedHorse(chested_horse) => chested_horse.get_entity(), + AnyEntity::Donkey(donkey) => donkey.get_entity(), + AnyEntity::Llama(llama) => llama.get_entity(), + AnyEntity::TraderLlama(trader_llama) => trader_llama.get_entity(), + AnyEntity::Mule(mule) => mule.get_entity(), + AnyEntity::Axolotl(axolotl) => axolotl.get_entity(), + AnyEntity::Bee(bee) => bee.get_entity(), + AnyEntity::Fox(fox) => fox.get_entity(), + AnyEntity::Frog(frog) => frog.get_entity(), + AnyEntity::Ocelot(ocelot) => ocelot.get_entity(), + AnyEntity::Panda(panda) => panda.get_entity(), + AnyEntity::Pig(pig) => pig.get_entity(), + AnyEntity::Rabbit(rabbit) => rabbit.get_entity(), + AnyEntity::Turtle(turtle) => turtle.get_entity(), + AnyEntity::PolarBear(polar_bear) => polar_bear.get_entity(), + AnyEntity::Chicken(chicken) => chicken.get_entity(), + AnyEntity::Cow(cow) => cow.get_entity(), + AnyEntity::Hoglin(hoglin) => hoglin.get_entity(), + AnyEntity::Mooshroom(mooshroom) => mooshroom.get_entity(), + AnyEntity::Sheep(sheep) => sheep.get_entity(), + AnyEntity::Strider(strider) => strider.get_entity(), + AnyEntity::TameableAnimal(tameable_animal) => tameable_animal.get_entity(), + AnyEntity::Cat(cat) => cat.get_entity(), + AnyEntity::Wolf(wolf) => wolf.get_entity(), + AnyEntity::Parrot(parrot) => parrot.get_entity(), + AnyEntity::AbstractVillager(abstract_villager) => abstract_villager.get_entity(), + AnyEntity::Villager(villager) => villager.get_entity(), + AnyEntity::WanderingTrader(wandering_trader) => wandering_trader.get_entity(), + AnyEntity::AbstractGolem(abstract_golem) => abstract_golem.get_entity(), + AnyEntity::IronGolem(iron_golem) => iron_golem.get_entity(), + AnyEntity::SnowGolem(snow_golem) => snow_golem.get_entity(), + AnyEntity::Shulker(shulker) => shulker.get_entity(), + AnyEntity::Monster(monster) => monster.get_entity(), + AnyEntity::BasePiglin(base_piglin) => base_piglin.get_entity(), + AnyEntity::Piglin(piglin) => piglin.get_entity(), + AnyEntity::PiglinBrute(piglin_brute) => piglin_brute.get_entity(), + AnyEntity::Blaze(blaze) => blaze.get_entity(), + AnyEntity::Creeper(creeper) => creeper.get_entity(), + AnyEntity::Endermite(endermite) => endermite.get_entity(), + AnyEntity::Giant(giant) => giant.get_entity(), + AnyEntity::Goat(goat) => goat.get_entity(), + AnyEntity::Guardian(guardian) => guardian.get_entity(), + AnyEntity::ElderGuardian(elder_guardian) => elder_guardian.get_entity(), + AnyEntity::Silverfish(silverfish) => silverfish.get_entity(), + AnyEntity::Raider(raider) => raider.get_entity(), + AnyEntity::AbstractIllager(abstract_illager) => abstract_illager.get_entity(), + AnyEntity::Vindicator(vindicator) => vindicator.get_entity(), + AnyEntity::Pillager(pillager) => pillager.get_entity(), + AnyEntity::SpellcasterIllager(spellcaster_illager) => spellcaster_illager.get_entity(), + AnyEntity::Evoker(evoker) => evoker.get_entity(), + AnyEntity::Illusioner(illusioner) => illusioner.get_entity(), + AnyEntity::Ravager(ravager) => ravager.get_entity(), + AnyEntity::Witch(witch) => witch.get_entity(), + AnyEntity::EvokerFangs(evoker_fangs) => evoker_fangs.get_entity(), + AnyEntity::Vex(vex) => vex.get_entity(), + AnyEntity::Skeleton(skeleton) => skeleton.get_entity(), + AnyEntity::AbstractSkeleton(abstract_skeleton) => abstract_skeleton.get_entity(), + AnyEntity::WitherSkeleton(wither_skeleton) => wither_skeleton.get_entity(), + AnyEntity::Stray(stray) => stray.get_entity(), + AnyEntity::Spider(spider) => spider.get_entity(), + AnyEntity::Warden(warden) => warden.get_entity(), + AnyEntity::Wither(wither) => wither.get_entity(), + AnyEntity::Zoglin(zoglin) => zoglin.get_entity(), + AnyEntity::Zombie(zombie) => zombie.get_entity(), + AnyEntity::ZombieVillager(zombie_villager) => zombie_villager.get_entity(), + AnyEntity::Husk(husk) => husk.get_entity(), + AnyEntity::Drowned(drowned) => drowned.get_entity(), + AnyEntity::ZombifiedPiglin(zombified_piglin) => zombified_piglin.get_entity(), + AnyEntity::Enderman(enderman) => enderman.get_entity(), + AnyEntity::EnderDragon(ender_dragon) => ender_dragon.get_entity(), + AnyEntity::Flying(flying) => flying.get_entity(), + AnyEntity::Ghast(ghast) => ghast.get_entity(), + AnyEntity::Phantom(phantom) => phantom.get_entity(), + AnyEntity::Slime(slime) => slime.get_entity(), + AnyEntity::LlamaSpit(llama_spit) => llama_spit.get_entity(), + AnyEntity::EyeOfEnder(eye_of_ender) => eye_of_ender.get_entity(), + AnyEntity::FallingBlock(falling_block) => falling_block.get_entity(), + AnyEntity::AreaEffectCloud(area_effect_cloud) => area_effect_cloud.get_entity(), + AnyEntity::FishingHook(fishing_hook) => fishing_hook.get_entity(), + AnyEntity::EndCrystal(end_crystal) => end_crystal.get_entity(), + AnyEntity::DragonFireball(dragon_fireball) => dragon_fireball.get_entity(), + AnyEntity::SmallFireball(small_fireball) => small_fireball.get_entity(), + AnyEntity::Fireball(fireball) => fireball.get_entity(), + AnyEntity::WitherSkull(wither_skull) => wither_skull.get_entity(), + AnyEntity::FireworkRocket(firework_rocket) => firework_rocket.get_entity(), + AnyEntity::ItemFrame(item_frame) => item_frame.get_entity(), + AnyEntity::GlowingItemFrame(glowing_item_frame) => glowing_item_frame.get_entity(), + AnyEntity::Painting(painting) => painting.get_entity(), + AnyEntity::ItemEntity(item_entity) => item_entity.get_entity(), + AnyEntity::ArmorStand(armor_stand) => armor_stand.get_entity(), + AnyEntity::Dolphin(dolphin) => dolphin.get_entity(), + AnyEntity::AbstractFish(abstract_fish) => abstract_fish.get_entity(), + AnyEntity::Cod(cod) => cod.get_entity(), + AnyEntity::PufferFish(pufferfish) => pufferfish.get_entity(), + AnyEntity::Salmon(salmon) => salmon.get_entity(), + AnyEntity::TropicalFish(tropical_fish) => tropical_fish.get_entity(), + AnyEntity::Tadpole(tadpole) => tadpole.get_entity(), + }) + } + + fn try_as_entity_mut(&mut self) -> Option<&mut Entity> { + Some(match self { + AnyEntity::Entity(entity) => entity, + AnyEntity::Display(display) => display.get_entity_mut(), + AnyEntity::BlockDisplay(block_display) => block_display.get_entity_mut(), + AnyEntity::ItemDisplay(item_display) => item_display.get_entity_mut(), + AnyEntity::TextDisplay(text_display) => text_display.get_entity_mut(), + AnyEntity::ThrownItemProjectile(throw_item_projectile) => throw_item_projectile.get_entity_mut(), + AnyEntity::ThrownEgg(throw_egg) => throw_egg.get_entity_mut(), + AnyEntity::ThrownEnderPearl(throw_ender_pearl) => throw_ender_pearl.get_entity_mut(), + AnyEntity::ThrownExperienceBottle(throw_experience_bottle) => throw_experience_bottle.get_entity_mut(), + AnyEntity::ThrownPotion(throw_potion) => throw_potion.get_entity_mut(), + AnyEntity::Snowball(snowball) => snowball.get_entity_mut(), + AnyEntity::AbstractArrow(abstract_arrow) => abstract_arrow.get_entity_mut(), + AnyEntity::Arrow(arrow) => arrow.get_entity_mut(), + AnyEntity::SpectralArrow(spectral_arrow) => spectral_arrow.get_entity_mut(), + AnyEntity::ThrownTrident(throw_trident) => throw_trident.get_entity_mut(), + AnyEntity::Boat(boat) => boat.get_entity_mut(), + AnyEntity::ChestBoat(chest_boat) => chest_boat.get_entity_mut(), + AnyEntity::LivingEntity(living_entity) => living_entity.get_entity_mut(), + AnyEntity::Player(player) => player.get_entity_mut(), + AnyEntity::Mob(mob) => mob.get_entity_mut(), + AnyEntity::AmbientCreature(ambient_creature) => ambient_creature.get_entity_mut(), + AnyEntity::Bat(bat) => bat.get_entity_mut(), + AnyEntity::PathfinderMob(pathfinder_mob) => pathfinder_mob.get_entity_mut(), + AnyEntity::WaterAnimal(water_animal) => water_animal.get_entity_mut(), + AnyEntity::Squid(squid) => squid.get_entity_mut(), + AnyEntity::AgeableMob(ageable_mob) => ageable_mob.get_entity_mut(), + AnyEntity::Animal(animal) => animal.get_entity_mut(), + AnyEntity::Sniffer(sniffer) => sniffer.get_entity_mut(), + AnyEntity::AbstractHorse(abstract_horse) => abstract_horse.get_entity_mut(), + AnyEntity::ZombieHorse(zombie_horse) => zombie_horse.get_entity_mut(), + AnyEntity::Horse(horse) => horse.get_entity_mut(), + AnyEntity::SkeletonHorse(skeleton_horse) => skeleton_horse.get_entity_mut(), + AnyEntity::Camel(camel) => camel.get_entity_mut(), + AnyEntity::ChestedHorse(chested_horse) => chested_horse.get_entity_mut(), + AnyEntity::Donkey(donkey) => donkey.get_entity_mut(), + AnyEntity::Llama(llama) => llama.get_entity_mut(), + AnyEntity::TraderLlama(trader_llama) => trader_llama.get_entity_mut(), + AnyEntity::Mule(mule) => mule.get_entity_mut(), + AnyEntity::Axolotl(axolotl) => axolotl.get_entity_mut(), + AnyEntity::Bee(bee) => bee.get_entity_mut(), + AnyEntity::Fox(fox) => fox.get_entity_mut(), + AnyEntity::Frog(frog) => frog.get_entity_mut(), + AnyEntity::Ocelot(ocelot) => ocelot.get_entity_mut(), + AnyEntity::Panda(panda) => panda.get_entity_mut(), + AnyEntity::Pig(pig) => pig.get_entity_mut(), + AnyEntity::Rabbit(rabbit) => rabbit.get_entity_mut(), + AnyEntity::Turtle(turtle) => turtle.get_entity_mut(), + AnyEntity::PolarBear(polar_bear) => polar_bear.get_entity_mut(), + AnyEntity::Chicken(chicken) => chicken.get_entity_mut(), + AnyEntity::Cow(cow) => cow.get_entity_mut(), + AnyEntity::Hoglin(hoglin) => hoglin.get_entity_mut(), + AnyEntity::Mooshroom(mooshroom) => mooshroom.get_entity_mut(), + AnyEntity::Sheep(sheep) => sheep.get_entity_mut(), + AnyEntity::Strider(strider) => strider.get_entity_mut(), + AnyEntity::TameableAnimal(tameable_animal) => tameable_animal.get_entity_mut(), + AnyEntity::Cat(cat) => cat.get_entity_mut(), + AnyEntity::Wolf(wolf) => wolf.get_entity_mut(), + AnyEntity::Parrot(parrot) => parrot.get_entity_mut(), + AnyEntity::AbstractVillager(abstract_villager) => abstract_villager.get_entity_mut(), + AnyEntity::Villager(villager) => villager.get_entity_mut(), + AnyEntity::WanderingTrader(wandering_trader) => wandering_trader.get_entity_mut(), + AnyEntity::AbstractGolem(abstract_golem) => abstract_golem.get_entity_mut(), + AnyEntity::IronGolem(iron_golem) => iron_golem.get_entity_mut(), + AnyEntity::SnowGolem(snow_golem) => snow_golem.get_entity_mut(), + AnyEntity::Shulker(shulker) => shulker.get_entity_mut(), + AnyEntity::Monster(monster) => monster.get_entity_mut(), + AnyEntity::BasePiglin(base_piglin) => base_piglin.get_entity_mut(), + AnyEntity::Piglin(piglin) => piglin.get_entity_mut(), + AnyEntity::PiglinBrute(piglin_brute) => piglin_brute.get_entity_mut(), + AnyEntity::Blaze(blaze) => blaze.get_entity_mut(), + AnyEntity::Creeper(creeper) => creeper.get_entity_mut(), + AnyEntity::Endermite(endermite) => endermite.get_entity_mut(), + AnyEntity::Giant(giant) => giant.get_entity_mut(), + AnyEntity::Goat(goat) => goat.get_entity_mut(), + AnyEntity::Guardian(guardian) => guardian.get_entity_mut(), + AnyEntity::ElderGuardian(elder_guardian) => elder_guardian.get_entity_mut(), + AnyEntity::Silverfish(silverfish) => silverfish.get_entity_mut(), + AnyEntity::Raider(raider) => raider.get_entity_mut(), + AnyEntity::AbstractIllager(abstract_illager) => abstract_illager.get_entity_mut(), + AnyEntity::Vindicator(vindicator) => vindicator.get_entity_mut(), + AnyEntity::Pillager(pillager) => pillager.get_entity_mut(), + AnyEntity::SpellcasterIllager(spellcaster_illager) => spellcaster_illager.get_entity_mut(), + AnyEntity::Evoker(evoker) => evoker.get_entity_mut(), + AnyEntity::Illusioner(illusioner) => illusioner.get_entity_mut(), + AnyEntity::Ravager(ravager) => ravager.get_entity_mut(), + AnyEntity::Witch(witch) => witch.get_entity_mut(), + AnyEntity::EvokerFangs(evoker_fangs) => evoker_fangs.get_entity_mut(), + AnyEntity::Vex(vex) => vex.get_entity_mut(), + AnyEntity::Skeleton(skeleton) => skeleton.get_entity_mut(), + AnyEntity::AbstractSkeleton(abstract_skeleton) => abstract_skeleton.get_entity_mut(), + AnyEntity::WitherSkeleton(wither_skeleton) => wither_skeleton.get_entity_mut(), + AnyEntity::Stray(stray) => stray.get_entity_mut(), + AnyEntity::Spider(spider) => spider.get_entity_mut(), + AnyEntity::Warden(warden) => warden.get_entity_mut(), + AnyEntity::Wither(wither) => wither.get_entity_mut(), + AnyEntity::Zoglin(zoglin) => zoglin.get_entity_mut(), + AnyEntity::Zombie(zombie) => zombie.get_entity_mut(), + AnyEntity::ZombieVillager(zombie_villager) => zombie_villager.get_entity_mut(), + AnyEntity::Husk(husk) => husk.get_entity_mut(), + AnyEntity::Drowned(drowned) => drowned.get_entity_mut(), + AnyEntity::ZombifiedPiglin(zombified_piglin) => zombified_piglin.get_entity_mut(), + AnyEntity::Enderman(enderman) => enderman.get_entity_mut(), + AnyEntity::EnderDragon(ender_dragon) => ender_dragon.get_entity_mut(), + AnyEntity::Flying(flying) => flying.get_entity_mut(), + AnyEntity::Ghast(ghast) => ghast.get_entity_mut(), + AnyEntity::Phantom(phantom) => phantom.get_entity_mut(), + AnyEntity::Slime(slime) => slime.get_entity_mut(), + AnyEntity::LlamaSpit(llama_spit) => llama_spit.get_entity_mut(), + AnyEntity::EyeOfEnder(eye_of_ender) => eye_of_ender.get_entity_mut(), + AnyEntity::FallingBlock(falling_block) => falling_block.get_entity_mut(), + AnyEntity::AreaEffectCloud(area_effect_cloud) => area_effect_cloud.get_entity_mut(), + AnyEntity::FishingHook(fishing_hook) => fishing_hook.get_entity_mut(), + AnyEntity::EndCrystal(end_crystal) => end_crystal.get_entity_mut(), + AnyEntity::DragonFireball(dragon_fireball) => dragon_fireball.get_entity_mut(), + AnyEntity::SmallFireball(small_fireball) => small_fireball.get_entity_mut(), + AnyEntity::Fireball(fireball) => fireball.get_entity_mut(), + AnyEntity::WitherSkull(wither_skull) => wither_skull.get_entity_mut(), + AnyEntity::FireworkRocket(firework_rocket) => firework_rocket.get_entity_mut(), + AnyEntity::ItemFrame(item_frame) => item_frame.get_entity_mut(), + AnyEntity::GlowingItemFrame(glowing_item_frame) => glowing_item_frame.get_entity_mut(), + AnyEntity::Painting(painting) => painting.get_entity_mut(), + AnyEntity::ItemEntity(item_entity) => item_entity.get_entity_mut(), + AnyEntity::ArmorStand(armor_stand) => armor_stand.get_entity_mut(), + AnyEntity::Dolphin(dolphin) => dolphin.get_entity_mut(), + AnyEntity::AbstractFish(abstract_fish) => abstract_fish.get_entity_mut(), + AnyEntity::Cod(cod) => cod.get_entity_mut(), + AnyEntity::PufferFish(pufferfish) => pufferfish.get_entity_mut(), + AnyEntity::Salmon(salmon) => salmon.get_entity_mut(), + AnyEntity::TropicalFish(tropical_fish) => tropical_fish.get_entity_mut(), + AnyEntity::Tadpole(tadpole) => tadpole.get_entity_mut(), + }) + } +} diff --git a/minecraft-entities/src/fire_entities.rs b/minecraft-entities/src/fire_entities.rs index eef22f51..ac330586 100644 --- a/minecraft-entities/src/fire_entities.rs +++ b/minecraft-entities/src/fire_entities.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - inheritable, parents { Entity }, + parents { Entity }, )] pub struct DragonFireball { pub entity: Entity, @@ -10,7 +10,7 @@ pub struct DragonFireball { #[derive(Default)] #[MinecraftEntity( - inheritable, parents { Entity }, + parents { Entity }, )] pub struct SmallFireball { pub entity: Entity, @@ -19,7 +19,7 @@ pub struct SmallFireball { #[derive(Default)] #[MinecraftEntity( - inheritable, parents { Entity }, + parents { Entity }, )] pub struct Fireball { pub entity: Entity, @@ -28,7 +28,7 @@ pub struct Fireball { #[derive(Default)] #[MinecraftEntity( - inheritable, parents { Entity }, + parents { Entity }, )] pub struct FireworkRocket { pub entity: Entity, diff --git a/minecraft-entities/src/item.rs b/minecraft-entities/src/item.rs index 86ce6fcd..b90df0d9 100644 --- a/minecraft-entities/src/item.rs +++ b/minecraft-entities/src/item.rs @@ -10,6 +10,24 @@ pub struct ItemFrame { pub rotation: u8, } +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&Entity> { + match self { + AnyEntity::ItemFrame(item_frame) => Some(&item_frame.entity), + AnyEntity::GlowingItemFrame(glowing_item_frame) => Some(&glowing_item_frame.item_frame.entity), + _ => None, + } + } + + fn try_as_entity_mut(&mut self) -> Option<&mut ItemFrame> { + match self { + AnyEntity::ItemFrame(item_frame) => Some(item_frame), + AnyEntity::GlowingItemFrame(glowing_item_frame) => Some(&mut glowing_item_frame.item_frame), + _ => None, + } + } +} + #[derive(Default)] #[MinecraftEntity( parents { ItemFrame, Entity }, diff --git a/minecraft-entities/src/lib.rs b/minecraft-entities/src/lib.rs index e70ce69d..7d557c4b 100644 --- a/minecraft-entities/src/lib.rs +++ b/minecraft-entities/src/lib.rs @@ -54,12 +54,8 @@ type CallBack1 = fn(O, I) -> Pin>>; type CallBack2 = fn(O, I, J) -> Pin>>; trait TryAsEntityRef { - fn try_as_entity_ref(&self) -> Option<&T> { - None - } - fn try_as_entity_mut(&mut self) -> Option<&mut T> { - None - } + fn try_as_entity_ref(&self) -> Option<&T>; + fn try_as_entity_mut(&mut self) -> Option<&mut T>; } trait WorldTest { diff --git a/minecraft-entities/src/living_entity.rs b/minecraft-entities/src/living_entity.rs index 2a9c68f9..fac081ea 100644 --- a/minecraft-entities/src/living_entity.rs +++ b/minecraft-entities/src/living_entity.rs @@ -33,6 +33,30 @@ impl Default for LivingEntity { } } +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&LivingEntity> { + match self { + AnyEntity::LivingEntity(living_entity) => return Some(living_entity), + AnyEntity::Player(player) => return Some(&player.living_entity), + _ => (), + } + if let Some(mob) = self.try_as_entity_ref::() { + return mob.living_entity.try_as_entity_ref(); + } + } + + fn try_as_entity_mut(&mut self) -> Option<&mut LivingEntity> { + match self { + AnyEntity::LivingEntity(living_entity) => return Some(living_entity), + AnyEntity::Player(player) => return Some(&mut player.living_entity), + _ => (), + } + if let Some(mob) = self.try_as_entity_mut::() { + return mob.living_entity.try_as_entity_mut(); + } + } +} + #[MinecraftEntity( parents { LivingEntity, Entity }, )] diff --git a/minecraft-entities/src/mobs/flying.rs b/minecraft-entities/src/mobs/flying.rs index 7983cf1b..c3598f84 100644 --- a/minecraft-entities/src/mobs/flying.rs +++ b/minecraft-entities/src/mobs/flying.rs @@ -8,6 +8,26 @@ pub struct Flying { pub mob: Mob, } +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&Flying> { + match self { + AnyEntity::Flying(flying) => Some(&flying), + AnyEntity::Bat(bat) => Some(&bat.flying), + AnyEntity::Ghast(ghast) => Some(&ghast.flying), + _ => None, + } + } + + fn try_as_entity_mut(&mut self) -> Option<&mut Flying> { + match self { + AnyEntity::Flying(flying) => Some(flying), + AnyEntity::Bat(bat) => Some(&mut bat.flying), + AnyEntity::Ghast(ghast) => Some(&mut ghast.flying), + _ => None, + } + } +} + #[derive(Default)] #[MinecraftEntity( parents { Flying, Mob, LivingEntity, Entity }, diff --git a/minecraft-entities/src/mobs/golems.rs b/minecraft-entities/src/mobs/golems.rs index 229c561b..472ba744 100644 --- a/minecraft-entities/src/mobs/golems.rs +++ b/minecraft-entities/src/mobs/golems.rs @@ -8,6 +8,26 @@ pub struct AbstractGolem { pub pathfinder_mob: PathfinderMob, } +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&AbstractGolem> { + match self { + AnyEntity::AbstractGolem(abstract_golem) => Some(&abstract_golem), + AnyEntity::IronGolem(iron_golem) => Some(&iron_golem.abstract_golem), + AnyEntity::SnowGolem(snow_golem) => Some(&snow_golem.abstract_golem), + _ => None, + } + } + + fn try_as_entity_mut(&mut self) -> Option<&mut AbstractGolem> { + match self { + AnyEntity::AbstractGolem(abstract_golem) => Some(abstract_golem), + AnyEntity::IronGolem(iron_golem) => Some(&mut iron_golem.abstract_golem), + AnyEntity::SnowGolem(snow_golem) => Some(&mut snow_golem.abstract_golem), + _ => None, + } + } +} + #[derive(Default)] #[MinecraftEntity( parents { AbstractGolem, PathfinderMob, Mob, LivingEntity, Entity }, diff --git a/minecraft-entities/src/mobs/mod.rs b/minecraft-entities/src/mobs/mod.rs index 96e425de..fb76cd8c 100644 --- a/minecraft-entities/src/mobs/mod.rs +++ b/minecraft-entities/src/mobs/mod.rs @@ -24,6 +24,36 @@ pub struct Mob { pub is_aggressive: bool, } +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&Mob> { + match self { + AnyEntity::Mob(mob) => return Some(&mob), + _ => (), + } + if let Some(ambient_creature) = self.try_as_entity_ref::() { + return ambient_creature.mob.try_as_entity_ref(); + } + if let Some(pathfinder_mob) = self.try_as_entity_ref::() { + return pathfinder_mob.mob.try_as_entity_ref(); + } + None + } + + fn try_as_entity_mut(&mut self) -> Option<&mut Mob> { + match self { + AnyEntity::Mob(mob) => return Some(mob), + _ => (), + } + if let Some(ambient_creature) = self.try_as_entity_mut::() { + return ambient_creature.mob.try_as_entity_mut(); + } + if let Some(pathfinder_mob) = self.try_as_entity_mut::() { + return pathfinder_mob.mob.try_as_entity_mut(); + } + None + } +} + #[derive(Default)] #[MinecraftEntity( inheritable, parents { Mob, LivingEntity, Entity }, @@ -32,6 +62,26 @@ pub struct AmbientCreature { pub mob: Mob, } +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&AmbientCreature> { + match self { + AnyEntity::AmbientCreature(ambient_creature) => return Some(&ambient_creature), + AnyEntity::Bat(bat) => return Some(&bat.ambient_creature), + _ => (), + } + None + } + + fn try_as_entity_mut(&mut self) -> Option<&mut AmbientCreature> { + match self { + AnyEntity::AmbientCreature(ambient_creature) => return Some(ambient_creature), + AnyEntity::Bat(bat) => return Some(&mut bat.ambient_creature), + _ => (), + } + None + } +} + #[derive(Default)] #[MinecraftEntity( inheritable, parents { Mob, LivingEntity, Entity }, @@ -40,6 +90,30 @@ pub struct PathfinderMob { pub mob: Mob, } +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&PathfinderMob> { + match self { + AnyEntity::PathfinderMob(pathfinder_mob) => return Some(&pathfinder_mob), + _ => (), + } + if let Some(ageable_mob) = self.try_as_entity_ref::() { + return ageable_mob.pathfinder_mob.try_as_entity_ref(); + } + None + } + + fn try_as_entity_mut(&mut self) -> Option<&mut PathfinderMob> { + match self { + AnyEntity::PathfinderMob(pathfinder_mob) => return Some(pathfinder_mob), + _ => (), + } + if let Some(ageable_mob) = self.try_as_entity_mut::() { + return ageable_mob.pathfinder_mob.try_as_entity_mut(); + } + None + } +} + #[derive(Default)] #[MinecraftEntity( inheritable, parents { PathfinderMob, Mob, LivingEntity, Entity }, @@ -48,3 +122,27 @@ pub struct AgeableMob { pub pathfinder_mob: PathfinderMob, pub is_baby: bool, } + +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&AgeableMob> { + match self { + AnyEntity::AgeableMob(ageable_mob) => return Some(&ageable_mob), + _ => (), + } + if let Some(villager) = self.try_as_entity_ref::() { + return villager.try_as_entity_ref(); + } + None + } + + fn try_as_entity_mut(&mut self) -> Option<&mut AgeableMob> { + match self { + AnyEntity::AgeableMob(ageable_mob) => return Some(&mut ageable_mob), + _ => (), + } + if let Some(villager) = self.try_as_entity_mut::() { + return villager.try_as_entity_mut(); + } + None + } +} diff --git a/minecraft-entities/src/thrown_item_projectile.rs b/minecraft-entities/src/thrown_item_projectile.rs index 7ab40c85..af8c0423 100644 --- a/minecraft-entities/src/thrown_item_projectile.rs +++ b/minecraft-entities/src/thrown_item_projectile.rs @@ -17,6 +17,32 @@ impl Default for ThrownItemProjectile { } } +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&ThrownItemProjectile> { + match self { + AnyEntity::ThrownItemProjectile(throwable) => Some(throwable), + AnyEntity::ThrownEgg(egg) => Some(&egg.thrown_item_projectile), + AnyEntity::ThrownEnderPearl(ender_pearl) => Some(&ender_pearl.thrown_item_projectile), + AnyEntity::ThrownExperienceBottle(experience_bottle) => Some(&experience_bottle.thrown_item_projectile), + AnyEntity::ThrownPotion(potion) => Some(&potion.thrown_item_projectile), + AnyEntity::Snowball(snowball) => Some(&snowball.thrown_item_projectile), + _ => None, + } + } + + fn try_as_entity_mut(&mut self) -> Option<&mut ThrownItemProjectile> { + match self { + AnyEntity::ThrownItemProjectile(throwable) => Some(throwable), + AnyEntity::ThrownEgg(egg) => Some(&mut egg.thrown_item_projectile), + AnyEntity::ThrownEnderPearl(ender_pearl) => Some(&mut ender_pearl.thrown_item_projectile), + AnyEntity::ThrownExperienceBottle(experience_bottle) => Some(&mut experience_bottle.thrown_item_projectile), + AnyEntity::ThrownPotion(potion) => Some(&mut potion.thrown_item_projectile), + AnyEntity::Snowball(snowball) => Some(&mut snowball.thrown_item_projectile), + _ => None, + } + } +} + #[MinecraftEntity( parents { ThrownItemProjectile, Entity }, )] From b45a8cfd103db86df0b2c589e928d69ea59268ec Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Fri, 10 Nov 2023 18:27:56 +0100 Subject: [PATCH 30/89] Finish fishes --- minecraft-entities-derive/examples/main.rs | 37 ++++----- minecraft-entities/src/animals/cow.rs | 10 +++ minecraft-entities/src/animals/frog.rs | 1 - minecraft-entities/src/animals/hoglin.rs | 1 - minecraft-entities/src/animals/horses.rs | 80 ++++++++++++++++++- minecraft-entities/src/animals/mod.rs | 18 +++++ minecraft-entities/src/animals/ocelot.rs | 1 - minecraft-entities/src/animals/panda.rs | 1 - minecraft-entities/src/animals/sheep.rs | 2 +- .../src/animals/water_animal.rs | 54 +++++++++++++ minecraft-entities/src/entity.rs | 2 +- 11 files changed, 181 insertions(+), 26 deletions(-) diff --git a/minecraft-entities-derive/examples/main.rs b/minecraft-entities-derive/examples/main.rs index a1be6c76..a577989e 100644 --- a/minecraft-entities-derive/examples/main.rs +++ b/minecraft-entities-derive/examples/main.rs @@ -1,34 +1,35 @@ use minecraft_entities_derive::*; -struct Test { - test: fn(u8, u8) -> usize, - test2: fn(u8, u8) -> usize, -} - -const BOO: &Test = &Test { - test: |a, b| a as usize + b as usize, - test2: |a, b| a as usize + b as usize, -}; - -const BOO2: &Test = { - let mut t1 = BOO; - t1 -}; - use std::{pin::Pin, future::Future, sync::{Mutex, Arc}}; type CallBack = fn(O) -> Pin>>; type CallBack1 = fn(O, I) -> Pin>>; type CallBack2 = fn(O, I, J) -> Pin>>; -type UUID = u128; +type Eid = u32; + +trait TryAsEntityRef { + fn try_as_entity_ref(&self) -> Option<&T>; + fn try_as_entity_mut(&mut self) -> Option<&mut T>; +} + +trait WorldTest { + fn observe_entity(&self, eid: Eid, observer: fn(&AnyEntity)) -> dyn std::future::Future; + fn mutate_entity(&self, eid: Eid, mutator: fn(&mut AnyEntity)) -> dyn std::future::Future; +} + +enum AnyEntity { + Entity(Entity), + Animal(Animal), + Cow(Cow), +} pub struct Handler { - uuid: UUID, + uuid: Eid, world: Arc>, entity: std::marker::PhantomData, } impl Handler { - fn assume(uuid: UUID, world: Arc>) -> Self { + fn assume(uuid: Eid, world: Arc>) -> Self { Self { uuid, world, diff --git a/minecraft-entities/src/animals/cow.rs b/minecraft-entities/src/animals/cow.rs index 9e79f206..4041093b 100644 --- a/minecraft-entities/src/animals/cow.rs +++ b/minecraft-entities/src/animals/cow.rs @@ -8,6 +8,16 @@ pub struct Cow { pub animal: Animal, } +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&Cow> { + match self { + AnyEntity::Cow(cow) => return Some(&cow), + AnyEntity::Mooshroom(mooshroom) => return Some(&mooshroom.cow), + _ => (), + } + } +} + #[derive(Default)] #[MinecraftEntity( parents { Cow, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, diff --git a/minecraft-entities/src/animals/frog.rs b/minecraft-entities/src/animals/frog.rs index 6c03506d..cf6587ad 100644 --- a/minecraft-entities/src/animals/frog.rs +++ b/minecraft-entities/src/animals/frog.rs @@ -1,4 +1,3 @@ -use minecraft_protocol::packets::UUID; use super::*; #[derive(Default)] diff --git a/minecraft-entities/src/animals/hoglin.rs b/minecraft-entities/src/animals/hoglin.rs index 713b0eb8..517dd4cf 100644 --- a/minecraft-entities/src/animals/hoglin.rs +++ b/minecraft-entities/src/animals/hoglin.rs @@ -1,4 +1,3 @@ -use minecraft_protocol::packets::UUID; use super::*; #[derive(Default)] diff --git a/minecraft-entities/src/animals/horses.rs b/minecraft-entities/src/animals/horses.rs index 3b506838..72e872a3 100644 --- a/minecraft-entities/src/animals/horses.rs +++ b/minecraft-entities/src/animals/horses.rs @@ -18,6 +18,36 @@ pub struct Horse { pub variant: usize, } +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&AbstractHorse> { + match self { + AnyEntity::Horse(horse) => return Some(&horse), + AnyEntity::ZombieHorse(zombie_horse) => return Some(&zombie_horse.abstract_horse), + AnyEntity::SkeletonHorse(skeleton_horse) => return Some(&skeleton_horse.abstract_horse), + AnyEntity::Camel(camel) => return Some(&camel.abstract_horse), + _ => (), + } + if let Some(chested_horse) = self.try_as_entity_ref::() { + return Some(chested_horse.get_abstract_horse()) + } + None + } + + fn try_as_entity_mut(&mut self) -> Option<&mut AbstractHorse> { + match self { + AnyEntity::Horse(horse) => return Some(horse), + AnyEntity::ZombieHorse(zombie_horse) => return Some(&mut zombie_horse.abstract_horse), + AnyEntity::SkeletonHorse(skeleton_horse) => return Some(&mut skeleton_horse.abstract_horse), + AnyEntity::Camel(camel) => return Some(&mut camel.abstract_horse), + _ => (), + } + if let Some(chested_horse) = self.try_as_entity_mut::() { + return Some(chested_horse.get_abstract_horse_mut()) + } + None + } +} + #[derive(Default)] #[MinecraftEntity( parents { AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, @@ -53,6 +83,34 @@ pub struct ChestedHorse { pub has_chest: bool, } +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&ChestedHorse> { + match self { + AnyEntity::ChestedHorse(chested_horse) => return Some(&chested_horse), + AnyEntity::Mule(mule) => return Some(&mule.chested_horse), + AnyEntity::Donkey(donkey) => return Some(&donkey.chested_horse), + _ => (), + } + if let Some(lama) = self.try_as_entity_ref::() { + return Some(lama.get_chested_horse()) + } + None + } + + fn try_as_entity_mut(&mut self) -> Option<&mut ChestedHorse> { + match self { + AnyEntity::ChestedHorse(chested_horse) => return Some(chested_horse), + AnyEntity::Mule(mule) => return Some(&mut mule.chested_horse), + AnyEntity::Donkey(donkey) => return Some(&mut donkey.chested_horse), + _ => (), + } + if let Some(lama) = self.try_as_entity_mut::() { + return Some(lama.get_chested_horse_mut()) + } + None + } +} + #[derive(Default)] #[MinecraftEntity( parents { ChestedHorse, AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, @@ -74,9 +132,9 @@ pub struct Donkey { )] pub struct Llama { pub chested_horse: ChestedHorse, - /// Strength (number of columns of 3 slots in the llama's inventory once a chest is equipped) + /// Strength (number of columns of 3 slots in the llama's inventory once a chest is equipped) pub stength: u8, - /// Carpet color (a dye color, or -1 if no carpet equipped) + /// Carpet color (a dye color, or -1 if no carpet equipped) pub carpet_color: i16, pub variant: u8, } @@ -92,6 +150,24 @@ impl Default for Llama { } } +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&Llama> { + match self { + AnyEntity::Llama(llama) => Some(&llama), + AnyEntity::TraderLlama(trader_llama) => Some(&trader_llama.llama), + _ => None, + } + } + + fn try_as_entity_mut(&mut self) -> Option<&mut Llama> { + match self { + AnyEntity::Llama(llama) => Some(llama), + AnyEntity::TraderLlama(trader_llama) => Some(&mut trader_llama.llama), + _ => None, + } + } +} + #[derive(Default)] #[MinecraftEntity( parents { Llama, ChestedHorse, AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, diff --git a/minecraft-entities/src/animals/mod.rs b/minecraft-entities/src/animals/mod.rs index 4af770a2..ca099e88 100644 --- a/minecraft-entities/src/animals/mod.rs +++ b/minecraft-entities/src/animals/mod.rs @@ -84,3 +84,21 @@ pub struct TameableAnimal { pub action_mask: u8, pub owner: Option, } + +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&TameableAnimal> { + match self { + AnyEntity::TameableAnimal(tameable_animal) => return Some(&tameable_animal), + _ => (), + } + None + } + + fn try_as_entity_mut(&mut self) -> Option<&mut TameableAnimal> { + match self { + AnyEntity::TameableAnimal(tameable_animal) => return Some(tameable_animal), + _ => (), + } + None + } +} diff --git a/minecraft-entities/src/animals/ocelot.rs b/minecraft-entities/src/animals/ocelot.rs index 735d539a..e8c3bab8 100644 --- a/minecraft-entities/src/animals/ocelot.rs +++ b/minecraft-entities/src/animals/ocelot.rs @@ -1,4 +1,3 @@ -use minecraft_protocol::packets::UUID; use super::*; #[derive(Default)] diff --git a/minecraft-entities/src/animals/panda.rs b/minecraft-entities/src/animals/panda.rs index ca0ce7f2..dd89fe66 100644 --- a/minecraft-entities/src/animals/panda.rs +++ b/minecraft-entities/src/animals/panda.rs @@ -1,4 +1,3 @@ -use minecraft_protocol::packets::UUID; use super::*; #[derive(Default)] diff --git a/minecraft-entities/src/animals/sheep.rs b/minecraft-entities/src/animals/sheep.rs index 537a17a9..35309593 100644 --- a/minecraft-entities/src/animals/sheep.rs +++ b/minecraft-entities/src/animals/sheep.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - inheritable, parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Sheep { pub animal: Animal, diff --git a/minecraft-entities/src/animals/water_animal.rs b/minecraft-entities/src/animals/water_animal.rs index 905700f5..bf5b335b 100644 --- a/minecraft-entities/src/animals/water_animal.rs +++ b/minecraft-entities/src/animals/water_animal.rs @@ -8,6 +8,34 @@ pub struct WaterAnimal { pub pathfinder_mob: PathfinderMob, } +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&WaterAnimal> { + match self { + AnyEntity::WaterAnimal(water_animal) => return Some(&water_animal), + AnyEntity::Dolphin(dolphin) => return Some(&dolphin.water_animal), + AnyEntity::Squid(squid) => return Some(&squid.water_animal), + _ => (), + } + if let Some(fish) = self.try_as_entity_ref::() { + return Some(fish.get_water_animal()) + } + None + } + + fn try_as_entity_mut(&mut self) -> Option<&mut WaterAnimal> { + match self { + AnyEntity::WaterAnimal(water_animal) => return Some(water_animal), + AnyEntity::Dolphin(dolphin) => return Some(&mut dolphin.water_animal), + AnyEntity::Squid(squid) => return Some(&mut squid.water_animal), + _ => (), + } + if let Some(fish) = self.try_as_entity_mut::() { + return Some(fish.get_water_animal_mut()) + } + None + } +} + #[derive(Default)] #[MinecraftEntity( parents { WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, @@ -36,6 +64,32 @@ pub struct AbstractFish { pub from_bucket: bool, } +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&AbstractFish> { + match self { + AnyEntity::AbstractFish(abstract_fish) => Some(&abstract_fish), + AnyEntity::Cod(cod) => Some(&cod.abstract_fish), + AnyEntity::PufferFish(puffer_fish) => Some(&puffer_fish.abstract_fish), + AnyEntity::Salmon(salmon) => Some(&salmon.abstract_fish), + AnyEntity::TropicalFish(tropical_fish) => Some(&tropical_fish.abstract_fish), + AnyEntity::Tadpole(tadpole) => Some(&tadpole.abstract_fish), + _ => None, + } + } + + fn try_as_entity_mut(&mut self) -> Option<&mut AbstractFish> { + match self { + AnyEntity::AbstractFish(abstract_fish) => Some(abstract_fish), + AnyEntity::Cod(cod) => Some(&mut cod.abstract_fish), + AnyEntity::PufferFish(puffer_fish) => Some(&mut puffer_fish.abstract_fish), + AnyEntity::Salmon(salmon) => Some(&mut salmon.abstract_fish), + AnyEntity::TropicalFish(tropical_fish) => Some(&mut tropical_fish.abstract_fish), + AnyEntity::Tadpole(tadpole) => Some(&mut tadpole.abstract_fish), + _ => None, + } + } +} + #[derive(Default)] #[MinecraftEntity( parents { AbstractFish, WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, diff --git a/minecraft-entities/src/entity.rs b/minecraft-entities/src/entity.rs index f8684788..f667a8b5 100644 --- a/minecraft-entities/src/entity.rs +++ b/minecraft-entities/src/entity.rs @@ -1,7 +1,7 @@ use super::*; #[MinecraftEntity( - inheritable, parents {}, + inheritable )] pub struct Entity { pub position: Position, From 293fb892f42e54cf5d765ce4b115dd2df944df58 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Fri, 10 Nov 2023 19:31:58 +0100 Subject: [PATCH 31/89] Fix errors --- minecraft-entities/src/animals/cow.rs | 10 ++- minecraft-entities/src/animals/horses.rs | 22 +++--- minecraft-entities/src/animals/mod.rs | 10 ++- .../src/animals/water_animal.rs | 8 +- minecraft-entities/src/boat.rs | 6 +- minecraft-entities/src/display.rs | 10 +-- minecraft-entities/src/entity.rs | 2 + minecraft-entities/src/item.rs | 6 +- minecraft-entities/src/lib.rs | 10 ++- minecraft-entities/src/living_entity.rs | 10 ++- minecraft-entities/src/mobs/flying.rs | 4 +- minecraft-entities/src/mobs/mod.rs | 46 +++++------ minecraft-entities/src/mobs/villagers.rs | 20 +++++ .../src/monsters/base_piglin.rs | 2 - minecraft-entities/src/monsters/guardian.rs | 18 +++++ minecraft-entities/src/monsters/mod.rs | 33 +++++++- minecraft-entities/src/monsters/piglin.rs | 20 +++++ minecraft-entities/src/monsters/raider.rs | 76 +++++++++++++++++++ minecraft-entities/src/monsters/skeleton.rs | 22 ++++++ minecraft-entities/src/monsters/zombies.rs | 24 ++++++ 20 files changed, 293 insertions(+), 66 deletions(-) delete mode 100644 minecraft-entities/src/monsters/base_piglin.rs diff --git a/minecraft-entities/src/animals/cow.rs b/minecraft-entities/src/animals/cow.rs index 4041093b..8e1a90be 100644 --- a/minecraft-entities/src/animals/cow.rs +++ b/minecraft-entities/src/animals/cow.rs @@ -13,7 +13,15 @@ impl TryAsEntityRef for AnyEntity { match self { AnyEntity::Cow(cow) => return Some(&cow), AnyEntity::Mooshroom(mooshroom) => return Some(&mooshroom.cow), - _ => (), + _ => None, + } + } + + fn try_as_entity_mut(&mut self) -> Option<&mut Cow> { + match self { + AnyEntity::Cow(cow) => return Some(cow), + AnyEntity::Mooshroom(mooshroom) => return Some(&mut mooshroom.cow), + _ => None, } } } diff --git a/minecraft-entities/src/animals/horses.rs b/minecraft-entities/src/animals/horses.rs index 72e872a3..45d23f84 100644 --- a/minecraft-entities/src/animals/horses.rs +++ b/minecraft-entities/src/animals/horses.rs @@ -21,28 +21,30 @@ pub struct Horse { impl TryAsEntityRef for AnyEntity { fn try_as_entity_ref(&self) -> Option<&AbstractHorse> { match self { - AnyEntity::Horse(horse) => return Some(&horse), + AnyEntity::AbstractHorse(abstract_horse) => return Some(&abstract_horse), + AnyEntity::Horse(horse) => return Some(&horse.abstract_horse), AnyEntity::ZombieHorse(zombie_horse) => return Some(&zombie_horse.abstract_horse), AnyEntity::SkeletonHorse(skeleton_horse) => return Some(&skeleton_horse.abstract_horse), AnyEntity::Camel(camel) => return Some(&camel.abstract_horse), _ => (), } - if let Some(chested_horse) = self.try_as_entity_ref::() { - return Some(chested_horse.get_abstract_horse()) + if let Some(chested_horse) = >::try_as_entity_ref(self) { + return Some(&chested_horse.abstract_horse) } None } fn try_as_entity_mut(&mut self) -> Option<&mut AbstractHorse> { match self { - AnyEntity::Horse(horse) => return Some(horse), + AnyEntity::AbstractHorse(abstract_horse) => return Some(abstract_horse), + AnyEntity::Horse(horse) => return Some(&mut horse.abstract_horse), AnyEntity::ZombieHorse(zombie_horse) => return Some(&mut zombie_horse.abstract_horse), AnyEntity::SkeletonHorse(skeleton_horse) => return Some(&mut skeleton_horse.abstract_horse), AnyEntity::Camel(camel) => return Some(&mut camel.abstract_horse), _ => (), } - if let Some(chested_horse) = self.try_as_entity_mut::() { - return Some(chested_horse.get_abstract_horse_mut()) + if let Some(chested_horse) = >::try_as_entity_mut(self) { + return Some(&mut chested_horse.abstract_horse) } None } @@ -91,8 +93,8 @@ impl TryAsEntityRef for AnyEntity { AnyEntity::Donkey(donkey) => return Some(&donkey.chested_horse), _ => (), } - if let Some(lama) = self.try_as_entity_ref::() { - return Some(lama.get_chested_horse()) + if let Some(llama) = >::try_as_entity_ref(self) { + return Some(&llama.chested_horse) } None } @@ -104,8 +106,8 @@ impl TryAsEntityRef for AnyEntity { AnyEntity::Donkey(donkey) => return Some(&mut donkey.chested_horse), _ => (), } - if let Some(lama) = self.try_as_entity_mut::() { - return Some(lama.get_chested_horse_mut()) + if let Some(llama) = >::try_as_entity_mut(self) { + return Some(&mut llama.chested_horse) } None } diff --git a/minecraft-entities/src/animals/mod.rs b/minecraft-entities/src/animals/mod.rs index ca099e88..9a5a3a5d 100644 --- a/minecraft-entities/src/animals/mod.rs +++ b/minecraft-entities/src/animals/mod.rs @@ -59,9 +59,10 @@ impl TryAsEntityRef for AnyEntity { AnyEntity::Animal(animal) => return Some(&animal), _ => (), } - if let Some(tameable_animal) = self.try_as_entity_ref::() { - return tameable_animal.animal.try_as_entity_ref(); + if let Some(tameable_animal) = >::try_as_entity_ref(self) { + return Some(&tameable_animal.animal) } + None } fn try_as_entity_mut(&mut self) -> Option<&mut Animal> { @@ -69,9 +70,10 @@ impl TryAsEntityRef for AnyEntity { AnyEntity::Animal(animal) => return Some(animal), _ => (), } - if let Some(tameable_animal) = self.try_as_entity_mut::() { - return tameable_animal.animal.try_as_entity_mut(); + if let Some(tameable_animal) = >::try_as_entity_mut(self) { + return Some(&mut tameable_animal.animal) } + None } } diff --git a/minecraft-entities/src/animals/water_animal.rs b/minecraft-entities/src/animals/water_animal.rs index bf5b335b..fe262c85 100644 --- a/minecraft-entities/src/animals/water_animal.rs +++ b/minecraft-entities/src/animals/water_animal.rs @@ -16,8 +16,8 @@ impl TryAsEntityRef for AnyEntity { AnyEntity::Squid(squid) => return Some(&squid.water_animal), _ => (), } - if let Some(fish) = self.try_as_entity_ref::() { - return Some(fish.get_water_animal()) + if let Some(fish) = >::try_as_entity_ref(self) { + return Some(&fish.water_animal) } None } @@ -29,8 +29,8 @@ impl TryAsEntityRef for AnyEntity { AnyEntity::Squid(squid) => return Some(&mut squid.water_animal), _ => (), } - if let Some(fish) = self.try_as_entity_mut::() { - return Some(fish.get_water_animal_mut()) + if let Some(fish) = >::try_as_entity_mut(self) { + return Some(&mut fish.water_animal) } None } diff --git a/minecraft-entities/src/boat.rs b/minecraft-entities/src/boat.rs index b9a2a28e..bd58e0e3 100644 --- a/minecraft-entities/src/boat.rs +++ b/minecraft-entities/src/boat.rs @@ -31,10 +31,10 @@ impl Default for Boat { } impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&Entity> { + fn try_as_entity_ref(&self) -> Option<&Boat> { match self { - AnyEntity::Boat(boat) => Some(&boat.entity), - AnyEntity::ChestBoat(chest_boat) => Some(&chest_boat.boat.entity), + AnyEntity::Boat(boat) => Some(boat), + AnyEntity::ChestBoat(chest_boat) => Some(&chest_boat.boat), _ => None, } } diff --git a/minecraft-entities/src/display.rs b/minecraft-entities/src/display.rs index 679c7eeb..44d06482 100644 --- a/minecraft-entities/src/display.rs +++ b/minecraft-entities/src/display.rs @@ -53,12 +53,12 @@ impl Default for Display { } impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&Entity> { + fn try_as_entity_ref(&self) -> Option<&Display> { match self { - AnyEntity::Display(display) => Some(&display.entity), - AnyEntity::BlockDisplay(block_display) => Some(&block_display.display.entity), - AnyEntity::ItemDisplay(item_display) => Some(&item_display.display.entity), - AnyEntity::TextDisplay(text_display) => Some(&text_display.display.entity), + AnyEntity::Display(display) => Some(display), + AnyEntity::BlockDisplay(block_display) => Some(&block_display.display), + AnyEntity::ItemDisplay(item_display) => Some(&item_display.display), + AnyEntity::TextDisplay(text_display) => Some(&text_display.display), _ => None, } } diff --git a/minecraft-entities/src/entity.rs b/minecraft-entities/src/entity.rs index f667a8b5..97fbee28 100644 --- a/minecraft-entities/src/entity.rs +++ b/minecraft-entities/src/entity.rs @@ -47,6 +47,7 @@ impl TryAsEntityRef for AnyEntity { fn try_as_entity_ref(&self) -> Option<&Entity> { Some(match self { AnyEntity::Entity(entity) => entity, + AnyEntity::Interaction(interaction) => interaction.get_entity(), AnyEntity::Display(display) => display.get_entity(), AnyEntity::BlockDisplay(block_display) => block_display.get_entity(), AnyEntity::ItemDisplay(item_display) => item_display.get_entity(), @@ -182,6 +183,7 @@ impl TryAsEntityRef for AnyEntity { fn try_as_entity_mut(&mut self) -> Option<&mut Entity> { Some(match self { AnyEntity::Entity(entity) => entity, + AnyEntity::Interaction(interaction) => interaction.get_entity_mut(), AnyEntity::Display(display) => display.get_entity_mut(), AnyEntity::BlockDisplay(block_display) => block_display.get_entity_mut(), AnyEntity::ItemDisplay(item_display) => item_display.get_entity_mut(), diff --git a/minecraft-entities/src/item.rs b/minecraft-entities/src/item.rs index b90df0d9..8d95d2bf 100644 --- a/minecraft-entities/src/item.rs +++ b/minecraft-entities/src/item.rs @@ -11,10 +11,10 @@ pub struct ItemFrame { } impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&Entity> { + fn try_as_entity_ref(&self) -> Option<&ItemFrame> { match self { - AnyEntity::ItemFrame(item_frame) => Some(&item_frame.entity), - AnyEntity::GlowingItemFrame(glowing_item_frame) => Some(&glowing_item_frame.item_frame.entity), + AnyEntity::ItemFrame(item_frame) => Some(&item_frame), + AnyEntity::GlowingItemFrame(glowing_item_frame) => Some(&glowing_item_frame.item_frame), _ => None, } } diff --git a/minecraft-entities/src/lib.rs b/minecraft-entities/src/lib.rs index 7d557c4b..99066732 100644 --- a/minecraft-entities/src/lib.rs +++ b/minecraft-entities/src/lib.rs @@ -87,15 +87,16 @@ impl Handler where AnyEntity: TryAsEntityRef { } pub async fn observe(&self, observer: fn(&T)) { - let fut = self.world.observe_entity(self.id, |entity| { - - }); - fut.await; + //let fut = self.world.observe_entity(self.id, |entity| { + // + //}); + //fut.await; } } pub enum AnyEntity { Entity(Entity), + Interaction(Interaction), Display(Display), BlockDisplay(BlockDisplay), ItemDisplay(ItemDisplay), @@ -232,6 +233,7 @@ impl AnyEntity { pub fn as_entity(&self) -> &Entity { match self { AnyEntity::Entity(entity) => entity, + AnyEntity::Interaction(interaction) => interaction.get_entity(), AnyEntity::Display(display) => display.get_entity(), AnyEntity::BlockDisplay(block_display) => block_display.get_entity(), AnyEntity::ItemDisplay(item_display) => item_display.get_entity(), diff --git a/minecraft-entities/src/living_entity.rs b/minecraft-entities/src/living_entity.rs index fac081ea..ea259a37 100644 --- a/minecraft-entities/src/living_entity.rs +++ b/minecraft-entities/src/living_entity.rs @@ -40,9 +40,10 @@ impl TryAsEntityRef for AnyEntity { AnyEntity::Player(player) => return Some(&player.living_entity), _ => (), } - if let Some(mob) = self.try_as_entity_ref::() { - return mob.living_entity.try_as_entity_ref(); + if let Some(mob) = >::try_as_entity_ref(self) { + return Some(&mob.living_entity) } + None } fn try_as_entity_mut(&mut self) -> Option<&mut LivingEntity> { @@ -51,9 +52,10 @@ impl TryAsEntityRef for AnyEntity { AnyEntity::Player(player) => return Some(&mut player.living_entity), _ => (), } - if let Some(mob) = self.try_as_entity_mut::() { - return mob.living_entity.try_as_entity_mut(); + if let Some(mob) = >::try_as_entity_mut(self) { + return Some(&mut mob.living_entity) } + None } } diff --git a/minecraft-entities/src/mobs/flying.rs b/minecraft-entities/src/mobs/flying.rs index c3598f84..409e9e8f 100644 --- a/minecraft-entities/src/mobs/flying.rs +++ b/minecraft-entities/src/mobs/flying.rs @@ -12,8 +12,8 @@ impl TryAsEntityRef for AnyEntity { fn try_as_entity_ref(&self) -> Option<&Flying> { match self { AnyEntity::Flying(flying) => Some(&flying), - AnyEntity::Bat(bat) => Some(&bat.flying), AnyEntity::Ghast(ghast) => Some(&ghast.flying), + AnyEntity::Phantom(phantom) => Some(&phantom.flying), _ => None, } } @@ -21,8 +21,8 @@ impl TryAsEntityRef for AnyEntity { fn try_as_entity_mut(&mut self) -> Option<&mut Flying> { match self { AnyEntity::Flying(flying) => Some(flying), - AnyEntity::Bat(bat) => Some(&mut bat.flying), AnyEntity::Ghast(ghast) => Some(&mut ghast.flying), + AnyEntity::Phantom(phantom) => Some(&mut phantom.flying), _ => None, } } diff --git a/minecraft-entities/src/mobs/mod.rs b/minecraft-entities/src/mobs/mod.rs index fb76cd8c..245d7561 100644 --- a/minecraft-entities/src/mobs/mod.rs +++ b/minecraft-entities/src/mobs/mod.rs @@ -30,11 +30,10 @@ impl TryAsEntityRef for AnyEntity { AnyEntity::Mob(mob) => return Some(&mob), _ => (), } - if let Some(ambient_creature) = self.try_as_entity_ref::() { - return ambient_creature.mob.try_as_entity_ref(); - } - if let Some(pathfinder_mob) = self.try_as_entity_ref::() { - return pathfinder_mob.mob.try_as_entity_ref(); + if let Some(ambient_creature) = >::try_as_entity_ref(self) { + return Some(&ambient_creature.mob) + } else if let Some(pathfinder_mob) = >::try_as_entity_ref(self) { + return Some(&pathfinder_mob.mob) } None } @@ -44,13 +43,16 @@ impl TryAsEntityRef for AnyEntity { AnyEntity::Mob(mob) => return Some(mob), _ => (), } - if let Some(ambient_creature) = self.try_as_entity_mut::() { - return ambient_creature.mob.try_as_entity_mut(); - } - if let Some(pathfinder_mob) = self.try_as_entity_mut::() { - return pathfinder_mob.mob.try_as_entity_mut(); - } - None + let result: Option<&mut Mob> = + if let Some(ambient_creature) = >::try_as_entity_mut(self) { + Some(&mut ambient_creature.mob) + } else if let Some(pathfinder_mob) = >::try_as_entity_mut(self) { + Some(&mut pathfinder_mob.mob) + } else { + None + }; + + result } } @@ -96,8 +98,8 @@ impl TryAsEntityRef for AnyEntity { AnyEntity::PathfinderMob(pathfinder_mob) => return Some(&pathfinder_mob), _ => (), } - if let Some(ageable_mob) = self.try_as_entity_ref::() { - return ageable_mob.pathfinder_mob.try_as_entity_ref(); + if let Some(ageable_mob) = >::try_as_entity_ref(self) { + return Some(&ageable_mob.pathfinder_mob) } None } @@ -107,8 +109,8 @@ impl TryAsEntityRef for AnyEntity { AnyEntity::PathfinderMob(pathfinder_mob) => return Some(pathfinder_mob), _ => (), } - if let Some(ageable_mob) = self.try_as_entity_mut::() { - return ageable_mob.pathfinder_mob.try_as_entity_mut(); + if let Some(ageable_mob) = >::try_as_entity_mut(self) { + return Some(&mut ageable_mob.pathfinder_mob) } None } @@ -126,22 +128,22 @@ pub struct AgeableMob { impl TryAsEntityRef for AnyEntity { fn try_as_entity_ref(&self) -> Option<&AgeableMob> { match self { - AnyEntity::AgeableMob(ageable_mob) => return Some(&ageable_mob), + AnyEntity::AgeableMob(ageable_mob) => return Some(ageable_mob), _ => (), } - if let Some(villager) = self.try_as_entity_ref::() { - return villager.try_as_entity_ref(); + if let Some(abstract_villager) = >::try_as_entity_ref(self) { + return Some(&abstract_villager.ageable_mob) } None } fn try_as_entity_mut(&mut self) -> Option<&mut AgeableMob> { match self { - AnyEntity::AgeableMob(ageable_mob) => return Some(&mut ageable_mob), + AnyEntity::AgeableMob(ageable_mob) => return Some(ageable_mob), _ => (), } - if let Some(villager) = self.try_as_entity_mut::() { - return villager.try_as_entity_mut(); + if let Some(abstract_villager) = >::try_as_entity_mut(self) { + return Some(&mut abstract_villager.ageable_mob) } None } diff --git a/minecraft-entities/src/mobs/villagers.rs b/minecraft-entities/src/mobs/villagers.rs index 9f856a5a..96614641 100644 --- a/minecraft-entities/src/mobs/villagers.rs +++ b/minecraft-entities/src/mobs/villagers.rs @@ -9,6 +9,26 @@ pub struct AbstractVillager { pub head_shake_timer: u32, } +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&AbstractVillager> { + match self { + AnyEntity::AbstractVillager(abstract_villager) => return Some(&abstract_villager), + AnyEntity::Villager(villager) => return Some(&villager.abstract_villager), + AnyEntity::WanderingTrader(wandering_trader) => return Some(&wandering_trader.abstract_villager), + _ => None, + } + } + + fn try_as_entity_mut(&mut self) -> Option<&mut AbstractVillager> { + match self { + AnyEntity::AbstractVillager(abstract_villager) => return Some(abstract_villager), + AnyEntity::Villager(villager) => return Some(&mut villager.abstract_villager), + AnyEntity::WanderingTrader(wandering_trader) => return Some(&mut wandering_trader.abstract_villager), + _ => None, + } + } +} + #[derive(Default)] #[MinecraftEntity( parents { AbstractVillager, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, diff --git a/minecraft-entities/src/monsters/base_piglin.rs b/minecraft-entities/src/monsters/base_piglin.rs deleted file mode 100644 index c5d584ae..00000000 --- a/minecraft-entities/src/monsters/base_piglin.rs +++ /dev/null @@ -1,2 +0,0 @@ -use super::*; - diff --git a/minecraft-entities/src/monsters/guardian.rs b/minecraft-entities/src/monsters/guardian.rs index b5503551..3eee9923 100644 --- a/minecraft-entities/src/monsters/guardian.rs +++ b/minecraft-entities/src/monsters/guardian.rs @@ -10,6 +10,24 @@ pub struct Guardian { pub target_eid: Eid, } +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&Guardian> { + match self { + AnyEntity::Guardian(guardian) => Some(&guardian), + AnyEntity::ElderGuardian(elder_guardian) => Some(&elder_guardian.guardian), + _ => None, + } + } + + fn try_as_entity_mut(&mut self) -> Option<&mut Guardian> { + match self { + AnyEntity::Guardian(guardian) => Some(guardian), + AnyEntity::ElderGuardian(elder_guardian) => Some(&mut elder_guardian.guardian), + _ => None, + } + } +} + #[derive(Default)] #[MinecraftEntity( parents { Guardian, Monster, PathfinderMob, Mob, LivingEntity, Entity }, diff --git a/minecraft-entities/src/monsters/mod.rs b/minecraft-entities/src/monsters/mod.rs index 9a0ea762..c575ec63 100644 --- a/minecraft-entities/src/monsters/mod.rs +++ b/minecraft-entities/src/monsters/mod.rs @@ -1,7 +1,5 @@ use super::*; -mod base_piglin; -pub use base_piglin::*; mod piglin; pub use piglin::*; mod blaze; @@ -44,3 +42,34 @@ pub use enderman::*; pub struct Monster { pub pathfinder_mob: PathfinderMob, } + +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&Monster> { + match self { + AnyEntity::Monster(monster) => return Some(&monster), + _ => (), + } + if let Some(base_piglin) = >::try_as_entity_ref(self) { + return Some(&base_piglin.monster) + } + if let Some(guardian) = >::try_as_entity_ref(self) { + return Some(&guardian.monster) + } + None + } + + fn try_as_entity_mut(&mut self) -> Option<&mut Monster> { + match self { + AnyEntity::Monster(monster) => return Some(monster), + _ => (), + } + if let Some(base_piglin) = >::try_as_entity_mut(self) { + return Some(&mut base_piglin.monster) + } + if let Some(guardian) = >::try_as_entity_mut(self) { + return Some(&mut guardian.monster) + } + None + } +} + diff --git a/minecraft-entities/src/monsters/piglin.rs b/minecraft-entities/src/monsters/piglin.rs index 91f407b5..0bedfa76 100644 --- a/minecraft-entities/src/monsters/piglin.rs +++ b/minecraft-entities/src/monsters/piglin.rs @@ -9,6 +9,26 @@ pub struct BasePiglin { pub is_immune: bool, } +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&BasePiglin> { + match self { + AnyEntity::BasePiglin(base_piglin) => Some(&base_piglin), + AnyEntity::Piglin(piglin) => Some(&piglin.base_piglin), + AnyEntity::PiglinBrute(piglin_brute) => Some(&piglin_brute.base_piglin), + _ => None, + } + } + + fn try_as_entity_mut(&mut self) -> Option<&mut BasePiglin> { + match self { + AnyEntity::BasePiglin(base_piglin) => Some(base_piglin), + AnyEntity::Piglin(piglin) => Some(&mut piglin.base_piglin), + AnyEntity::PiglinBrute(piglin_brute) => Some(&mut piglin_brute.base_piglin), + _ => None, + } + } +} + #[derive(Default)] #[MinecraftEntity( parents { BasePiglin, Monster, PathfinderMob, Mob, LivingEntity, Entity }, diff --git a/minecraft-entities/src/monsters/raider.rs b/minecraft-entities/src/monsters/raider.rs index 33e19fbd..7ed0a302 100644 --- a/minecraft-entities/src/monsters/raider.rs +++ b/minecraft-entities/src/monsters/raider.rs @@ -9,6 +9,32 @@ pub struct Raider { pub is_celebrating: bool, } +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&Raider> { + match self { + AnyEntity::Raider(raider) => return Some(&raider), + AnyEntity::Witch(witch) => return Some(&witch.raider), + _ => (), + } + if let Some(abstract_illager) = >::try_as_entity_ref(self) { + return Some(&abstract_illager.raider) + } + None + } + + fn try_as_entity_mut(&mut self) -> Option<&mut Raider> { + match self { + AnyEntity::Raider(raider) => return Some(raider), + AnyEntity::Witch(witch) => return Some(&mut witch.raider), + _ => (), + } + if let Some(abstract_illager) = >::try_as_entity_mut(self) { + return Some(&mut abstract_illager.raider) + } + None + } +} + #[derive(Default)] #[MinecraftEntity( parents { Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity }, @@ -26,6 +52,34 @@ pub struct AbstractIllager { pub raider: Raider, } +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&AbstractIllager> { + match self { + AnyEntity::AbstractIllager(abstract_illager) => return Some(&abstract_illager), + AnyEntity::Vindicator(vindicator) => return Some(&vindicator.abstract_illager), + AnyEntity::Pillager(pillager) => return Some(&pillager.abstract_illager), + _ => (), + } + if let Some(spellcaster_illager) = >::try_as_entity_ref(self) { + return Some(&spellcaster_illager.abstract_illager) + } + None + } + + fn try_as_entity_mut(&mut self) -> Option<&mut AbstractIllager> { + match self { + AnyEntity::AbstractIllager(abstract_illager) => return Some(abstract_illager), + AnyEntity::Vindicator(vindicator) => return Some(&mut vindicator.abstract_illager), + AnyEntity::Pillager(pillager) => return Some(&mut pillager.abstract_illager), + _ => (), + } + if let Some(spellcaster_illager) = >::try_as_entity_mut(self) { + return Some(&mut spellcaster_illager.abstract_illager) + } + None + } +} + #[derive(Default)] #[MinecraftEntity( parents { AbstractIllager, Monster, PathfinderMob, Mob, LivingEntity, Entity }, @@ -52,6 +106,28 @@ pub struct SpellcasterIllager { pub spell: u8, } +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&SpellcasterIllager> { + match self { + AnyEntity::SpellcasterIllager(spellcaster_illager) => Some(&spellcaster_illager), + AnyEntity::Illusioner(illusioner) => Some(&illusioner.spellcaster_illager), + AnyEntity::Ravager(ravager) => Some(&ravager.spellcaster_illager), + AnyEntity::Evoker(evoker) => Some(&evoker.spellcaster_illager), + _ => None, + } + } + + fn try_as_entity_mut(&mut self) -> Option<&mut SpellcasterIllager> { + match self { + AnyEntity::SpellcasterIllager(spellcaster_illager) => Some(spellcaster_illager), + AnyEntity::Illusioner(illusioner) => Some(&mut illusioner.spellcaster_illager), + AnyEntity::Ravager(ravager) => Some(&mut ravager.spellcaster_illager), + AnyEntity::Evoker(evoker) => Some(&mut evoker.spellcaster_illager), + _ => None, + } + } +} + #[derive(Default)] #[MinecraftEntity( parents { SpellcasterIllager, AbstractIllager, Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity }, diff --git a/minecraft-entities/src/monsters/skeleton.rs b/minecraft-entities/src/monsters/skeleton.rs index 13792990..41573ea5 100644 --- a/minecraft-entities/src/monsters/skeleton.rs +++ b/minecraft-entities/src/monsters/skeleton.rs @@ -8,6 +8,28 @@ pub struct AbstractSkeleton { pub monster: Monster, } +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&AbstractSkeleton> { + match self { + AnyEntity::AbstractSkeleton(abstract_skeleton) => Some(&abstract_skeleton), + AnyEntity::Skeleton(skeleton) => Some(&skeleton.abstract_skeleton), + AnyEntity::WitherSkeleton(wither_skeleton) => Some(&wither_skeleton.abstract_skeleton), + AnyEntity::Stray(stray) => Some(&stray.abstract_skeleton), + _ => None, + } + } + + fn try_as_entity_mut(&mut self) -> Option<&mut AbstractSkeleton> { + match self { + AnyEntity::AbstractSkeleton(abstract_skeleton) => Some(abstract_skeleton), + AnyEntity::Skeleton(skeleton) => Some(&mut skeleton.abstract_skeleton), + AnyEntity::WitherSkeleton(wither_skeleton) => Some(&mut wither_skeleton.abstract_skeleton), + AnyEntity::Stray(stray) => Some(&mut stray.abstract_skeleton), + _ => None, + } + } +} + #[derive(Default)] #[MinecraftEntity( parents { AbstractSkeleton, Monster, PathfinderMob, Mob, LivingEntity, Entity }, diff --git a/minecraft-entities/src/monsters/zombies.rs b/minecraft-entities/src/monsters/zombies.rs index 61f7c6d0..cbaf7585 100644 --- a/minecraft-entities/src/monsters/zombies.rs +++ b/minecraft-entities/src/monsters/zombies.rs @@ -11,6 +11,30 @@ pub struct Zombie { pub is_becoming_drowned: bool, } +impl TryAsEntityRef for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&Zombie> { + match self { + AnyEntity::Zombie(zombie) => Some(&zombie), + AnyEntity::ZombieVillager(zombie_villager) => Some(&zombie_villager.zombie), + AnyEntity::Husk(husk) => Some(&husk.zombie), + AnyEntity::Drowned(drowned) => Some(&drowned.zombie), + AnyEntity::ZombifiedPiglin(zombified_piglin) => Some(&zombified_piglin.zombie), + _ => None, + } + } + + fn try_as_entity_mut(&mut self) -> Option<&mut Zombie> { + match self { + AnyEntity::Zombie(zombie) => Some(zombie), + AnyEntity::ZombieVillager(zombie_villager) => Some(&mut zombie_villager.zombie), + AnyEntity::Husk(husk) => Some(&mut husk.zombie), + AnyEntity::Drowned(drowned) => Some(&mut drowned.zombie), + AnyEntity::ZombifiedPiglin(zombified_piglin) => Some(&mut zombified_piglin.zombie), + _ => None, + } + } +} + #[derive(Default)] #[MinecraftEntity( parents { Zombie, Monster, PathfinderMob, Mob, LivingEntity, Entity }, From a110ce8de0f5dc4b858aecce214404646449df1f Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 00:58:40 +0100 Subject: [PATCH 32/89] Make it compile --- minecraft-entities/src/mobs/mod.rs | 19 ++++++++----------- minecraft-entities/src/monsters/mod.rs | 8 ++++---- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/minecraft-entities/src/mobs/mod.rs b/minecraft-entities/src/mobs/mod.rs index 245d7561..e6945b70 100644 --- a/minecraft-entities/src/mobs/mod.rs +++ b/minecraft-entities/src/mobs/mod.rs @@ -43,16 +43,13 @@ impl TryAsEntityRef for AnyEntity { AnyEntity::Mob(mob) => return Some(mob), _ => (), } - let result: Option<&mut Mob> = - if let Some(ambient_creature) = >::try_as_entity_mut(self) { - Some(&mut ambient_creature.mob) - } else if let Some(pathfinder_mob) = >::try_as_entity_mut(self) { - Some(&mut pathfinder_mob.mob) - } else { - None - }; - - result + if >::try_as_entity_ref(self).is_some() { + return >::try_as_entity_mut(self).map(|ambient_creature| &mut ambient_creature.mob) + } + if >::try_as_entity_ref(self).is_some() { + return >::try_as_entity_mut(self).map(|pathfinder_mob| &mut pathfinder_mob.mob) + } + None } } @@ -67,7 +64,7 @@ pub struct AmbientCreature { impl TryAsEntityRef for AnyEntity { fn try_as_entity_ref(&self) -> Option<&AmbientCreature> { match self { - AnyEntity::AmbientCreature(ambient_creature) => return Some(&ambient_creature), + AnyEntity::AmbientCreature(ambient_creature) => return Some(ambient_creature), AnyEntity::Bat(bat) => return Some(&bat.ambient_creature), _ => (), } diff --git a/minecraft-entities/src/monsters/mod.rs b/minecraft-entities/src/monsters/mod.rs index c575ec63..bb383e68 100644 --- a/minecraft-entities/src/monsters/mod.rs +++ b/minecraft-entities/src/monsters/mod.rs @@ -63,11 +63,11 @@ impl TryAsEntityRef for AnyEntity { AnyEntity::Monster(monster) => return Some(monster), _ => (), } - if let Some(base_piglin) = >::try_as_entity_mut(self) { - return Some(&mut base_piglin.monster) + if >::try_as_entity_ref(self).is_some() { + return >::try_as_entity_mut(self).map(|piglin| &mut piglin.monster) } - if let Some(guardian) = >::try_as_entity_mut(self) { - return Some(&mut guardian.monster) + if >::try_as_entity_ref(self).is_some() { + return >::try_as_entity_mut(self).map(|guardian| &mut guardian.monster) } None } From 0c19ddc6ba2b66dedd135bf3ce86d1dd676eabd8 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 01:00:12 +0100 Subject: [PATCH 33/89] Make stuff public --- minecraft-entities/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/minecraft-entities/src/lib.rs b/minecraft-entities/src/lib.rs index 99066732..2c0fe26b 100644 --- a/minecraft-entities/src/lib.rs +++ b/minecraft-entities/src/lib.rs @@ -53,12 +53,12 @@ type CallBack = fn(O) -> Pin>>; type CallBack1 = fn(O, I) -> Pin>>; type CallBack2 = fn(O, I, J) -> Pin>>; -trait TryAsEntityRef { +pub trait TryAsEntityRef { fn try_as_entity_ref(&self) -> Option<&T>; fn try_as_entity_mut(&mut self) -> Option<&mut T>; } -trait WorldTest { +pub trait WorldTest { fn observe_entity(&self, eid: Eid, observer: fn(&AnyEntity)) -> dyn std::future::Future; fn mutate_entity(&self, eid: Eid, mutator: fn(&mut AnyEntity)) -> dyn std::future::Future; } From 8146affca8b74d1d532e34ee24f493c7046b0543 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 01:10:27 +0100 Subject: [PATCH 34/89] Remove hundreds of warnings --- minecraft-entities-derive/src/lib.rs | 11 +++++++++++ minecraft-entities/src/item.rs | 2 +- minecraft-entities/src/monsters/guardian.rs | 2 +- minecraft-entities/src/monsters/mod.rs | 2 -- minecraft-entities/src/monsters/piglin.rs | 2 +- minecraft-entities/src/monsters/raider.rs | 6 +++--- minecraft-entities/src/monsters/witch.rs | 2 -- 7 files changed, 17 insertions(+), 10 deletions(-) delete mode 100644 minecraft-entities/src/monsters/witch.rs diff --git a/minecraft-entities-derive/src/lib.rs b/minecraft-entities-derive/src/lib.rs index 0f9a99c7..cf348a91 100644 --- a/minecraft-entities-derive/src/lib.rs +++ b/minecraft-entities-derive/src/lib.rs @@ -143,6 +143,7 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { // Generate code for parent let parent = inherited.remove(0); let code: TokenStream = r#" + #[automatically_derived] impl ParentDescendant for This { fn get_parent(&self) -> &Parent { &self.parent } fn get_parent_mut(&mut self) -> &mut Parent { &mut self.parent } @@ -164,6 +165,7 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { // Generate code for higher inheritance levels let code: TokenStream = r#" + #[automatically_derived] impl InheritedDescendant for This { fn get_inherited(&self) -> &Inherited { self.parent.get_inherited() } fn get_inherited_mut(&mut self) -> &mut Inherited { self.parent.get_inherited_mut() } @@ -186,11 +188,13 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { if inheritable { // Generate descendant trait let code: TokenStream = r#" + #[automatically_derived] pub trait ThisDescendant { fn get_this(&self) -> &This; fn get_this_mut(&mut self) -> &mut This; } + #[automatically_derived] impl ThisDescendant for This { fn get_this(&self) -> &This { self } fn get_this_mut(&mut self) -> &mut This { self } @@ -205,6 +209,7 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { } else { // Implement TryAsEntityRef for this struct let code: TokenStream = r#" + #[automatically_derived] impl TryAsEntityRef for AnyEntity { fn try_as_entity_ref(&self) -> Option<&This> { match self { @@ -231,6 +236,7 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { // Generate ext trait let code: TokenStream = r#" + #[automatically_derived] pub trait ThisExt: Sized + Into> { fn methods() -> &'static ThisMethods; } @@ -284,6 +290,7 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { // Generate methods struct let code: TokenStream = r#" + #[automatically_derived] pub struct ThisMethods { } @@ -372,6 +379,8 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { } let mod_codes: TokenStream = mod_codes.into_iter().collect(); let mod_code: TokenStream = format!(r#" + #[allow(clippy::needless_update)] + #[automatically_derived] pub mod {struct_name}_methods {{ use super::{{ {} }}; }} @@ -385,6 +394,7 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { // Implement ext traits for ascendant in hierarchy.iter().peekable() { let code: TokenStream = format!(r#" + #[automatically_derived] impl AscendantExt for Handler {{ fn methods() -> &'static AscendantMethods {{ {struct_name}_methods::ASCENDANT_METHODS_FOR_THIS @@ -406,6 +416,7 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { // Implement conversion traits for ascendant in hierarchy.iter().skip(1) { let code: TokenStream = r#" + #[automatically_derived] impl From> for Handler { fn from(val: Handler) -> Self { val.assume_other() diff --git a/minecraft-entities/src/item.rs b/minecraft-entities/src/item.rs index 8d95d2bf..b280c4c9 100644 --- a/minecraft-entities/src/item.rs +++ b/minecraft-entities/src/item.rs @@ -13,7 +13,7 @@ pub struct ItemFrame { impl TryAsEntityRef for AnyEntity { fn try_as_entity_ref(&self) -> Option<&ItemFrame> { match self { - AnyEntity::ItemFrame(item_frame) => Some(&item_frame), + AnyEntity::ItemFrame(item_frame) => Some(item_frame), AnyEntity::GlowingItemFrame(glowing_item_frame) => Some(&glowing_item_frame.item_frame), _ => None, } diff --git a/minecraft-entities/src/monsters/guardian.rs b/minecraft-entities/src/monsters/guardian.rs index 3eee9923..1a9ec039 100644 --- a/minecraft-entities/src/monsters/guardian.rs +++ b/minecraft-entities/src/monsters/guardian.rs @@ -13,7 +13,7 @@ pub struct Guardian { impl TryAsEntityRef for AnyEntity { fn try_as_entity_ref(&self) -> Option<&Guardian> { match self { - AnyEntity::Guardian(guardian) => Some(&guardian), + AnyEntity::Guardian(guardian) => Some(guardian), AnyEntity::ElderGuardian(elder_guardian) => Some(&elder_guardian.guardian), _ => None, } diff --git a/minecraft-entities/src/monsters/mod.rs b/minecraft-entities/src/monsters/mod.rs index bb383e68..3dafed23 100644 --- a/minecraft-entities/src/monsters/mod.rs +++ b/minecraft-entities/src/monsters/mod.rs @@ -16,8 +16,6 @@ mod silverfish; pub use silverfish::*; mod raider; pub use raider::*; -mod witch; -pub use witch::*; mod vex; pub use vex::*; mod skeleton; diff --git a/minecraft-entities/src/monsters/piglin.rs b/minecraft-entities/src/monsters/piglin.rs index 0bedfa76..e18b4e5d 100644 --- a/minecraft-entities/src/monsters/piglin.rs +++ b/minecraft-entities/src/monsters/piglin.rs @@ -12,7 +12,7 @@ pub struct BasePiglin { impl TryAsEntityRef for AnyEntity { fn try_as_entity_ref(&self) -> Option<&BasePiglin> { match self { - AnyEntity::BasePiglin(base_piglin) => Some(&base_piglin), + AnyEntity::BasePiglin(base_piglin) => Some(base_piglin), AnyEntity::Piglin(piglin) => Some(&piglin.base_piglin), AnyEntity::PiglinBrute(piglin_brute) => Some(&piglin_brute.base_piglin), _ => None, diff --git a/minecraft-entities/src/monsters/raider.rs b/minecraft-entities/src/monsters/raider.rs index 7ed0a302..a54050f1 100644 --- a/minecraft-entities/src/monsters/raider.rs +++ b/minecraft-entities/src/monsters/raider.rs @@ -12,7 +12,7 @@ pub struct Raider { impl TryAsEntityRef for AnyEntity { fn try_as_entity_ref(&self) -> Option<&Raider> { match self { - AnyEntity::Raider(raider) => return Some(&raider), + AnyEntity::Raider(raider) => return Some(raider), AnyEntity::Witch(witch) => return Some(&witch.raider), _ => (), } @@ -55,7 +55,7 @@ pub struct AbstractIllager { impl TryAsEntityRef for AnyEntity { fn try_as_entity_ref(&self) -> Option<&AbstractIllager> { match self { - AnyEntity::AbstractIllager(abstract_illager) => return Some(&abstract_illager), + AnyEntity::AbstractIllager(abstract_illager) => return Some(abstract_illager), AnyEntity::Vindicator(vindicator) => return Some(&vindicator.abstract_illager), AnyEntity::Pillager(pillager) => return Some(&pillager.abstract_illager), _ => (), @@ -109,7 +109,7 @@ pub struct SpellcasterIllager { impl TryAsEntityRef for AnyEntity { fn try_as_entity_ref(&self) -> Option<&SpellcasterIllager> { match self { - AnyEntity::SpellcasterIllager(spellcaster_illager) => Some(&spellcaster_illager), + AnyEntity::SpellcasterIllager(spellcaster_illager) => Some(spellcaster_illager), AnyEntity::Illusioner(illusioner) => Some(&illusioner.spellcaster_illager), AnyEntity::Ravager(ravager) => Some(&ravager.spellcaster_illager), AnyEntity::Evoker(evoker) => Some(&evoker.spellcaster_illager), diff --git a/minecraft-entities/src/monsters/witch.rs b/minecraft-entities/src/monsters/witch.rs deleted file mode 100644 index c5d584ae..00000000 --- a/minecraft-entities/src/monsters/witch.rs +++ /dev/null @@ -1,2 +0,0 @@ -use super::*; - From 4e09e2b597ef3650687b8a40aaf9fe51f4b66d3e Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 01:34:05 +0100 Subject: [PATCH 35/89] Add descendants --- minecraft-entities-derive/examples/main.rs | 8 +++-- minecraft-entities-derive/src/lib.rs | 38 ++++++++++++++++++---- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/minecraft-entities-derive/examples/main.rs b/minecraft-entities-derive/examples/main.rs index a577989e..3b874bea 100644 --- a/minecraft-entities-derive/examples/main.rs +++ b/minecraft-entities-derive/examples/main.rs @@ -49,7 +49,8 @@ impl Handler { // Entity #[MinecraftEntity( - parents { }, + ancestors { }, + descendants { Animal... }, inheritable, defines { on_moved(self, from: f32, to: f32); @@ -73,7 +74,8 @@ impl Handler { // Animal #[MinecraftEntity( - parents { Entity }, + ancestors { Entity }, + descendants { Cow }, inheritable, defines { Entity.on_spawned(self); @@ -102,7 +104,7 @@ impl Handler { // Cow #[MinecraftEntity( - parents { Animal, Entity }, + ancestors { Animal, Entity }, defines { Entity.on_spawned(self); Animal.on_hit(self, damage: usize); diff --git a/minecraft-entities-derive/src/lib.rs b/minecraft-entities-derive/src/lib.rs index cf348a91..7695e04a 100644 --- a/minecraft-entities-derive/src/lib.rs +++ b/minecraft-entities-derive/src/lib.rs @@ -27,7 +27,8 @@ fn replace_idents(token: &mut TokenTree, to_replace: &HashMap<&'static str, Iden #[proc_macro_attribute] #[proc_macro_error] pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { - let mut inherited = Vec::new(); + let mut ancestors = Vec::new(); + let mut descendants = Vec::new(); let mut inheritable = false; let mut defines = Vec::new(); let mut codes = Vec::new(); @@ -63,13 +64,36 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { while let Some(ident) = attrs.next() { let TokenTree::Ident(ident) = ident else { abort!(ident.span(), "expected ident") }; match ident.to_string().as_str() { - "parents" => { + "ancestors" => { let Some(token_tree) = attrs.next() else { abort!(ident.span(), "expected group after parents") }; let TokenTree::Group(group) = token_tree else { abort!(token_tree.span(), "expected group") }; let mut group_attrs = group.stream().into_iter().peekable(); while let Some(ident) = group_attrs.next() { let TokenTree::Ident(ident) = ident else { abort!(ident.span(), "expected ident") }; - inherited.push(ident); + ancestors.push(ident); + if matches!(group_attrs.peek(), Some(TokenTree::Punct(punct)) if punct.as_char() == ',') { + group_attrs.next(); + } + } + } + "descendants" => { + let Some(token_tree) = attrs.next() else { abort!(ident.span(), "expected group after parents") }; + let TokenTree::Group(group) = token_tree else { abort!(token_tree.span(), "expected group") }; + let mut group_attrs = group.stream().into_iter().peekable(); + while let Some(ident) = group_attrs.next() { + let TokenTree::Ident(ident) = ident else { abort!(ident.span(), "expected ident") }; + let mut generic = false; + if matches!(group_attrs.peek(), Some(TokenTree::Punct(punct)) if punct.as_char() == '.') { + let dot = group_attrs.next().unwrap(); + if !matches!(group_attrs.next(), Some(TokenTree::Punct(punct)) if punct.as_char() == '.') { + abort!(dot.span(), "this dot needs to come with two other dots"); + } + if !matches!(group_attrs.next(), Some(TokenTree::Punct(punct)) if punct.as_char() == '.') { + abort!(dot.span(), "this dot needs to come with two other dots"); + } + generic = true; + } + descendants.push((ident, generic)); if matches!(group_attrs.peek(), Some(TokenTree::Punct(punct)) if punct.as_char() == ',') { group_attrs.next(); } @@ -128,7 +152,7 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { attrs.next(); } } - let mut hierarchy = inherited.clone(); + let mut hierarchy = ancestors.clone(); hierarchy.insert(0, struct_name.clone()); let mut to_replace = HashMap::new(); @@ -139,9 +163,9 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { to_replace.insert("get_this", Ident::new(&format!("get_{}", struct_name.to_string().to_case(Case::Snake)), struct_name.span())); to_replace.insert("get_this_mut", Ident::new(&format!("get_{}_mut", struct_name.to_string().to_case(Case::Snake)), struct_name.span())); - if !inherited.is_empty() { + if !ancestors.is_empty() { // Generate code for parent - let parent = inherited.remove(0); + let parent = ancestors.remove(0); let code: TokenStream = r#" #[automatically_derived] impl ParentDescendant for This { @@ -171,7 +195,7 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { fn get_inherited_mut(&mut self) -> &mut Inherited { self.parent.get_inherited_mut() } } "#.parse().unwrap(); - for inherited in inherited { + for inherited in ancestors { to_replace.insert("InheritedDescendant", Ident::new(&format!("{}Descendant", inherited), inherited.span())); to_replace.insert("Inherited", inherited.clone()); to_replace.insert("get_inherited", Ident::new(&format!("get_{}", inherited.to_string().to_case(Case::Snake)), inherited.span())); From 355a4d7d11cfbf1675f0d159f2f142cd47785f13 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 01:35:02 +0100 Subject: [PATCH 36/89] Rename parents to ancestors --- minecraft-entities/src/animals/axolotl.rs | 2 +- minecraft-entities/src/animals/bee.rs | 2 +- minecraft-entities/src/animals/cat.rs | 2 +- minecraft-entities/src/animals/chicken.rs | 2 +- minecraft-entities/src/animals/cow.rs | 4 ++-- minecraft-entities/src/animals/fox.rs | 2 +- minecraft-entities/src/animals/frog.rs | 2 +- minecraft-entities/src/animals/goat.rs | 2 +- minecraft-entities/src/animals/hoglin.rs | 2 +- minecraft-entities/src/animals/horses.rs | 22 +++++++++---------- minecraft-entities/src/animals/mod.rs | 4 ++-- minecraft-entities/src/animals/ocelot.rs | 2 +- minecraft-entities/src/animals/panda.rs | 2 +- minecraft-entities/src/animals/parrot.rs | 2 +- minecraft-entities/src/animals/pig.rs | 2 +- minecraft-entities/src/animals/polar_bear.rs | 2 +- minecraft-entities/src/animals/rabbit.rs | 2 +- minecraft-entities/src/animals/sheep.rs | 2 +- minecraft-entities/src/animals/sniffer.rs | 2 +- minecraft-entities/src/animals/strider.rs | 2 +- minecraft-entities/src/animals/turtle.rs | 2 +- .../src/animals/water_animal.rs | 18 +++++++-------- minecraft-entities/src/animals/wolf.rs | 2 +- minecraft-entities/src/arrow.rs | 8 +++---- minecraft-entities/src/block.rs | 2 +- minecraft-entities/src/boat.rs | 4 ++-- minecraft-entities/src/display.rs | 10 ++++----- minecraft-entities/src/fire_entities.rs | 8 +++---- minecraft-entities/src/interaction.rs | 2 +- minecraft-entities/src/item.rs | 6 ++--- minecraft-entities/src/living_entity.rs | 4 ++-- minecraft-entities/src/mobs/bat.rs | 2 +- minecraft-entities/src/mobs/ender_dragon.rs | 4 ++-- minecraft-entities/src/mobs/flying.rs | 6 ++--- minecraft-entities/src/mobs/golems.rs | 6 ++--- minecraft-entities/src/mobs/mod.rs | 8 +++---- minecraft-entities/src/mobs/slime.rs | 2 +- minecraft-entities/src/mobs/villagers.rs | 6 ++--- minecraft-entities/src/monsters/blaze.rs | 2 +- minecraft-entities/src/monsters/creeper.rs | 2 +- minecraft-entities/src/monsters/enderman.rs | 2 +- minecraft-entities/src/monsters/endermite.rs | 2 +- minecraft-entities/src/monsters/giant.rs | 2 +- minecraft-entities/src/monsters/guardian.rs | 4 ++-- minecraft-entities/src/monsters/mod.rs | 2 +- minecraft-entities/src/monsters/piglin.rs | 6 ++--- minecraft-entities/src/monsters/raider.rs | 20 ++++++++--------- minecraft-entities/src/monsters/silverfish.rs | 2 +- minecraft-entities/src/monsters/skeleton.rs | 8 +++---- minecraft-entities/src/monsters/spider.rs | 2 +- minecraft-entities/src/monsters/vex.rs | 2 +- minecraft-entities/src/monsters/warden.rs | 2 +- minecraft-entities/src/monsters/wither.rs | 4 ++-- minecraft-entities/src/monsters/zoglin.rs | 2 +- minecraft-entities/src/monsters/zombies.rs | 10 ++++----- minecraft-entities/src/particles.rs | 4 ++-- minecraft-entities/src/player.rs | 2 +- minecraft-entities/src/shulker.rs | 2 +- .../src/thrown_item_projectile.rs | 14 ++++++------ 59 files changed, 130 insertions(+), 130 deletions(-) diff --git a/minecraft-entities/src/animals/axolotl.rs b/minecraft-entities/src/animals/axolotl.rs index e137a43d..233c93af 100644 --- a/minecraft-entities/src/animals/axolotl.rs +++ b/minecraft-entities/src/animals/axolotl.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Axolotl { pub animal: Animal, diff --git a/minecraft-entities/src/animals/bee.rs b/minecraft-entities/src/animals/bee.rs index 5cf99082..de1ee9d4 100644 --- a/minecraft-entities/src/animals/bee.rs +++ b/minecraft-entities/src/animals/bee.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Bee { pub animal: Animal, diff --git a/minecraft-entities/src/animals/cat.rs b/minecraft-entities/src/animals/cat.rs index 028c6f1f..215b65b9 100644 --- a/minecraft-entities/src/animals/cat.rs +++ b/minecraft-entities/src/animals/cat.rs @@ -1,7 +1,7 @@ use super::*; #[MinecraftEntity( - parents { TameableAnimal, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { TameableAnimal, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Cat { pub tameable_animal: TameableAnimal, diff --git a/minecraft-entities/src/animals/chicken.rs b/minecraft-entities/src/animals/chicken.rs index 57e25686..84d4fae0 100644 --- a/minecraft-entities/src/animals/chicken.rs +++ b/minecraft-entities/src/animals/chicken.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Chicken { pub animal: Animal, diff --git a/minecraft-entities/src/animals/cow.rs b/minecraft-entities/src/animals/cow.rs index 8e1a90be..e280ad16 100644 --- a/minecraft-entities/src/animals/cow.rs +++ b/minecraft-entities/src/animals/cow.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - inheritable, parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, ancestors { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Cow { pub animal: Animal, @@ -28,7 +28,7 @@ impl TryAsEntityRef for AnyEntity { #[derive(Default)] #[MinecraftEntity( - parents { Cow, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Cow, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Mooshroom { pub cow: Cow, diff --git a/minecraft-entities/src/animals/fox.rs b/minecraft-entities/src/animals/fox.rs index b07ed93f..45bcbe5b 100644 --- a/minecraft-entities/src/animals/fox.rs +++ b/minecraft-entities/src/animals/fox.rs @@ -3,7 +3,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Fox { pub animal: Animal, diff --git a/minecraft-entities/src/animals/frog.rs b/minecraft-entities/src/animals/frog.rs index cf6587ad..6fcd5aef 100644 --- a/minecraft-entities/src/animals/frog.rs +++ b/minecraft-entities/src/animals/frog.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Frog { pub animal: Animal, diff --git a/minecraft-entities/src/animals/goat.rs b/minecraft-entities/src/animals/goat.rs index 3dfcda58..b944fb2b 100644 --- a/minecraft-entities/src/animals/goat.rs +++ b/minecraft-entities/src/animals/goat.rs @@ -1,7 +1,7 @@ use super::*; #[MinecraftEntity( - parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Goat { pub animal: Animal, diff --git a/minecraft-entities/src/animals/hoglin.rs b/minecraft-entities/src/animals/hoglin.rs index 517dd4cf..8b4b17b9 100644 --- a/minecraft-entities/src/animals/hoglin.rs +++ b/minecraft-entities/src/animals/hoglin.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Hoglin { pub animal: Animal, diff --git a/minecraft-entities/src/animals/horses.rs b/minecraft-entities/src/animals/horses.rs index 45d23f84..4e3aaf2d 100644 --- a/minecraft-entities/src/animals/horses.rs +++ b/minecraft-entities/src/animals/horses.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - inheritable, parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, ancestors { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct AbstractHorse { pub animal: Animal, @@ -11,7 +11,7 @@ pub struct AbstractHorse { #[derive(Default)] #[MinecraftEntity( - parents { AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Horse { pub abstract_horse: AbstractHorse, @@ -52,7 +52,7 @@ impl TryAsEntityRef for AnyEntity { #[derive(Default)] #[MinecraftEntity( - parents { AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct ZombieHorse { pub abstract_horse: AbstractHorse, @@ -60,7 +60,7 @@ pub struct ZombieHorse { #[derive(Default)] #[MinecraftEntity( - parents { AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct SkeletonHorse { pub abstract_horse: AbstractHorse, @@ -68,7 +68,7 @@ pub struct SkeletonHorse { #[derive(Default)] #[MinecraftEntity( - parents { AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Camel { pub abstract_horse: AbstractHorse, @@ -78,7 +78,7 @@ pub struct Camel { #[derive(Default)] #[MinecraftEntity( - inheritable, parents { AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, ancestors { AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct ChestedHorse { pub abstract_horse: AbstractHorse, @@ -115,7 +115,7 @@ impl TryAsEntityRef for AnyEntity { #[derive(Default)] #[MinecraftEntity( - parents { ChestedHorse, AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { ChestedHorse, AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Mule { pub chested_horse: ChestedHorse, @@ -123,14 +123,14 @@ pub struct Mule { #[derive(Default)] #[MinecraftEntity( - parents { ChestedHorse, AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { ChestedHorse, AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Donkey { pub chested_horse: ChestedHorse, } #[MinecraftEntity( - inheritable, parents { ChestedHorse, AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, ancestors { ChestedHorse, AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Llama { pub chested_horse: ChestedHorse, @@ -172,7 +172,7 @@ impl TryAsEntityRef for AnyEntity { #[derive(Default)] #[MinecraftEntity( - parents { Llama, ChestedHorse, AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Llama, ChestedHorse, AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct TraderLlama { pub llama: Llama, @@ -181,7 +181,7 @@ pub struct TraderLlama { #[derive(Default)] #[MinecraftEntity( - parents { Entity }, + ancestors { Entity }, )] pub struct LlamaSpit { pub entity: Entity, diff --git a/minecraft-entities/src/animals/mod.rs b/minecraft-entities/src/animals/mod.rs index 9a5a3a5d..f9dcbcff 100644 --- a/minecraft-entities/src/animals/mod.rs +++ b/minecraft-entities/src/animals/mod.rs @@ -47,7 +47,7 @@ pub use water_animal::*; #[derive(Default)] #[MinecraftEntity( - inheritable, parents { AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, ancestors { AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Animal { pub ageable_mob: AgeableMob, @@ -79,7 +79,7 @@ impl TryAsEntityRef for AnyEntity { #[derive(Default)] #[MinecraftEntity( - inheritable, parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, ancestors { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct TameableAnimal { pub animal: Animal, diff --git a/minecraft-entities/src/animals/ocelot.rs b/minecraft-entities/src/animals/ocelot.rs index e8c3bab8..39550542 100644 --- a/minecraft-entities/src/animals/ocelot.rs +++ b/minecraft-entities/src/animals/ocelot.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Ocelot { pub animal: Animal, diff --git a/minecraft-entities/src/animals/panda.rs b/minecraft-entities/src/animals/panda.rs index dd89fe66..e38a256f 100644 --- a/minecraft-entities/src/animals/panda.rs +++ b/minecraft-entities/src/animals/panda.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Panda { pub animal: Animal, diff --git a/minecraft-entities/src/animals/parrot.rs b/minecraft-entities/src/animals/parrot.rs index 8bfc97da..0fa54605 100644 --- a/minecraft-entities/src/animals/parrot.rs +++ b/minecraft-entities/src/animals/parrot.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { TameableAnimal, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { TameableAnimal, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Parrot { pub tameable_animal: TameableAnimal, diff --git a/minecraft-entities/src/animals/pig.rs b/minecraft-entities/src/animals/pig.rs index 15b373b2..921f2121 100644 --- a/minecraft-entities/src/animals/pig.rs +++ b/minecraft-entities/src/animals/pig.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Pig { pub animal: Animal, diff --git a/minecraft-entities/src/animals/polar_bear.rs b/minecraft-entities/src/animals/polar_bear.rs index 737428bc..95e0aefa 100644 --- a/minecraft-entities/src/animals/polar_bear.rs +++ b/minecraft-entities/src/animals/polar_bear.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct PolarBear { pub animal: Animal, diff --git a/minecraft-entities/src/animals/rabbit.rs b/minecraft-entities/src/animals/rabbit.rs index 696cb18d..0173be5f 100644 --- a/minecraft-entities/src/animals/rabbit.rs +++ b/minecraft-entities/src/animals/rabbit.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Rabbit { pub animal: Animal, diff --git a/minecraft-entities/src/animals/sheep.rs b/minecraft-entities/src/animals/sheep.rs index 35309593..53fa1ebf 100644 --- a/minecraft-entities/src/animals/sheep.rs +++ b/minecraft-entities/src/animals/sheep.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Sheep { pub animal: Animal, diff --git a/minecraft-entities/src/animals/sniffer.rs b/minecraft-entities/src/animals/sniffer.rs index 77144da3..20f54d7d 100644 --- a/minecraft-entities/src/animals/sniffer.rs +++ b/minecraft-entities/src/animals/sniffer.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Sniffer { pub animal: Animal, diff --git a/minecraft-entities/src/animals/strider.rs b/minecraft-entities/src/animals/strider.rs index 0ed64600..176c4381 100644 --- a/minecraft-entities/src/animals/strider.rs +++ b/minecraft-entities/src/animals/strider.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Strider { pub animal: Animal, diff --git a/minecraft-entities/src/animals/turtle.rs b/minecraft-entities/src/animals/turtle.rs index b6554b06..72e17a47 100644 --- a/minecraft-entities/src/animals/turtle.rs +++ b/minecraft-entities/src/animals/turtle.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Turtle { pub animal: Animal, diff --git a/minecraft-entities/src/animals/water_animal.rs b/minecraft-entities/src/animals/water_animal.rs index fe262c85..1105957a 100644 --- a/minecraft-entities/src/animals/water_animal.rs +++ b/minecraft-entities/src/animals/water_animal.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - inheritable, parents { PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, ancestors { PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct WaterAnimal { pub pathfinder_mob: PathfinderMob, @@ -38,7 +38,7 @@ impl TryAsEntityRef for AnyEntity { #[derive(Default)] #[MinecraftEntity( - parents { WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Dolphin { pub water_animal: WaterAnimal, @@ -49,7 +49,7 @@ pub struct Dolphin { #[derive(Default)] #[MinecraftEntity( - parents { WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Squid { pub water_animal: WaterAnimal, @@ -57,7 +57,7 @@ pub struct Squid { #[derive(Default)] #[MinecraftEntity( - inheritable, parents { WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, ancestors { WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct AbstractFish { pub water_animal: WaterAnimal, @@ -92,7 +92,7 @@ impl TryAsEntityRef for AnyEntity { #[derive(Default)] #[MinecraftEntity( - parents { AbstractFish, WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { AbstractFish, WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Cod { pub abstract_fish: AbstractFish, @@ -100,7 +100,7 @@ pub struct Cod { #[derive(Default)] #[MinecraftEntity( - parents { AbstractFish, WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { AbstractFish, WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct PufferFish { pub abstract_fish: AbstractFish, @@ -109,7 +109,7 @@ pub struct PufferFish { #[derive(Default)] #[MinecraftEntity( - parents { AbstractFish, WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { AbstractFish, WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Salmon { pub abstract_fish: AbstractFish, @@ -117,7 +117,7 @@ pub struct Salmon { #[derive(Default)] #[MinecraftEntity( - parents { AbstractFish, WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { AbstractFish, WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct TropicalFish { pub abstract_fish: AbstractFish, @@ -126,7 +126,7 @@ pub struct TropicalFish { #[derive(Default)] #[MinecraftEntity( - parents { AbstractFish, WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { AbstractFish, WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Tadpole { pub abstract_fish: AbstractFish, diff --git a/minecraft-entities/src/animals/wolf.rs b/minecraft-entities/src/animals/wolf.rs index c920068c..00b634a4 100644 --- a/minecraft-entities/src/animals/wolf.rs +++ b/minecraft-entities/src/animals/wolf.rs @@ -1,7 +1,7 @@ use super::*; #[MinecraftEntity( - parents { TameableAnimal, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { TameableAnimal, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Wolf { pub tameable_animal: TameableAnimal, diff --git a/minecraft-entities/src/arrow.rs b/minecraft-entities/src/arrow.rs index efe507c3..f6bb1f5b 100644 --- a/minecraft-entities/src/arrow.rs +++ b/minecraft-entities/src/arrow.rs @@ -1,7 +1,7 @@ use super::*; #[MinecraftEntity( - inheritable, parents { Entity }, + inheritable, ancestors { Entity }, )] pub struct AbstractArrow { pub entity: Entity, @@ -44,7 +44,7 @@ impl TryAsEntityRef for AnyEntity { } #[MinecraftEntity( - parents { AbstractArrow, Entity }, + ancestors { AbstractArrow, Entity }, )] pub struct Arrow { pub abstract_arrow: AbstractArrow, @@ -61,7 +61,7 @@ impl Default for Arrow { } #[MinecraftEntity( - parents { AbstractArrow, Entity }, + ancestors { AbstractArrow, Entity }, )] pub struct SpectralArrow { pub abstract_arrow: AbstractArrow, @@ -80,7 +80,7 @@ impl Default for SpectralArrow { } #[MinecraftEntity( - parents { AbstractArrow, Entity }, + ancestors { AbstractArrow, Entity }, )] pub struct ThrownTrident { pub abstract_arrow: AbstractArrow, diff --git a/minecraft-entities/src/block.rs b/minecraft-entities/src/block.rs index a097d7dd..26d7f1b7 100644 --- a/minecraft-entities/src/block.rs +++ b/minecraft-entities/src/block.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { Entity }, + ancestors { Entity }, )] pub struct FallingBlock { pub entity: Entity, diff --git a/minecraft-entities/src/boat.rs b/minecraft-entities/src/boat.rs index bd58e0e3..0da1ee2b 100644 --- a/minecraft-entities/src/boat.rs +++ b/minecraft-entities/src/boat.rs @@ -1,7 +1,7 @@ use super::*; #[MinecraftEntity( - inheritable, parents { Entity }, + inheritable, ancestors { Entity }, )] pub struct Boat { pub entity: Entity, @@ -50,7 +50,7 @@ impl TryAsEntityRef for AnyEntity { #[derive(Default)] #[MinecraftEntity( - parents { Boat, Entity }, + ancestors { Boat, Entity }, )] pub struct ChestBoat { pub boat: Boat, diff --git a/minecraft-entities/src/display.rs b/minecraft-entities/src/display.rs index 44d06482..c5b54a17 100644 --- a/minecraft-entities/src/display.rs +++ b/minecraft-entities/src/display.rs @@ -2,7 +2,7 @@ use super::*; use minecraft_protocol::components::paintings::Painting as PaintingType; #[MinecraftEntity( - inheritable, parents { Entity }, + inheritable, ancestors { Entity }, )] pub struct Display { pub entity: Entity, @@ -75,7 +75,7 @@ impl TryAsEntityRef for AnyEntity { } #[MinecraftEntity( - parents { Display, Entity }, + ancestors { Display, Entity }, )] pub struct BlockDisplay { pub display: Display, @@ -92,7 +92,7 @@ impl Default for BlockDisplay { } #[MinecraftEntity( - parents { Display, Entity }, + ancestors { Display, Entity }, )] pub struct ItemDisplay { pub display: Display, @@ -111,7 +111,7 @@ impl Default for ItemDisplay { } #[MinecraftEntity( - parents { Display, Entity }, + ancestors { Display, Entity }, )] pub struct TextDisplay { pub display: Display, @@ -143,7 +143,7 @@ impl Default for TextDisplay { #[derive(Default)] #[MinecraftEntity( - parents { Entity }, + ancestors { Entity }, )] pub struct Painting { pub entity: Entity, diff --git a/minecraft-entities/src/fire_entities.rs b/minecraft-entities/src/fire_entities.rs index ac330586..0b8d8265 100644 --- a/minecraft-entities/src/fire_entities.rs +++ b/minecraft-entities/src/fire_entities.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { Entity }, + ancestors { Entity }, )] pub struct DragonFireball { pub entity: Entity, @@ -10,7 +10,7 @@ pub struct DragonFireball { #[derive(Default)] #[MinecraftEntity( - parents { Entity }, + ancestors { Entity }, )] pub struct SmallFireball { pub entity: Entity, @@ -19,7 +19,7 @@ pub struct SmallFireball { #[derive(Default)] #[MinecraftEntity( - parents { Entity }, + ancestors { Entity }, )] pub struct Fireball { pub entity: Entity, @@ -28,7 +28,7 @@ pub struct Fireball { #[derive(Default)] #[MinecraftEntity( - parents { Entity }, + ancestors { Entity }, )] pub struct FireworkRocket { pub entity: Entity, diff --git a/minecraft-entities/src/interaction.rs b/minecraft-entities/src/interaction.rs index c7e31469..c33c1eb8 100644 --- a/minecraft-entities/src/interaction.rs +++ b/minecraft-entities/src/interaction.rs @@ -1,7 +1,7 @@ use super::*; #[MinecraftEntity( - parents { Entity }, + ancestors { Entity }, )] pub struct Interaction { pub entity: Entity, diff --git a/minecraft-entities/src/item.rs b/minecraft-entities/src/item.rs index b280c4c9..7619b973 100644 --- a/minecraft-entities/src/item.rs +++ b/minecraft-entities/src/item.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - inheritable, parents { Entity }, + inheritable, ancestors { Entity }, )] pub struct ItemFrame { pub entity: Entity, @@ -30,7 +30,7 @@ impl TryAsEntityRef for AnyEntity { #[derive(Default)] #[MinecraftEntity( - parents { ItemFrame, Entity }, + ancestors { ItemFrame, Entity }, )] pub struct GlowingItemFrame { pub item_frame: ItemFrame, @@ -38,7 +38,7 @@ pub struct GlowingItemFrame { #[derive(Default)] #[MinecraftEntity( - parents { Entity }, + ancestors { Entity }, )] pub struct ItemEntity { pub entity: Entity, diff --git a/minecraft-entities/src/living_entity.rs b/minecraft-entities/src/living_entity.rs index ea259a37..476cc56b 100644 --- a/minecraft-entities/src/living_entity.rs +++ b/minecraft-entities/src/living_entity.rs @@ -1,7 +1,7 @@ use super::*; #[MinecraftEntity( - inheritable, parents { Entity }, + inheritable, ancestors { Entity }, )] pub struct LivingEntity { pub entity: Entity, @@ -60,7 +60,7 @@ impl TryAsEntityRef for AnyEntity { } #[MinecraftEntity( - parents { LivingEntity, Entity }, + ancestors { LivingEntity, Entity }, )] pub struct ArmorStand { pub living_entity: LivingEntity, diff --git a/minecraft-entities/src/mobs/bat.rs b/minecraft-entities/src/mobs/bat.rs index 5e852840..f4a4ecc6 100644 --- a/minecraft-entities/src/mobs/bat.rs +++ b/minecraft-entities/src/mobs/bat.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { AmbientCreature, Mob, LivingEntity, Entity }, + ancestors { AmbientCreature, Mob, LivingEntity, Entity }, )] pub struct Bat { pub ambient_creature: AmbientCreature, diff --git a/minecraft-entities/src/mobs/ender_dragon.rs b/minecraft-entities/src/mobs/ender_dragon.rs index bc8f3121..04a200b6 100644 --- a/minecraft-entities/src/mobs/ender_dragon.rs +++ b/minecraft-entities/src/mobs/ender_dragon.rs @@ -1,7 +1,7 @@ use super::*; #[MinecraftEntity( - parents { Mob, LivingEntity, Entity }, + ancestors { Mob, LivingEntity, Entity }, )] pub struct EnderDragon { pub mob: Mob, @@ -18,7 +18,7 @@ impl Default for EnderDragon { } #[MinecraftEntity( - parents { Entity }, + ancestors { Entity }, )] pub struct EndCrystal { pub entity: Entity, diff --git a/minecraft-entities/src/mobs/flying.rs b/minecraft-entities/src/mobs/flying.rs index 409e9e8f..238721d3 100644 --- a/minecraft-entities/src/mobs/flying.rs +++ b/minecraft-entities/src/mobs/flying.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - inheritable, parents { Mob, LivingEntity, Entity }, + inheritable, ancestors { Mob, LivingEntity, Entity }, )] pub struct Flying { pub mob: Mob, @@ -30,7 +30,7 @@ impl TryAsEntityRef for AnyEntity { #[derive(Default)] #[MinecraftEntity( - parents { Flying, Mob, LivingEntity, Entity }, + ancestors { Flying, Mob, LivingEntity, Entity }, )] pub struct Ghast { pub flying: Flying, @@ -39,7 +39,7 @@ pub struct Ghast { #[derive(Default)] #[MinecraftEntity( - parents { Flying, Mob, LivingEntity, Entity }, + ancestors { Flying, Mob, LivingEntity, Entity }, )] pub struct Phantom { pub flying: Flying, diff --git a/minecraft-entities/src/mobs/golems.rs b/minecraft-entities/src/mobs/golems.rs index 472ba744..45c36bb5 100644 --- a/minecraft-entities/src/mobs/golems.rs +++ b/minecraft-entities/src/mobs/golems.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - inheritable, parents { PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, ancestors { PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct AbstractGolem { pub pathfinder_mob: PathfinderMob, @@ -30,7 +30,7 @@ impl TryAsEntityRef for AnyEntity { #[derive(Default)] #[MinecraftEntity( - parents { AbstractGolem, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { AbstractGolem, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct IronGolem { pub abstract_golem: AbstractGolem, @@ -39,7 +39,7 @@ pub struct IronGolem { #[derive(Default)] #[MinecraftEntity( - parents { AbstractGolem, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { AbstractGolem, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct SnowGolem { pub abstract_golem: AbstractGolem, diff --git a/minecraft-entities/src/mobs/mod.rs b/minecraft-entities/src/mobs/mod.rs index e6945b70..f6b0d861 100644 --- a/minecraft-entities/src/mobs/mod.rs +++ b/minecraft-entities/src/mobs/mod.rs @@ -15,7 +15,7 @@ pub use bat::*; #[derive(Default)] #[MinecraftEntity( - inheritable, parents { LivingEntity, Entity }, + inheritable, ancestors { LivingEntity, Entity }, )] pub struct Mob { pub living_entity: LivingEntity, @@ -55,7 +55,7 @@ impl TryAsEntityRef for AnyEntity { #[derive(Default)] #[MinecraftEntity( - inheritable, parents { Mob, LivingEntity, Entity }, + inheritable, ancestors { Mob, LivingEntity, Entity }, )] pub struct AmbientCreature { pub mob: Mob, @@ -83,7 +83,7 @@ impl TryAsEntityRef for AnyEntity { #[derive(Default)] #[MinecraftEntity( - inheritable, parents { Mob, LivingEntity, Entity }, + inheritable, ancestors { Mob, LivingEntity, Entity }, )] pub struct PathfinderMob { pub mob: Mob, @@ -115,7 +115,7 @@ impl TryAsEntityRef for AnyEntity { #[derive(Default)] #[MinecraftEntity( - inheritable, parents { PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, ancestors { PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct AgeableMob { pub pathfinder_mob: PathfinderMob, diff --git a/minecraft-entities/src/mobs/slime.rs b/minecraft-entities/src/mobs/slime.rs index 5ce9839e..8383ca50 100644 --- a/minecraft-entities/src/mobs/slime.rs +++ b/minecraft-entities/src/mobs/slime.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { Mob, LivingEntity, Entity }, + ancestors { Mob, LivingEntity, Entity }, )] pub struct Slime { pub mob: Mob, diff --git a/minecraft-entities/src/mobs/villagers.rs b/minecraft-entities/src/mobs/villagers.rs index 96614641..65294d17 100644 --- a/minecraft-entities/src/mobs/villagers.rs +++ b/minecraft-entities/src/mobs/villagers.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - inheritable, parents { AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, ancestors { AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct AbstractVillager { pub ageable_mob: AgeableMob, @@ -31,7 +31,7 @@ impl TryAsEntityRef for AnyEntity { #[derive(Default)] #[MinecraftEntity( - parents { AbstractVillager, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { AbstractVillager, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Villager { pub abstract_villager: AbstractVillager, @@ -40,7 +40,7 @@ pub struct Villager { #[derive(Default)] #[MinecraftEntity( - parents { AbstractVillager, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { AbstractVillager, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct WanderingTrader { pub abstract_villager: AbstractVillager, diff --git a/minecraft-entities/src/monsters/blaze.rs b/minecraft-entities/src/monsters/blaze.rs index edd5d3c6..bdac2f22 100644 --- a/minecraft-entities/src/monsters/blaze.rs +++ b/minecraft-entities/src/monsters/blaze.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Blaze { pub monster: Monster, diff --git a/minecraft-entities/src/monsters/creeper.rs b/minecraft-entities/src/monsters/creeper.rs index 2eea2131..92ee9cf5 100644 --- a/minecraft-entities/src/monsters/creeper.rs +++ b/minecraft-entities/src/monsters/creeper.rs @@ -1,7 +1,7 @@ use super::*; #[MinecraftEntity( - parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Creeper { pub monster: Monster, diff --git a/minecraft-entities/src/monsters/enderman.rs b/minecraft-entities/src/monsters/enderman.rs index 1432a5ad..cc244ac9 100644 --- a/minecraft-entities/src/monsters/enderman.rs +++ b/minecraft-entities/src/monsters/enderman.rs @@ -3,7 +3,7 @@ use minecraft_protocol::ids::blocks::Block; use super::*; #[MinecraftEntity( - parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Enderman { pub monster: Monster, diff --git a/minecraft-entities/src/monsters/endermite.rs b/minecraft-entities/src/monsters/endermite.rs index 82317fce..aec4e303 100644 --- a/minecraft-entities/src/monsters/endermite.rs +++ b/minecraft-entities/src/monsters/endermite.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Endermite { pub monster: Monster, diff --git a/minecraft-entities/src/monsters/giant.rs b/minecraft-entities/src/monsters/giant.rs index 60c4bbbf..c7fbe40c 100644 --- a/minecraft-entities/src/monsters/giant.rs +++ b/minecraft-entities/src/monsters/giant.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Giant { pub monster: Monster, diff --git a/minecraft-entities/src/monsters/guardian.rs b/minecraft-entities/src/monsters/guardian.rs index 1a9ec039..19567c78 100644 --- a/minecraft-entities/src/monsters/guardian.rs +++ b/minecraft-entities/src/monsters/guardian.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - inheritable, parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Guardian { pub monster: Monster, @@ -30,7 +30,7 @@ impl TryAsEntityRef for AnyEntity { #[derive(Default)] #[MinecraftEntity( - parents { Guardian, Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Guardian, Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct ElderGuardian { pub guardian: Guardian, diff --git a/minecraft-entities/src/monsters/mod.rs b/minecraft-entities/src/monsters/mod.rs index 3dafed23..a0e4108b 100644 --- a/minecraft-entities/src/monsters/mod.rs +++ b/minecraft-entities/src/monsters/mod.rs @@ -35,7 +35,7 @@ pub use enderman::*; #[derive(Default)] #[MinecraftEntity( - inheritable, parents { PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, ancestors { PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Monster { pub pathfinder_mob: PathfinderMob, diff --git a/minecraft-entities/src/monsters/piglin.rs b/minecraft-entities/src/monsters/piglin.rs index e18b4e5d..de05922c 100644 --- a/minecraft-entities/src/monsters/piglin.rs +++ b/minecraft-entities/src/monsters/piglin.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - inheritable, parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct BasePiglin { pub monster: Monster, @@ -31,7 +31,7 @@ impl TryAsEntityRef for AnyEntity { #[derive(Default)] #[MinecraftEntity( - parents { BasePiglin, Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { BasePiglin, Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Piglin { pub base_piglin: BasePiglin, @@ -42,7 +42,7 @@ pub struct Piglin { #[derive(Default)] #[MinecraftEntity( - parents { BasePiglin, Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { BasePiglin, Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct PiglinBrute { pub base_piglin: BasePiglin, diff --git a/minecraft-entities/src/monsters/raider.rs b/minecraft-entities/src/monsters/raider.rs index a54050f1..f6c87f6e 100644 --- a/minecraft-entities/src/monsters/raider.rs +++ b/minecraft-entities/src/monsters/raider.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - inheritable, parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Raider { pub monster: Monster, @@ -37,7 +37,7 @@ impl TryAsEntityRef for AnyEntity { #[derive(Default)] #[MinecraftEntity( - parents { Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Witch { pub raider: Raider, @@ -46,7 +46,7 @@ pub struct Witch { #[derive(Default)] #[MinecraftEntity( - inheritable, parents { Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, ancestors { Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct AbstractIllager { pub raider: Raider, @@ -82,7 +82,7 @@ impl TryAsEntityRef for AnyEntity { #[derive(Default)] #[MinecraftEntity( - parents { AbstractIllager, Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { AbstractIllager, Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Vindicator { pub abstract_illager: AbstractIllager, @@ -90,7 +90,7 @@ pub struct Vindicator { #[derive(Default)] #[MinecraftEntity( - parents { AbstractIllager, Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { AbstractIllager, Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Pillager { pub abstract_illager: AbstractIllager, @@ -99,7 +99,7 @@ pub struct Pillager { #[derive(Default)] #[MinecraftEntity( - inheritable, parents { AbstractIllager, Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, ancestors { AbstractIllager, Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct SpellcasterIllager { pub abstract_illager: AbstractIllager, @@ -130,7 +130,7 @@ impl TryAsEntityRef for AnyEntity { #[derive(Default)] #[MinecraftEntity( - parents { SpellcasterIllager, AbstractIllager, Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { SpellcasterIllager, AbstractIllager, Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Illusioner { pub spellcaster_illager: SpellcasterIllager, @@ -138,7 +138,7 @@ pub struct Illusioner { #[derive(Default)] #[MinecraftEntity( - parents { SpellcasterIllager, AbstractIllager, Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { SpellcasterIllager, AbstractIllager, Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Ravager { pub spellcaster_illager: SpellcasterIllager, @@ -146,7 +146,7 @@ pub struct Ravager { #[derive(Default)] #[MinecraftEntity( - parents { SpellcasterIllager, AbstractIllager, Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { SpellcasterIllager, AbstractIllager, Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Evoker { pub spellcaster_illager: SpellcasterIllager, @@ -154,7 +154,7 @@ pub struct Evoker { #[derive(Default)] #[MinecraftEntity( - parents { Entity }, + ancestors { Entity }, )] pub struct EvokerFangs { pub entity: Entity, diff --git a/minecraft-entities/src/monsters/silverfish.rs b/minecraft-entities/src/monsters/silverfish.rs index dd2dfdf5..a8578abb 100644 --- a/minecraft-entities/src/monsters/silverfish.rs +++ b/minecraft-entities/src/monsters/silverfish.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Silverfish { pub monster: Monster, diff --git a/minecraft-entities/src/monsters/skeleton.rs b/minecraft-entities/src/monsters/skeleton.rs index 41573ea5..4f6c9b63 100644 --- a/minecraft-entities/src/monsters/skeleton.rs +++ b/minecraft-entities/src/monsters/skeleton.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - inheritable, parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct AbstractSkeleton { pub monster: Monster, @@ -32,7 +32,7 @@ impl TryAsEntityRef for AnyEntity { #[derive(Default)] #[MinecraftEntity( - parents { AbstractSkeleton, Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { AbstractSkeleton, Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Skeleton { pub abstract_skeleton: AbstractSkeleton, @@ -40,7 +40,7 @@ pub struct Skeleton { #[derive(Default)] #[MinecraftEntity( - parents { AbstractSkeleton, Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { AbstractSkeleton, Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct WitherSkeleton { pub abstract_skeleton: AbstractSkeleton, @@ -48,7 +48,7 @@ pub struct WitherSkeleton { #[derive(Default)] #[MinecraftEntity( - parents { AbstractSkeleton, Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { AbstractSkeleton, Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Stray { pub abstract_skeleton: AbstractSkeleton, diff --git a/minecraft-entities/src/monsters/spider.rs b/minecraft-entities/src/monsters/spider.rs index 4f6d0b01..f076cfd7 100644 --- a/minecraft-entities/src/monsters/spider.rs +++ b/minecraft-entities/src/monsters/spider.rs @@ -1,7 +1,7 @@ use super::*; #[MinecraftEntity( - parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Spider { pub monster: Monster, diff --git a/minecraft-entities/src/monsters/vex.rs b/minecraft-entities/src/monsters/vex.rs index 883c6290..54c0198d 100644 --- a/minecraft-entities/src/monsters/vex.rs +++ b/minecraft-entities/src/monsters/vex.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Vex { pub monster: Monster, diff --git a/minecraft-entities/src/monsters/warden.rs b/minecraft-entities/src/monsters/warden.rs index b6b29629..906fc877 100644 --- a/minecraft-entities/src/monsters/warden.rs +++ b/minecraft-entities/src/monsters/warden.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Warden { pub monster: Monster, diff --git a/minecraft-entities/src/monsters/wither.rs b/minecraft-entities/src/monsters/wither.rs index 6e8fbe3e..5da7fa2f 100644 --- a/minecraft-entities/src/monsters/wither.rs +++ b/minecraft-entities/src/monsters/wither.rs @@ -1,7 +1,7 @@ use super::*; #[MinecraftEntity( - parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Wither { pub monster: Monster, @@ -13,7 +13,7 @@ pub struct Wither { #[derive(Default)] #[MinecraftEntity( - parents { Entity }, + ancestors { Entity }, )] pub struct WitherSkull { pub entity: Entity, diff --git a/minecraft-entities/src/monsters/zoglin.rs b/minecraft-entities/src/monsters/zoglin.rs index 0a85aabd..d05a01ac 100644 --- a/minecraft-entities/src/monsters/zoglin.rs +++ b/minecraft-entities/src/monsters/zoglin.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Zoglin { pub monster: Monster, diff --git a/minecraft-entities/src/monsters/zombies.rs b/minecraft-entities/src/monsters/zombies.rs index cbaf7585..2739d8c1 100644 --- a/minecraft-entities/src/monsters/zombies.rs +++ b/minecraft-entities/src/monsters/zombies.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - inheritable, parents { Monster, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Zombie { pub monster: Monster, @@ -37,7 +37,7 @@ impl TryAsEntityRef for AnyEntity { #[derive(Default)] #[MinecraftEntity( - parents { Zombie, Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Zombie, Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct ZombieVillager { pub zombie: Zombie, @@ -47,7 +47,7 @@ pub struct ZombieVillager { #[derive(Default)] #[MinecraftEntity( - parents { Zombie, Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Zombie, Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Husk { pub zombie: Zombie, @@ -55,7 +55,7 @@ pub struct Husk { #[derive(Default)] #[MinecraftEntity( - parents { Zombie, Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Zombie, Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Drowned { pub zombie: Zombie, @@ -63,7 +63,7 @@ pub struct Drowned { #[derive(Default)] #[MinecraftEntity( - parents { Zombie, Monster, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { Zombie, Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct ZombifiedPiglin { pub zombie: Zombie, diff --git a/minecraft-entities/src/particles.rs b/minecraft-entities/src/particles.rs index 0cbc7095..8f28cbe7 100644 --- a/minecraft-entities/src/particles.rs +++ b/minecraft-entities/src/particles.rs @@ -2,7 +2,7 @@ use minecraft_protocol::components::particle::Particle; use super::*; #[MinecraftEntity( - parents { Entity }, + ancestors { Entity }, )] pub struct AreaEffectCloud { pub entity: Entity, @@ -26,7 +26,7 @@ impl Default for AreaEffectCloud { #[derive(Default)] #[MinecraftEntity( - parents { Entity }, + ancestors { Entity }, )] pub struct FishingHook{ pub entity: Entity, diff --git a/minecraft-entities/src/player.rs b/minecraft-entities/src/player.rs index 194895ea..1d2a7d18 100644 --- a/minecraft-entities/src/player.rs +++ b/minecraft-entities/src/player.rs @@ -1,7 +1,7 @@ use super::*; #[MinecraftEntity( - parents { LivingEntity, Entity }, + ancestors { LivingEntity, Entity }, )] pub struct Player { pub living_entity: LivingEntity, diff --git a/minecraft-entities/src/shulker.rs b/minecraft-entities/src/shulker.rs index 6d69b5bf..6cc7093e 100644 --- a/minecraft-entities/src/shulker.rs +++ b/minecraft-entities/src/shulker.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - parents { AbstractGolem, PathfinderMob, Mob, LivingEntity, Entity }, + ancestors { AbstractGolem, PathfinderMob, Mob, LivingEntity, Entity }, )] pub struct Shulker { pub abstract_golem: AbstractGolem, diff --git a/minecraft-entities/src/thrown_item_projectile.rs b/minecraft-entities/src/thrown_item_projectile.rs index af8c0423..c1ef51ac 100644 --- a/minecraft-entities/src/thrown_item_projectile.rs +++ b/minecraft-entities/src/thrown_item_projectile.rs @@ -1,7 +1,7 @@ use super::*; #[MinecraftEntity( - inheritable, parents { Entity }, + inheritable, ancestors { Entity }, )] pub struct ThrownItemProjectile { pub entity: Entity, @@ -44,7 +44,7 @@ impl TryAsEntityRef for AnyEntity { } #[MinecraftEntity( - parents { ThrownItemProjectile, Entity }, + ancestors { ThrownItemProjectile, Entity }, )] pub struct ThrownEgg { pub thrown_item_projectile: ThrownItemProjectile, @@ -66,7 +66,7 @@ impl Default for ThrownEgg { } #[MinecraftEntity( - parents { ThrownItemProjectile, Entity }, + ancestors { ThrownItemProjectile, Entity }, )] pub struct ThrownEnderPearl { pub thrown_item_projectile: ThrownItemProjectile, @@ -88,7 +88,7 @@ impl Default for ThrownEnderPearl { } #[MinecraftEntity( - parents { ThrownItemProjectile, Entity }, + ancestors { ThrownItemProjectile, Entity }, )] pub struct ThrownExperienceBottle { pub thrown_item_projectile: ThrownItemProjectile, @@ -110,7 +110,7 @@ impl Default for ThrownExperienceBottle { } #[MinecraftEntity( - parents { ThrownItemProjectile, Entity }, + ancestors { ThrownItemProjectile, Entity }, )] pub struct ThrownPotion { pub thrown_item_projectile: ThrownItemProjectile, @@ -132,7 +132,7 @@ impl Default for ThrownPotion { } #[MinecraftEntity( - parents { ThrownItemProjectile, Entity }, + ancestors { ThrownItemProjectile, Entity }, )] pub struct Snowball { pub thrown_item_projectile: ThrownItemProjectile, @@ -155,7 +155,7 @@ impl Default for Snowball { #[derive(Default)] #[MinecraftEntity( - parents { Entity }, + ancestors { Entity }, )] pub struct EyeOfEnder { pub entity: Entity, From 13dee564a7f970613885705cecc71df056b31015 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 02:18:08 +0100 Subject: [PATCH 37/89] Impl TryAsEntityRef for all entities --- minecraft-entities-derive/Cargo.toml | 2 + minecraft-entities-derive/src/lib.rs | 86 +++++++++++++++++----------- 2 files changed, 54 insertions(+), 34 deletions(-) diff --git a/minecraft-entities-derive/Cargo.toml b/minecraft-entities-derive/Cargo.toml index 7b504bbe..c6922f18 100644 --- a/minecraft-entities-derive/Cargo.toml +++ b/minecraft-entities-derive/Cargo.toml @@ -9,3 +9,5 @@ proc-macro = true [dependencies] convert_case = "0.6" proc-macro-error = "1.0.4" +quote = "1.0" +proc-macro2 = "1.0" diff --git a/minecraft-entities-derive/src/lib.rs b/minecraft-entities-derive/src/lib.rs index 7695e04a..d7444d6d 100644 --- a/minecraft-entities-derive/src/lib.rs +++ b/minecraft-entities-derive/src/lib.rs @@ -1,8 +1,9 @@ use std::collections::HashMap; -use proc_macro::{TokenStream, TokenTree, Ident, Group}; +use proc_macro2::{TokenStream, TokenTree, Ident, Group, Delimiter}; use convert_case::{Case, Casing}; use proc_macro_error::*; +use quote::quote; fn replace_idents(token: &mut TokenTree, to_replace: &HashMap<&'static str, Ident>) { match token { @@ -26,9 +27,13 @@ fn replace_idents(token: &mut TokenTree, to_replace: &HashMap<&'static str, Iden #[allow(non_snake_case)] #[proc_macro_attribute] #[proc_macro_error] -pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { +pub fn MinecraftEntity(attr: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream { + let attr = TokenStream::from(attr.clone()); + let item = TokenStream::from(item.clone()); + let mut ancestors = Vec::new(); let mut descendants = Vec::new(); + let mut wildcard_descendants = Vec::new(); let mut inheritable = false; let mut defines = Vec::new(); let mut codes = Vec::new(); @@ -82,7 +87,6 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { let mut group_attrs = group.stream().into_iter().peekable(); while let Some(ident) = group_attrs.next() { let TokenTree::Ident(ident) = ident else { abort!(ident.span(), "expected ident") }; - let mut generic = false; if matches!(group_attrs.peek(), Some(TokenTree::Punct(punct)) if punct.as_char() == '.') { let dot = group_attrs.next().unwrap(); if !matches!(group_attrs.next(), Some(TokenTree::Punct(punct)) if punct.as_char() == '.') { @@ -91,9 +95,10 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { if !matches!(group_attrs.next(), Some(TokenTree::Punct(punct)) if punct.as_char() == '.') { abort!(dot.span(), "this dot needs to come with two other dots"); } - generic = true; + descendants.push(ident); + } else { + wildcard_descendants.push(ident); } - descendants.push((ident, generic)); if matches!(group_attrs.peek(), Some(TokenTree::Punct(punct)) if punct.as_char() == ',') { group_attrs.next(); } @@ -115,7 +120,7 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { } let Some(group) = group_attrs.next() else { abort!(method.span(), "expected group after method name") }; let TokenTree::Group(params) = group else { abort!(group.span(), "expected group") }; - if params.delimiter() != proc_macro::Delimiter::Parenthesis { + if params.delimiter() != Delimiter::Parenthesis { abort!(params.span(), "expected parenthesis"); } let mut params = params.stream().into_iter().peekable(); @@ -156,7 +161,9 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { hierarchy.insert(0, struct_name.clone()); let mut to_replace = HashMap::new(); - to_replace.insert("This", struct_name.clone()); + let this = struct_name.clone(); + let this_snake = Ident::new(&struct_name.to_string().to_case(Case::Snake), struct_name.span()); + to_replace.insert("This", this.clone()); to_replace.insert("ThisDescendant", Ident::new(&format!("{}Descendant", struct_name), struct_name.span())); to_replace.insert("ThisMethods", Ident::new(&format!("{}Methods", struct_name), struct_name.span())); to_replace.insert("ThisExt", Ident::new(&format!("{}Ext", struct_name), struct_name.span())); @@ -230,32 +237,6 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { } let code: TokenStream = code.into_iter().collect(); codes.push(code); - } else { - // Implement TryAsEntityRef for this struct - let code: TokenStream = r#" - #[automatically_derived] - impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&This> { - match self { - AnyEntity::This(ref val) => Some(val), - _ => None, - } - } - - fn try_as_entity_mut(&mut self) -> Option<&mut This> { - match self { - AnyEntity::This(ref mut val) => Some(val), - _ => None, - } - } - } - "#.parse().unwrap(); - let mut code = code.clone().into_iter().collect::>(); - for element in &mut code { - replace_idents(element, &to_replace); - } - let code: TokenStream = code.into_iter().collect(); - codes.push(code); } // Generate ext trait @@ -455,11 +436,48 @@ pub fn MinecraftEntity(attr: TokenStream, item: TokenStream) -> TokenStream { let code: TokenStream = code.into_iter().collect(); codes.push(code); } + + // Implement TryAsEntityRef + let descendants_snake = descendants.iter().map(|i| Ident::new(i.to_string().to_case(Case::Snake).as_str(), i.span())).collect::>(); + let wildcard_descendants_snake = wildcard_descendants.iter().map(|i| Ident::new(i.to_string().to_case(Case::Snake).as_str(), i.span())).collect::>(); + let code = quote! { + #[automatically_derived] + impl TryAsEntityRef<#this> for AnyEntity { + fn try_as_entity_ref(&self) -> Option<&#this> { + match self { + AnyEntity::#this(#this_snake) => return Some(#this_snake), + #( AnyEntity::#descendants(#descendants_snake) => return Some(&#descendants_snake.#this_snake), )* + _ => (), + } + #( + if let Some(#wildcard_descendants_snake) = >::try_as_entity_ref(self) { + return Some(&#wildcard_descendants_snake.#this_snake) + } + )* + None + } + + fn try_as_entity_mut(&mut self) -> Option<&mut #this> { + match self { + AnyEntity::#this(#this_snake) => return Some(#this_snake), + #( AnyEntity::#descendants(#descendants_snake) => return Some(&mut #descendants_snake.#this_snake), )* + _ => (), + } + #( + if >::try_as_entity_ref(self).is_some() { + return >::try_as_entity_mut(self).map(|#wildcard_descendants_snake| &mut #wildcard_descendants_snake.#this_snake) + } + )* + None + } + } + }; + codes.push(code); // Generate final code let mut final_code = item; for code in codes { final_code.extend(code); } - final_code + proc_macro::TokenStream::from(final_code) } From b9581fd1ff8094cfb22e4c583994400d58a43fc2 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 02:38:28 +0100 Subject: [PATCH 38/89] Use newer code --- minecraft-entities/src/animals/cow.rs | 22 +- minecraft-entities/src/animals/horses.rs | 90 +----- minecraft-entities/src/animals/mod.rs | 50 +--- .../src/animals/water_animal.rs | 62 +--- minecraft-entities/src/arrow.rs | 26 +- minecraft-entities/src/boat.rs | 22 +- minecraft-entities/src/display.rs | 26 +- minecraft-entities/src/entity.rs | 277 +----------------- minecraft-entities/src/item.rs | 22 +- minecraft-entities/src/living_entity.rs | 30 +- minecraft-entities/src/mobs/flying.rs | 24 +- minecraft-entities/src/mobs/golems.rs | 24 +- minecraft-entities/src/mobs/mod.rs | 113 +------ minecraft-entities/src/mobs/villagers.rs | 24 +- minecraft-entities/src/monsters/guardian.rs | 22 +- minecraft-entities/src/monsters/mod.rs | 35 +-- minecraft-entities/src/monsters/piglin.rs | 24 +- minecraft-entities/src/monsters/raider.rs | 88 +----- minecraft-entities/src/monsters/skeleton.rs | 26 +- minecraft-entities/src/monsters/zombies.rs | 28 +- .../src/thrown_item_projectile.rs | 30 +- 21 files changed, 89 insertions(+), 976 deletions(-) diff --git a/minecraft-entities/src/animals/cow.rs b/minecraft-entities/src/animals/cow.rs index e280ad16..e13915e0 100644 --- a/minecraft-entities/src/animals/cow.rs +++ b/minecraft-entities/src/animals/cow.rs @@ -2,30 +2,14 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - inheritable, ancestors { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, + ancestors { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + descendants { Mooshroom }, )] pub struct Cow { pub animal: Animal, } -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&Cow> { - match self { - AnyEntity::Cow(cow) => return Some(&cow), - AnyEntity::Mooshroom(mooshroom) => return Some(&mooshroom.cow), - _ => None, - } - } - - fn try_as_entity_mut(&mut self) -> Option<&mut Cow> { - match self { - AnyEntity::Cow(cow) => return Some(cow), - AnyEntity::Mooshroom(mooshroom) => return Some(&mut mooshroom.cow), - _ => None, - } - } -} - #[derive(Default)] #[MinecraftEntity( ancestors { Cow, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, diff --git a/minecraft-entities/src/animals/horses.rs b/minecraft-entities/src/animals/horses.rs index 4e3aaf2d..af9172f6 100644 --- a/minecraft-entities/src/animals/horses.rs +++ b/minecraft-entities/src/animals/horses.rs @@ -2,7 +2,9 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - inheritable, ancestors { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, + ancestors { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + descendants { Horse, ZombieHorse, SkeletonHorse, Camel, ChestedHorse... }, )] pub struct AbstractHorse { pub animal: Animal, @@ -18,38 +20,6 @@ pub struct Horse { pub variant: usize, } -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&AbstractHorse> { - match self { - AnyEntity::AbstractHorse(abstract_horse) => return Some(&abstract_horse), - AnyEntity::Horse(horse) => return Some(&horse.abstract_horse), - AnyEntity::ZombieHorse(zombie_horse) => return Some(&zombie_horse.abstract_horse), - AnyEntity::SkeletonHorse(skeleton_horse) => return Some(&skeleton_horse.abstract_horse), - AnyEntity::Camel(camel) => return Some(&camel.abstract_horse), - _ => (), - } - if let Some(chested_horse) = >::try_as_entity_ref(self) { - return Some(&chested_horse.abstract_horse) - } - None - } - - fn try_as_entity_mut(&mut self) -> Option<&mut AbstractHorse> { - match self { - AnyEntity::AbstractHorse(abstract_horse) => return Some(abstract_horse), - AnyEntity::Horse(horse) => return Some(&mut horse.abstract_horse), - AnyEntity::ZombieHorse(zombie_horse) => return Some(&mut zombie_horse.abstract_horse), - AnyEntity::SkeletonHorse(skeleton_horse) => return Some(&mut skeleton_horse.abstract_horse), - AnyEntity::Camel(camel) => return Some(&mut camel.abstract_horse), - _ => (), - } - if let Some(chested_horse) = >::try_as_entity_mut(self) { - return Some(&mut chested_horse.abstract_horse) - } - None - } -} - #[derive(Default)] #[MinecraftEntity( ancestors { AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, @@ -78,41 +48,15 @@ pub struct Camel { #[derive(Default)] #[MinecraftEntity( - inheritable, ancestors { AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, + ancestors { AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + descendants { Mule, Donkey, Llama... }, )] pub struct ChestedHorse { pub abstract_horse: AbstractHorse, pub has_chest: bool, } -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&ChestedHorse> { - match self { - AnyEntity::ChestedHorse(chested_horse) => return Some(&chested_horse), - AnyEntity::Mule(mule) => return Some(&mule.chested_horse), - AnyEntity::Donkey(donkey) => return Some(&donkey.chested_horse), - _ => (), - } - if let Some(llama) = >::try_as_entity_ref(self) { - return Some(&llama.chested_horse) - } - None - } - - fn try_as_entity_mut(&mut self) -> Option<&mut ChestedHorse> { - match self { - AnyEntity::ChestedHorse(chested_horse) => return Some(chested_horse), - AnyEntity::Mule(mule) => return Some(&mut mule.chested_horse), - AnyEntity::Donkey(donkey) => return Some(&mut donkey.chested_horse), - _ => (), - } - if let Some(llama) = >::try_as_entity_mut(self) { - return Some(&mut llama.chested_horse) - } - None - } -} - #[derive(Default)] #[MinecraftEntity( ancestors { ChestedHorse, AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, @@ -130,7 +74,9 @@ pub struct Donkey { } #[MinecraftEntity( - inheritable, ancestors { ChestedHorse, AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, + ancestors { ChestedHorse, AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + descendants { TraderLlama }, )] pub struct Llama { pub chested_horse: ChestedHorse, @@ -152,24 +98,6 @@ impl Default for Llama { } } -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&Llama> { - match self { - AnyEntity::Llama(llama) => Some(&llama), - AnyEntity::TraderLlama(trader_llama) => Some(&trader_llama.llama), - _ => None, - } - } - - fn try_as_entity_mut(&mut self) -> Option<&mut Llama> { - match self { - AnyEntity::Llama(llama) => Some(llama), - AnyEntity::TraderLlama(trader_llama) => Some(&mut trader_llama.llama), - _ => None, - } - } -} - #[derive(Default)] #[MinecraftEntity( ancestors { Llama, ChestedHorse, AbstractHorse, Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, diff --git a/minecraft-entities/src/animals/mod.rs b/minecraft-entities/src/animals/mod.rs index f9dcbcff..ae316075 100644 --- a/minecraft-entities/src/animals/mod.rs +++ b/minecraft-entities/src/animals/mod.rs @@ -47,60 +47,22 @@ pub use water_animal::*; #[derive(Default)] #[MinecraftEntity( - inheritable, ancestors { AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, + ancestors { AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + descendants { TameableAnimal... }, )] pub struct Animal { pub ageable_mob: AgeableMob, } -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&Animal> { - match self { - AnyEntity::Animal(animal) => return Some(&animal), - _ => (), - } - if let Some(tameable_animal) = >::try_as_entity_ref(self) { - return Some(&tameable_animal.animal) - } - None - } - - fn try_as_entity_mut(&mut self) -> Option<&mut Animal> { - match self { - AnyEntity::Animal(animal) => return Some(animal), - _ => (), - } - if let Some(tameable_animal) = >::try_as_entity_mut(self) { - return Some(&mut tameable_animal.animal) - } - None - } -} - #[derive(Default)] #[MinecraftEntity( - inheritable, ancestors { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, + ancestors { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + descendants { } )] pub struct TameableAnimal { pub animal: Animal, pub action_mask: u8, pub owner: Option, } - -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&TameableAnimal> { - match self { - AnyEntity::TameableAnimal(tameable_animal) => return Some(&tameable_animal), - _ => (), - } - None - } - - fn try_as_entity_mut(&mut self) -> Option<&mut TameableAnimal> { - match self { - AnyEntity::TameableAnimal(tameable_animal) => return Some(tameable_animal), - _ => (), - } - None - } -} diff --git a/minecraft-entities/src/animals/water_animal.rs b/minecraft-entities/src/animals/water_animal.rs index 1105957a..3645aa2e 100644 --- a/minecraft-entities/src/animals/water_animal.rs +++ b/minecraft-entities/src/animals/water_animal.rs @@ -2,40 +2,14 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - inheritable, ancestors { PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, + ancestors { PathfinderMob, Mob, LivingEntity, Entity }, + descendants { Dolphin, Squid, AbstractFish... }, )] pub struct WaterAnimal { pub pathfinder_mob: PathfinderMob, } -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&WaterAnimal> { - match self { - AnyEntity::WaterAnimal(water_animal) => return Some(&water_animal), - AnyEntity::Dolphin(dolphin) => return Some(&dolphin.water_animal), - AnyEntity::Squid(squid) => return Some(&squid.water_animal), - _ => (), - } - if let Some(fish) = >::try_as_entity_ref(self) { - return Some(&fish.water_animal) - } - None - } - - fn try_as_entity_mut(&mut self) -> Option<&mut WaterAnimal> { - match self { - AnyEntity::WaterAnimal(water_animal) => return Some(water_animal), - AnyEntity::Dolphin(dolphin) => return Some(&mut dolphin.water_animal), - AnyEntity::Squid(squid) => return Some(&mut squid.water_animal), - _ => (), - } - if let Some(fish) = >::try_as_entity_mut(self) { - return Some(&mut fish.water_animal) - } - None - } -} - #[derive(Default)] #[MinecraftEntity( ancestors { WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, @@ -57,39 +31,15 @@ pub struct Squid { #[derive(Default)] #[MinecraftEntity( - inheritable, ancestors { WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, + ancestors { WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, + descendants { Cod, PufferFish, Salmon, TropicalFish, Tadpole... }, )] pub struct AbstractFish { pub water_animal: WaterAnimal, pub from_bucket: bool, } -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&AbstractFish> { - match self { - AnyEntity::AbstractFish(abstract_fish) => Some(&abstract_fish), - AnyEntity::Cod(cod) => Some(&cod.abstract_fish), - AnyEntity::PufferFish(puffer_fish) => Some(&puffer_fish.abstract_fish), - AnyEntity::Salmon(salmon) => Some(&salmon.abstract_fish), - AnyEntity::TropicalFish(tropical_fish) => Some(&tropical_fish.abstract_fish), - AnyEntity::Tadpole(tadpole) => Some(&tadpole.abstract_fish), - _ => None, - } - } - - fn try_as_entity_mut(&mut self) -> Option<&mut AbstractFish> { - match self { - AnyEntity::AbstractFish(abstract_fish) => Some(abstract_fish), - AnyEntity::Cod(cod) => Some(&mut cod.abstract_fish), - AnyEntity::PufferFish(puffer_fish) => Some(&mut puffer_fish.abstract_fish), - AnyEntity::Salmon(salmon) => Some(&mut salmon.abstract_fish), - AnyEntity::TropicalFish(tropical_fish) => Some(&mut tropical_fish.abstract_fish), - AnyEntity::Tadpole(tadpole) => Some(&mut tadpole.abstract_fish), - _ => None, - } - } -} - #[derive(Default)] #[MinecraftEntity( ancestors { AbstractFish, WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, diff --git a/minecraft-entities/src/arrow.rs b/minecraft-entities/src/arrow.rs index f6bb1f5b..7a8367f2 100644 --- a/minecraft-entities/src/arrow.rs +++ b/minecraft-entities/src/arrow.rs @@ -1,7 +1,9 @@ use super::*; #[MinecraftEntity( - inheritable, ancestors { Entity }, + inheritable, + ancestors { Entity }, + descendants { Arrow, SpectralArrow, ThrownTrident }, )] pub struct AbstractArrow { pub entity: Entity, @@ -21,28 +23,6 @@ impl Default for AbstractArrow { } } -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&AbstractArrow> { - match self { - AnyEntity::AbstractArrow(abstract_arrow) => Some(abstract_arrow), - AnyEntity::Arrow(arrow) => Some(&arrow.abstract_arrow), - AnyEntity::SpectralArrow(spectral_arrow) => Some(&spectral_arrow.abstract_arrow), - AnyEntity::ThrownTrident(thrown_trident) => Some(&thrown_trident.abstract_arrow), - _ => None, - } - } - - fn try_as_entity_mut(&mut self) -> Option<&mut AbstractArrow> { - match self { - AnyEntity::AbstractArrow(abstract_arrow) => Some(abstract_arrow), - AnyEntity::Arrow(arrow) => Some(&mut arrow.abstract_arrow), - AnyEntity::SpectralArrow(spectral_arrow) => Some(&mut spectral_arrow.abstract_arrow), - AnyEntity::ThrownTrident(thrown_trident) => Some(&mut thrown_trident.abstract_arrow), - _ => None, - } - } -} - #[MinecraftEntity( ancestors { AbstractArrow, Entity }, )] diff --git a/minecraft-entities/src/boat.rs b/minecraft-entities/src/boat.rs index 0da1ee2b..53288360 100644 --- a/minecraft-entities/src/boat.rs +++ b/minecraft-entities/src/boat.rs @@ -1,7 +1,9 @@ use super::*; #[MinecraftEntity( - inheritable, ancestors { Entity }, + inheritable, + ancestors { Entity }, + descendants { ChestBoat }, )] pub struct Boat { pub entity: Entity, @@ -30,24 +32,6 @@ impl Default for Boat { } } -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&Boat> { - match self { - AnyEntity::Boat(boat) => Some(boat), - AnyEntity::ChestBoat(chest_boat) => Some(&chest_boat.boat), - _ => None, - } - } - - fn try_as_entity_mut(&mut self) -> Option<&mut Boat> { - match self { - AnyEntity::Boat(boat) => Some(boat), - AnyEntity::ChestBoat(chest_boat) => Some(&mut chest_boat.boat), - _ => None, - } - } -} - #[derive(Default)] #[MinecraftEntity( ancestors { Boat, Entity }, diff --git a/minecraft-entities/src/display.rs b/minecraft-entities/src/display.rs index c5b54a17..e5f2527f 100644 --- a/minecraft-entities/src/display.rs +++ b/minecraft-entities/src/display.rs @@ -2,7 +2,9 @@ use super::*; use minecraft_protocol::components::paintings::Painting as PaintingType; #[MinecraftEntity( - inheritable, ancestors { Entity }, + inheritable, + ancestors { Entity }, + descendants { BlockDisplay, ItemDisplay, TextDisplay }, )] pub struct Display { pub entity: Entity, @@ -52,28 +54,6 @@ impl Default for Display { } } -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&Display> { - match self { - AnyEntity::Display(display) => Some(display), - AnyEntity::BlockDisplay(block_display) => Some(&block_display.display), - AnyEntity::ItemDisplay(item_display) => Some(&item_display.display), - AnyEntity::TextDisplay(text_display) => Some(&text_display.display), - _ => None, - } - } - - fn try_as_entity_mut(&mut self) -> Option<&mut Display> { - match self { - AnyEntity::Display(display) => Some(display), - AnyEntity::BlockDisplay(block_display) => Some(&mut block_display.display), - AnyEntity::ItemDisplay(item_display) => Some(&mut item_display.display), - AnyEntity::TextDisplay(text_display) => Some(&mut text_display.display), - _ => None, - } - } -} - #[MinecraftEntity( ancestors { Display, Entity }, )] diff --git a/minecraft-entities/src/entity.rs b/minecraft-entities/src/entity.rs index 97fbee28..29f47726 100644 --- a/minecraft-entities/src/entity.rs +++ b/minecraft-entities/src/entity.rs @@ -1,7 +1,8 @@ use super::*; #[MinecraftEntity( - inheritable + inheritable, + descendants { }, )] pub struct Entity { pub position: Position, @@ -42,277 +43,3 @@ impl Default for Entity { } } } - -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&Entity> { - Some(match self { - AnyEntity::Entity(entity) => entity, - AnyEntity::Interaction(interaction) => interaction.get_entity(), - AnyEntity::Display(display) => display.get_entity(), - AnyEntity::BlockDisplay(block_display) => block_display.get_entity(), - AnyEntity::ItemDisplay(item_display) => item_display.get_entity(), - AnyEntity::TextDisplay(text_display) => text_display.get_entity(), - AnyEntity::ThrownItemProjectile(throw_item_projectile) => throw_item_projectile.get_entity(), - AnyEntity::ThrownEgg(throw_egg) => throw_egg.get_entity(), - AnyEntity::ThrownEnderPearl(throw_ender_pearl) => throw_ender_pearl.get_entity(), - AnyEntity::ThrownExperienceBottle(throw_experience_bottle) => throw_experience_bottle.get_entity(), - AnyEntity::ThrownPotion(throw_potion) => throw_potion.get_entity(), - AnyEntity::Snowball(snowball) => snowball.get_entity(), - AnyEntity::AbstractArrow(abstract_arrow) => abstract_arrow.get_entity(), - AnyEntity::Arrow(arrow) => arrow.get_entity(), - AnyEntity::SpectralArrow(spectral_arrow) => spectral_arrow.get_entity(), - AnyEntity::ThrownTrident(throw_trident) => throw_trident.get_entity(), - AnyEntity::Boat(boat) => boat.get_entity(), - AnyEntity::ChestBoat(chest_boat) => chest_boat.get_entity(), - AnyEntity::LivingEntity(living_entity) => living_entity.get_entity(), - AnyEntity::Player(player) => player.get_entity(), - AnyEntity::Mob(mob) => mob.get_entity(), - AnyEntity::AmbientCreature(ambient_creature) => ambient_creature.get_entity(), - AnyEntity::Bat(bat) => bat.get_entity(), - AnyEntity::PathfinderMob(pathfinder_mob) => pathfinder_mob.get_entity(), - AnyEntity::WaterAnimal(water_animal) => water_animal.get_entity(), - AnyEntity::Squid(squid) => squid.get_entity(), - AnyEntity::AgeableMob(ageable_mob) => ageable_mob.get_entity(), - AnyEntity::Animal(animal) => animal.get_entity(), - AnyEntity::Sniffer(sniffer) => sniffer.get_entity(), - AnyEntity::AbstractHorse(abstract_horse) => abstract_horse.get_entity(), - AnyEntity::ZombieHorse(zombie_horse) => zombie_horse.get_entity(), - AnyEntity::Horse(horse) => horse.get_entity(), - AnyEntity::SkeletonHorse(skeleton_horse) => skeleton_horse.get_entity(), - AnyEntity::Camel(camel) => camel.get_entity(), - AnyEntity::ChestedHorse(chested_horse) => chested_horse.get_entity(), - AnyEntity::Donkey(donkey) => donkey.get_entity(), - AnyEntity::Llama(llama) => llama.get_entity(), - AnyEntity::TraderLlama(trader_llama) => trader_llama.get_entity(), - AnyEntity::Mule(mule) => mule.get_entity(), - AnyEntity::Axolotl(axolotl) => axolotl.get_entity(), - AnyEntity::Bee(bee) => bee.get_entity(), - AnyEntity::Fox(fox) => fox.get_entity(), - AnyEntity::Frog(frog) => frog.get_entity(), - AnyEntity::Ocelot(ocelot) => ocelot.get_entity(), - AnyEntity::Panda(panda) => panda.get_entity(), - AnyEntity::Pig(pig) => pig.get_entity(), - AnyEntity::Rabbit(rabbit) => rabbit.get_entity(), - AnyEntity::Turtle(turtle) => turtle.get_entity(), - AnyEntity::PolarBear(polar_bear) => polar_bear.get_entity(), - AnyEntity::Chicken(chicken) => chicken.get_entity(), - AnyEntity::Cow(cow) => cow.get_entity(), - AnyEntity::Hoglin(hoglin) => hoglin.get_entity(), - AnyEntity::Mooshroom(mooshroom) => mooshroom.get_entity(), - AnyEntity::Sheep(sheep) => sheep.get_entity(), - AnyEntity::Strider(strider) => strider.get_entity(), - AnyEntity::TameableAnimal(tameable_animal) => tameable_animal.get_entity(), - AnyEntity::Cat(cat) => cat.get_entity(), - AnyEntity::Wolf(wolf) => wolf.get_entity(), - AnyEntity::Parrot(parrot) => parrot.get_entity(), - AnyEntity::AbstractVillager(abstract_villager) => abstract_villager.get_entity(), - AnyEntity::Villager(villager) => villager.get_entity(), - AnyEntity::WanderingTrader(wandering_trader) => wandering_trader.get_entity(), - AnyEntity::AbstractGolem(abstract_golem) => abstract_golem.get_entity(), - AnyEntity::IronGolem(iron_golem) => iron_golem.get_entity(), - AnyEntity::SnowGolem(snow_golem) => snow_golem.get_entity(), - AnyEntity::Shulker(shulker) => shulker.get_entity(), - AnyEntity::Monster(monster) => monster.get_entity(), - AnyEntity::BasePiglin(base_piglin) => base_piglin.get_entity(), - AnyEntity::Piglin(piglin) => piglin.get_entity(), - AnyEntity::PiglinBrute(piglin_brute) => piglin_brute.get_entity(), - AnyEntity::Blaze(blaze) => blaze.get_entity(), - AnyEntity::Creeper(creeper) => creeper.get_entity(), - AnyEntity::Endermite(endermite) => endermite.get_entity(), - AnyEntity::Giant(giant) => giant.get_entity(), - AnyEntity::Goat(goat) => goat.get_entity(), - AnyEntity::Guardian(guardian) => guardian.get_entity(), - AnyEntity::ElderGuardian(elder_guardian) => elder_guardian.get_entity(), - AnyEntity::Silverfish(silverfish) => silverfish.get_entity(), - AnyEntity::Raider(raider) => raider.get_entity(), - AnyEntity::AbstractIllager(abstract_illager) => abstract_illager.get_entity(), - AnyEntity::Vindicator(vindicator) => vindicator.get_entity(), - AnyEntity::Pillager(pillager) => pillager.get_entity(), - AnyEntity::SpellcasterIllager(spellcaster_illager) => spellcaster_illager.get_entity(), - AnyEntity::Evoker(evoker) => evoker.get_entity(), - AnyEntity::Illusioner(illusioner) => illusioner.get_entity(), - AnyEntity::Ravager(ravager) => ravager.get_entity(), - AnyEntity::Witch(witch) => witch.get_entity(), - AnyEntity::EvokerFangs(evoker_fangs) => evoker_fangs.get_entity(), - AnyEntity::Vex(vex) => vex.get_entity(), - AnyEntity::Skeleton(skeleton) => skeleton.get_entity(), - AnyEntity::AbstractSkeleton(abstract_skeleton) => abstract_skeleton.get_entity(), - AnyEntity::WitherSkeleton(wither_skeleton) => wither_skeleton.get_entity(), - AnyEntity::Stray(stray) => stray.get_entity(), - AnyEntity::Spider(spider) => spider.get_entity(), - AnyEntity::Warden(warden) => warden.get_entity(), - AnyEntity::Wither(wither) => wither.get_entity(), - AnyEntity::Zoglin(zoglin) => zoglin.get_entity(), - AnyEntity::Zombie(zombie) => zombie.get_entity(), - AnyEntity::ZombieVillager(zombie_villager) => zombie_villager.get_entity(), - AnyEntity::Husk(husk) => husk.get_entity(), - AnyEntity::Drowned(drowned) => drowned.get_entity(), - AnyEntity::ZombifiedPiglin(zombified_piglin) => zombified_piglin.get_entity(), - AnyEntity::Enderman(enderman) => enderman.get_entity(), - AnyEntity::EnderDragon(ender_dragon) => ender_dragon.get_entity(), - AnyEntity::Flying(flying) => flying.get_entity(), - AnyEntity::Ghast(ghast) => ghast.get_entity(), - AnyEntity::Phantom(phantom) => phantom.get_entity(), - AnyEntity::Slime(slime) => slime.get_entity(), - AnyEntity::LlamaSpit(llama_spit) => llama_spit.get_entity(), - AnyEntity::EyeOfEnder(eye_of_ender) => eye_of_ender.get_entity(), - AnyEntity::FallingBlock(falling_block) => falling_block.get_entity(), - AnyEntity::AreaEffectCloud(area_effect_cloud) => area_effect_cloud.get_entity(), - AnyEntity::FishingHook(fishing_hook) => fishing_hook.get_entity(), - AnyEntity::EndCrystal(end_crystal) => end_crystal.get_entity(), - AnyEntity::DragonFireball(dragon_fireball) => dragon_fireball.get_entity(), - AnyEntity::SmallFireball(small_fireball) => small_fireball.get_entity(), - AnyEntity::Fireball(fireball) => fireball.get_entity(), - AnyEntity::WitherSkull(wither_skull) => wither_skull.get_entity(), - AnyEntity::FireworkRocket(firework_rocket) => firework_rocket.get_entity(), - AnyEntity::ItemFrame(item_frame) => item_frame.get_entity(), - AnyEntity::GlowingItemFrame(glowing_item_frame) => glowing_item_frame.get_entity(), - AnyEntity::Painting(painting) => painting.get_entity(), - AnyEntity::ItemEntity(item_entity) => item_entity.get_entity(), - AnyEntity::ArmorStand(armor_stand) => armor_stand.get_entity(), - AnyEntity::Dolphin(dolphin) => dolphin.get_entity(), - AnyEntity::AbstractFish(abstract_fish) => abstract_fish.get_entity(), - AnyEntity::Cod(cod) => cod.get_entity(), - AnyEntity::PufferFish(pufferfish) => pufferfish.get_entity(), - AnyEntity::Salmon(salmon) => salmon.get_entity(), - AnyEntity::TropicalFish(tropical_fish) => tropical_fish.get_entity(), - AnyEntity::Tadpole(tadpole) => tadpole.get_entity(), - }) - } - - fn try_as_entity_mut(&mut self) -> Option<&mut Entity> { - Some(match self { - AnyEntity::Entity(entity) => entity, - AnyEntity::Interaction(interaction) => interaction.get_entity_mut(), - AnyEntity::Display(display) => display.get_entity_mut(), - AnyEntity::BlockDisplay(block_display) => block_display.get_entity_mut(), - AnyEntity::ItemDisplay(item_display) => item_display.get_entity_mut(), - AnyEntity::TextDisplay(text_display) => text_display.get_entity_mut(), - AnyEntity::ThrownItemProjectile(throw_item_projectile) => throw_item_projectile.get_entity_mut(), - AnyEntity::ThrownEgg(throw_egg) => throw_egg.get_entity_mut(), - AnyEntity::ThrownEnderPearl(throw_ender_pearl) => throw_ender_pearl.get_entity_mut(), - AnyEntity::ThrownExperienceBottle(throw_experience_bottle) => throw_experience_bottle.get_entity_mut(), - AnyEntity::ThrownPotion(throw_potion) => throw_potion.get_entity_mut(), - AnyEntity::Snowball(snowball) => snowball.get_entity_mut(), - AnyEntity::AbstractArrow(abstract_arrow) => abstract_arrow.get_entity_mut(), - AnyEntity::Arrow(arrow) => arrow.get_entity_mut(), - AnyEntity::SpectralArrow(spectral_arrow) => spectral_arrow.get_entity_mut(), - AnyEntity::ThrownTrident(throw_trident) => throw_trident.get_entity_mut(), - AnyEntity::Boat(boat) => boat.get_entity_mut(), - AnyEntity::ChestBoat(chest_boat) => chest_boat.get_entity_mut(), - AnyEntity::LivingEntity(living_entity) => living_entity.get_entity_mut(), - AnyEntity::Player(player) => player.get_entity_mut(), - AnyEntity::Mob(mob) => mob.get_entity_mut(), - AnyEntity::AmbientCreature(ambient_creature) => ambient_creature.get_entity_mut(), - AnyEntity::Bat(bat) => bat.get_entity_mut(), - AnyEntity::PathfinderMob(pathfinder_mob) => pathfinder_mob.get_entity_mut(), - AnyEntity::WaterAnimal(water_animal) => water_animal.get_entity_mut(), - AnyEntity::Squid(squid) => squid.get_entity_mut(), - AnyEntity::AgeableMob(ageable_mob) => ageable_mob.get_entity_mut(), - AnyEntity::Animal(animal) => animal.get_entity_mut(), - AnyEntity::Sniffer(sniffer) => sniffer.get_entity_mut(), - AnyEntity::AbstractHorse(abstract_horse) => abstract_horse.get_entity_mut(), - AnyEntity::ZombieHorse(zombie_horse) => zombie_horse.get_entity_mut(), - AnyEntity::Horse(horse) => horse.get_entity_mut(), - AnyEntity::SkeletonHorse(skeleton_horse) => skeleton_horse.get_entity_mut(), - AnyEntity::Camel(camel) => camel.get_entity_mut(), - AnyEntity::ChestedHorse(chested_horse) => chested_horse.get_entity_mut(), - AnyEntity::Donkey(donkey) => donkey.get_entity_mut(), - AnyEntity::Llama(llama) => llama.get_entity_mut(), - AnyEntity::TraderLlama(trader_llama) => trader_llama.get_entity_mut(), - AnyEntity::Mule(mule) => mule.get_entity_mut(), - AnyEntity::Axolotl(axolotl) => axolotl.get_entity_mut(), - AnyEntity::Bee(bee) => bee.get_entity_mut(), - AnyEntity::Fox(fox) => fox.get_entity_mut(), - AnyEntity::Frog(frog) => frog.get_entity_mut(), - AnyEntity::Ocelot(ocelot) => ocelot.get_entity_mut(), - AnyEntity::Panda(panda) => panda.get_entity_mut(), - AnyEntity::Pig(pig) => pig.get_entity_mut(), - AnyEntity::Rabbit(rabbit) => rabbit.get_entity_mut(), - AnyEntity::Turtle(turtle) => turtle.get_entity_mut(), - AnyEntity::PolarBear(polar_bear) => polar_bear.get_entity_mut(), - AnyEntity::Chicken(chicken) => chicken.get_entity_mut(), - AnyEntity::Cow(cow) => cow.get_entity_mut(), - AnyEntity::Hoglin(hoglin) => hoglin.get_entity_mut(), - AnyEntity::Mooshroom(mooshroom) => mooshroom.get_entity_mut(), - AnyEntity::Sheep(sheep) => sheep.get_entity_mut(), - AnyEntity::Strider(strider) => strider.get_entity_mut(), - AnyEntity::TameableAnimal(tameable_animal) => tameable_animal.get_entity_mut(), - AnyEntity::Cat(cat) => cat.get_entity_mut(), - AnyEntity::Wolf(wolf) => wolf.get_entity_mut(), - AnyEntity::Parrot(parrot) => parrot.get_entity_mut(), - AnyEntity::AbstractVillager(abstract_villager) => abstract_villager.get_entity_mut(), - AnyEntity::Villager(villager) => villager.get_entity_mut(), - AnyEntity::WanderingTrader(wandering_trader) => wandering_trader.get_entity_mut(), - AnyEntity::AbstractGolem(abstract_golem) => abstract_golem.get_entity_mut(), - AnyEntity::IronGolem(iron_golem) => iron_golem.get_entity_mut(), - AnyEntity::SnowGolem(snow_golem) => snow_golem.get_entity_mut(), - AnyEntity::Shulker(shulker) => shulker.get_entity_mut(), - AnyEntity::Monster(monster) => monster.get_entity_mut(), - AnyEntity::BasePiglin(base_piglin) => base_piglin.get_entity_mut(), - AnyEntity::Piglin(piglin) => piglin.get_entity_mut(), - AnyEntity::PiglinBrute(piglin_brute) => piglin_brute.get_entity_mut(), - AnyEntity::Blaze(blaze) => blaze.get_entity_mut(), - AnyEntity::Creeper(creeper) => creeper.get_entity_mut(), - AnyEntity::Endermite(endermite) => endermite.get_entity_mut(), - AnyEntity::Giant(giant) => giant.get_entity_mut(), - AnyEntity::Goat(goat) => goat.get_entity_mut(), - AnyEntity::Guardian(guardian) => guardian.get_entity_mut(), - AnyEntity::ElderGuardian(elder_guardian) => elder_guardian.get_entity_mut(), - AnyEntity::Silverfish(silverfish) => silverfish.get_entity_mut(), - AnyEntity::Raider(raider) => raider.get_entity_mut(), - AnyEntity::AbstractIllager(abstract_illager) => abstract_illager.get_entity_mut(), - AnyEntity::Vindicator(vindicator) => vindicator.get_entity_mut(), - AnyEntity::Pillager(pillager) => pillager.get_entity_mut(), - AnyEntity::SpellcasterIllager(spellcaster_illager) => spellcaster_illager.get_entity_mut(), - AnyEntity::Evoker(evoker) => evoker.get_entity_mut(), - AnyEntity::Illusioner(illusioner) => illusioner.get_entity_mut(), - AnyEntity::Ravager(ravager) => ravager.get_entity_mut(), - AnyEntity::Witch(witch) => witch.get_entity_mut(), - AnyEntity::EvokerFangs(evoker_fangs) => evoker_fangs.get_entity_mut(), - AnyEntity::Vex(vex) => vex.get_entity_mut(), - AnyEntity::Skeleton(skeleton) => skeleton.get_entity_mut(), - AnyEntity::AbstractSkeleton(abstract_skeleton) => abstract_skeleton.get_entity_mut(), - AnyEntity::WitherSkeleton(wither_skeleton) => wither_skeleton.get_entity_mut(), - AnyEntity::Stray(stray) => stray.get_entity_mut(), - AnyEntity::Spider(spider) => spider.get_entity_mut(), - AnyEntity::Warden(warden) => warden.get_entity_mut(), - AnyEntity::Wither(wither) => wither.get_entity_mut(), - AnyEntity::Zoglin(zoglin) => zoglin.get_entity_mut(), - AnyEntity::Zombie(zombie) => zombie.get_entity_mut(), - AnyEntity::ZombieVillager(zombie_villager) => zombie_villager.get_entity_mut(), - AnyEntity::Husk(husk) => husk.get_entity_mut(), - AnyEntity::Drowned(drowned) => drowned.get_entity_mut(), - AnyEntity::ZombifiedPiglin(zombified_piglin) => zombified_piglin.get_entity_mut(), - AnyEntity::Enderman(enderman) => enderman.get_entity_mut(), - AnyEntity::EnderDragon(ender_dragon) => ender_dragon.get_entity_mut(), - AnyEntity::Flying(flying) => flying.get_entity_mut(), - AnyEntity::Ghast(ghast) => ghast.get_entity_mut(), - AnyEntity::Phantom(phantom) => phantom.get_entity_mut(), - AnyEntity::Slime(slime) => slime.get_entity_mut(), - AnyEntity::LlamaSpit(llama_spit) => llama_spit.get_entity_mut(), - AnyEntity::EyeOfEnder(eye_of_ender) => eye_of_ender.get_entity_mut(), - AnyEntity::FallingBlock(falling_block) => falling_block.get_entity_mut(), - AnyEntity::AreaEffectCloud(area_effect_cloud) => area_effect_cloud.get_entity_mut(), - AnyEntity::FishingHook(fishing_hook) => fishing_hook.get_entity_mut(), - AnyEntity::EndCrystal(end_crystal) => end_crystal.get_entity_mut(), - AnyEntity::DragonFireball(dragon_fireball) => dragon_fireball.get_entity_mut(), - AnyEntity::SmallFireball(small_fireball) => small_fireball.get_entity_mut(), - AnyEntity::Fireball(fireball) => fireball.get_entity_mut(), - AnyEntity::WitherSkull(wither_skull) => wither_skull.get_entity_mut(), - AnyEntity::FireworkRocket(firework_rocket) => firework_rocket.get_entity_mut(), - AnyEntity::ItemFrame(item_frame) => item_frame.get_entity_mut(), - AnyEntity::GlowingItemFrame(glowing_item_frame) => glowing_item_frame.get_entity_mut(), - AnyEntity::Painting(painting) => painting.get_entity_mut(), - AnyEntity::ItemEntity(item_entity) => item_entity.get_entity_mut(), - AnyEntity::ArmorStand(armor_stand) => armor_stand.get_entity_mut(), - AnyEntity::Dolphin(dolphin) => dolphin.get_entity_mut(), - AnyEntity::AbstractFish(abstract_fish) => abstract_fish.get_entity_mut(), - AnyEntity::Cod(cod) => cod.get_entity_mut(), - AnyEntity::PufferFish(pufferfish) => pufferfish.get_entity_mut(), - AnyEntity::Salmon(salmon) => salmon.get_entity_mut(), - AnyEntity::TropicalFish(tropical_fish) => tropical_fish.get_entity_mut(), - AnyEntity::Tadpole(tadpole) => tadpole.get_entity_mut(), - }) - } -} diff --git a/minecraft-entities/src/item.rs b/minecraft-entities/src/item.rs index 7619b973..3d4eede4 100644 --- a/minecraft-entities/src/item.rs +++ b/minecraft-entities/src/item.rs @@ -2,7 +2,9 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - inheritable, ancestors { Entity }, + inheritable, + ancestors { Entity }, + descendants { GlowingItemFrame }, )] pub struct ItemFrame { pub entity: Entity, @@ -10,24 +12,6 @@ pub struct ItemFrame { pub rotation: u8, } -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&ItemFrame> { - match self { - AnyEntity::ItemFrame(item_frame) => Some(item_frame), - AnyEntity::GlowingItemFrame(glowing_item_frame) => Some(&glowing_item_frame.item_frame), - _ => None, - } - } - - fn try_as_entity_mut(&mut self) -> Option<&mut ItemFrame> { - match self { - AnyEntity::ItemFrame(item_frame) => Some(item_frame), - AnyEntity::GlowingItemFrame(glowing_item_frame) => Some(&mut glowing_item_frame.item_frame), - _ => None, - } - } -} - #[derive(Default)] #[MinecraftEntity( ancestors { ItemFrame, Entity }, diff --git a/minecraft-entities/src/living_entity.rs b/minecraft-entities/src/living_entity.rs index 476cc56b..136e4c95 100644 --- a/minecraft-entities/src/living_entity.rs +++ b/minecraft-entities/src/living_entity.rs @@ -1,7 +1,9 @@ use super::*; #[MinecraftEntity( - inheritable, ancestors { Entity }, + inheritable, + ancestors { Entity }, + descendants { Player, ArmorStand, Mob... }, )] pub struct LivingEntity { pub entity: Entity, @@ -33,32 +35,6 @@ impl Default for LivingEntity { } } -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&LivingEntity> { - match self { - AnyEntity::LivingEntity(living_entity) => return Some(living_entity), - AnyEntity::Player(player) => return Some(&player.living_entity), - _ => (), - } - if let Some(mob) = >::try_as_entity_ref(self) { - return Some(&mob.living_entity) - } - None - } - - fn try_as_entity_mut(&mut self) -> Option<&mut LivingEntity> { - match self { - AnyEntity::LivingEntity(living_entity) => return Some(living_entity), - AnyEntity::Player(player) => return Some(&mut player.living_entity), - _ => (), - } - if let Some(mob) = >::try_as_entity_mut(self) { - return Some(&mut mob.living_entity) - } - None - } -} - #[MinecraftEntity( ancestors { LivingEntity, Entity }, )] diff --git a/minecraft-entities/src/mobs/flying.rs b/minecraft-entities/src/mobs/flying.rs index 238721d3..c516c278 100644 --- a/minecraft-entities/src/mobs/flying.rs +++ b/minecraft-entities/src/mobs/flying.rs @@ -2,32 +2,14 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - inheritable, ancestors { Mob, LivingEntity, Entity }, + inheritable, + ancestors { Mob, LivingEntity, Entity }, + descendants { Ghast, Phantom }, )] pub struct Flying { pub mob: Mob, } -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&Flying> { - match self { - AnyEntity::Flying(flying) => Some(&flying), - AnyEntity::Ghast(ghast) => Some(&ghast.flying), - AnyEntity::Phantom(phantom) => Some(&phantom.flying), - _ => None, - } - } - - fn try_as_entity_mut(&mut self) -> Option<&mut Flying> { - match self { - AnyEntity::Flying(flying) => Some(flying), - AnyEntity::Ghast(ghast) => Some(&mut ghast.flying), - AnyEntity::Phantom(phantom) => Some(&mut phantom.flying), - _ => None, - } - } -} - #[derive(Default)] #[MinecraftEntity( ancestors { Flying, Mob, LivingEntity, Entity }, diff --git a/minecraft-entities/src/mobs/golems.rs b/minecraft-entities/src/mobs/golems.rs index 45c36bb5..f5971d69 100644 --- a/minecraft-entities/src/mobs/golems.rs +++ b/minecraft-entities/src/mobs/golems.rs @@ -2,32 +2,14 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - inheritable, ancestors { PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, + ancestors { PathfinderMob, Mob, LivingEntity, Entity }, + descendants { IronGolem, SnowGolem }, )] pub struct AbstractGolem { pub pathfinder_mob: PathfinderMob, } -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&AbstractGolem> { - match self { - AnyEntity::AbstractGolem(abstract_golem) => Some(&abstract_golem), - AnyEntity::IronGolem(iron_golem) => Some(&iron_golem.abstract_golem), - AnyEntity::SnowGolem(snow_golem) => Some(&snow_golem.abstract_golem), - _ => None, - } - } - - fn try_as_entity_mut(&mut self) -> Option<&mut AbstractGolem> { - match self { - AnyEntity::AbstractGolem(abstract_golem) => Some(abstract_golem), - AnyEntity::IronGolem(iron_golem) => Some(&mut iron_golem.abstract_golem), - AnyEntity::SnowGolem(snow_golem) => Some(&mut snow_golem.abstract_golem), - _ => None, - } - } -} - #[derive(Default)] #[MinecraftEntity( ancestors { AbstractGolem, PathfinderMob, Mob, LivingEntity, Entity }, diff --git a/minecraft-entities/src/mobs/mod.rs b/minecraft-entities/src/mobs/mod.rs index f6b0d861..aa25494a 100644 --- a/minecraft-entities/src/mobs/mod.rs +++ b/minecraft-entities/src/mobs/mod.rs @@ -15,7 +15,9 @@ pub use bat::*; #[derive(Default)] #[MinecraftEntity( - inheritable, ancestors { LivingEntity, Entity }, + inheritable, + ancestors { LivingEntity, Entity }, + descendants { AmbientCreature..., PathfinderMob... }, )] pub struct Mob { pub living_entity: LivingEntity, @@ -24,124 +26,33 @@ pub struct Mob { pub is_aggressive: bool, } -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&Mob> { - match self { - AnyEntity::Mob(mob) => return Some(&mob), - _ => (), - } - if let Some(ambient_creature) = >::try_as_entity_ref(self) { - return Some(&ambient_creature.mob) - } else if let Some(pathfinder_mob) = >::try_as_entity_ref(self) { - return Some(&pathfinder_mob.mob) - } - None - } - - fn try_as_entity_mut(&mut self) -> Option<&mut Mob> { - match self { - AnyEntity::Mob(mob) => return Some(mob), - _ => (), - } - if >::try_as_entity_ref(self).is_some() { - return >::try_as_entity_mut(self).map(|ambient_creature| &mut ambient_creature.mob) - } - if >::try_as_entity_ref(self).is_some() { - return >::try_as_entity_mut(self).map(|pathfinder_mob| &mut pathfinder_mob.mob) - } - None - } -} - #[derive(Default)] #[MinecraftEntity( - inheritable, ancestors { Mob, LivingEntity, Entity }, + inheritable, + ancestors { Mob, LivingEntity, Entity }, + descendants { Bat }, )] pub struct AmbientCreature { pub mob: Mob, } -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&AmbientCreature> { - match self { - AnyEntity::AmbientCreature(ambient_creature) => return Some(ambient_creature), - AnyEntity::Bat(bat) => return Some(&bat.ambient_creature), - _ => (), - } - None - } - - fn try_as_entity_mut(&mut self) -> Option<&mut AmbientCreature> { - match self { - AnyEntity::AmbientCreature(ambient_creature) => return Some(ambient_creature), - AnyEntity::Bat(bat) => return Some(&mut bat.ambient_creature), - _ => (), - } - None - } -} - #[derive(Default)] #[MinecraftEntity( - inheritable, ancestors { Mob, LivingEntity, Entity }, + inheritable, + ancestors { Mob, LivingEntity, Entity }, + descendants { AgeableMob... }, )] pub struct PathfinderMob { pub mob: Mob, } -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&PathfinderMob> { - match self { - AnyEntity::PathfinderMob(pathfinder_mob) => return Some(&pathfinder_mob), - _ => (), - } - if let Some(ageable_mob) = >::try_as_entity_ref(self) { - return Some(&ageable_mob.pathfinder_mob) - } - None - } - - fn try_as_entity_mut(&mut self) -> Option<&mut PathfinderMob> { - match self { - AnyEntity::PathfinderMob(pathfinder_mob) => return Some(pathfinder_mob), - _ => (), - } - if let Some(ageable_mob) = >::try_as_entity_mut(self) { - return Some(&mut ageable_mob.pathfinder_mob) - } - None - } -} - #[derive(Default)] #[MinecraftEntity( - inheritable, ancestors { PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, + ancestors { PathfinderMob, Mob, LivingEntity, Entity }, + descendants { AbstractVillager... }, )] pub struct AgeableMob { pub pathfinder_mob: PathfinderMob, pub is_baby: bool, } - -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&AgeableMob> { - match self { - AnyEntity::AgeableMob(ageable_mob) => return Some(ageable_mob), - _ => (), - } - if let Some(abstract_villager) = >::try_as_entity_ref(self) { - return Some(&abstract_villager.ageable_mob) - } - None - } - - fn try_as_entity_mut(&mut self) -> Option<&mut AgeableMob> { - match self { - AnyEntity::AgeableMob(ageable_mob) => return Some(ageable_mob), - _ => (), - } - if let Some(abstract_villager) = >::try_as_entity_mut(self) { - return Some(&mut abstract_villager.ageable_mob) - } - None - } -} diff --git a/minecraft-entities/src/mobs/villagers.rs b/minecraft-entities/src/mobs/villagers.rs index 65294d17..ca8a2e14 100644 --- a/minecraft-entities/src/mobs/villagers.rs +++ b/minecraft-entities/src/mobs/villagers.rs @@ -2,33 +2,15 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - inheritable, ancestors { AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, + ancestors { AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, + descendants { Villager, WanderingTrader }, )] pub struct AbstractVillager { pub ageable_mob: AgeableMob, pub head_shake_timer: u32, } -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&AbstractVillager> { - match self { - AnyEntity::AbstractVillager(abstract_villager) => return Some(&abstract_villager), - AnyEntity::Villager(villager) => return Some(&villager.abstract_villager), - AnyEntity::WanderingTrader(wandering_trader) => return Some(&wandering_trader.abstract_villager), - _ => None, - } - } - - fn try_as_entity_mut(&mut self) -> Option<&mut AbstractVillager> { - match self { - AnyEntity::AbstractVillager(abstract_villager) => return Some(abstract_villager), - AnyEntity::Villager(villager) => return Some(&mut villager.abstract_villager), - AnyEntity::WanderingTrader(wandering_trader) => return Some(&mut wandering_trader.abstract_villager), - _ => None, - } - } -} - #[derive(Default)] #[MinecraftEntity( ancestors { AbstractVillager, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, diff --git a/minecraft-entities/src/monsters/guardian.rs b/minecraft-entities/src/monsters/guardian.rs index 19567c78..0f831530 100644 --- a/minecraft-entities/src/monsters/guardian.rs +++ b/minecraft-entities/src/monsters/guardian.rs @@ -2,7 +2,9 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - inheritable, ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, + ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, + descendants { ElderGuardian }, )] pub struct Guardian { pub monster: Monster, @@ -10,24 +12,6 @@ pub struct Guardian { pub target_eid: Eid, } -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&Guardian> { - match self { - AnyEntity::Guardian(guardian) => Some(guardian), - AnyEntity::ElderGuardian(elder_guardian) => Some(&elder_guardian.guardian), - _ => None, - } - } - - fn try_as_entity_mut(&mut self) -> Option<&mut Guardian> { - match self { - AnyEntity::Guardian(guardian) => Some(guardian), - AnyEntity::ElderGuardian(elder_guardian) => Some(&mut elder_guardian.guardian), - _ => None, - } - } -} - #[derive(Default)] #[MinecraftEntity( ancestors { Guardian, Monster, PathfinderMob, Mob, LivingEntity, Entity }, diff --git a/minecraft-entities/src/monsters/mod.rs b/minecraft-entities/src/monsters/mod.rs index a0e4108b..042dfc84 100644 --- a/minecraft-entities/src/monsters/mod.rs +++ b/minecraft-entities/src/monsters/mod.rs @@ -35,39 +35,10 @@ pub use enderman::*; #[derive(Default)] #[MinecraftEntity( - inheritable, ancestors { PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, + ancestors { PathfinderMob, Mob, LivingEntity, Entity }, + descendants { BasePiglin..., Guardian... }, )] pub struct Monster { pub pathfinder_mob: PathfinderMob, } - -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&Monster> { - match self { - AnyEntity::Monster(monster) => return Some(&monster), - _ => (), - } - if let Some(base_piglin) = >::try_as_entity_ref(self) { - return Some(&base_piglin.monster) - } - if let Some(guardian) = >::try_as_entity_ref(self) { - return Some(&guardian.monster) - } - None - } - - fn try_as_entity_mut(&mut self) -> Option<&mut Monster> { - match self { - AnyEntity::Monster(monster) => return Some(monster), - _ => (), - } - if >::try_as_entity_ref(self).is_some() { - return >::try_as_entity_mut(self).map(|piglin| &mut piglin.monster) - } - if >::try_as_entity_ref(self).is_some() { - return >::try_as_entity_mut(self).map(|guardian| &mut guardian.monster) - } - None - } -} - diff --git a/minecraft-entities/src/monsters/piglin.rs b/minecraft-entities/src/monsters/piglin.rs index de05922c..75e9594e 100644 --- a/minecraft-entities/src/monsters/piglin.rs +++ b/minecraft-entities/src/monsters/piglin.rs @@ -2,33 +2,15 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - inheritable, ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, + ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, + descendants { Piglin, PiglinBrute }, )] pub struct BasePiglin { pub monster: Monster, pub is_immune: bool, } -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&BasePiglin> { - match self { - AnyEntity::BasePiglin(base_piglin) => Some(base_piglin), - AnyEntity::Piglin(piglin) => Some(&piglin.base_piglin), - AnyEntity::PiglinBrute(piglin_brute) => Some(&piglin_brute.base_piglin), - _ => None, - } - } - - fn try_as_entity_mut(&mut self) -> Option<&mut BasePiglin> { - match self { - AnyEntity::BasePiglin(base_piglin) => Some(base_piglin), - AnyEntity::Piglin(piglin) => Some(&mut piglin.base_piglin), - AnyEntity::PiglinBrute(piglin_brute) => Some(&mut piglin_brute.base_piglin), - _ => None, - } - } -} - #[derive(Default)] #[MinecraftEntity( ancestors { BasePiglin, Monster, PathfinderMob, Mob, LivingEntity, Entity }, diff --git a/minecraft-entities/src/monsters/raider.rs b/minecraft-entities/src/monsters/raider.rs index f6c87f6e..34e5bffd 100644 --- a/minecraft-entities/src/monsters/raider.rs +++ b/minecraft-entities/src/monsters/raider.rs @@ -2,39 +2,15 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - inheritable, ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, + ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, + descendants { Witch, AbstractIllager... }, )] pub struct Raider { pub monster: Monster, pub is_celebrating: bool, } -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&Raider> { - match self { - AnyEntity::Raider(raider) => return Some(raider), - AnyEntity::Witch(witch) => return Some(&witch.raider), - _ => (), - } - if let Some(abstract_illager) = >::try_as_entity_ref(self) { - return Some(&abstract_illager.raider) - } - None - } - - fn try_as_entity_mut(&mut self) -> Option<&mut Raider> { - match self { - AnyEntity::Raider(raider) => return Some(raider), - AnyEntity::Witch(witch) => return Some(&mut witch.raider), - _ => (), - } - if let Some(abstract_illager) = >::try_as_entity_mut(self) { - return Some(&mut abstract_illager.raider) - } - None - } -} - #[derive(Default)] #[MinecraftEntity( ancestors { Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity }, @@ -46,40 +22,14 @@ pub struct Witch { #[derive(Default)] #[MinecraftEntity( - inheritable, ancestors { Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, + ancestors { Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity }, + descendants { Vindicator, Pillager, SpellcasterIllager... }, )] pub struct AbstractIllager { pub raider: Raider, } -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&AbstractIllager> { - match self { - AnyEntity::AbstractIllager(abstract_illager) => return Some(abstract_illager), - AnyEntity::Vindicator(vindicator) => return Some(&vindicator.abstract_illager), - AnyEntity::Pillager(pillager) => return Some(&pillager.abstract_illager), - _ => (), - } - if let Some(spellcaster_illager) = >::try_as_entity_ref(self) { - return Some(&spellcaster_illager.abstract_illager) - } - None - } - - fn try_as_entity_mut(&mut self) -> Option<&mut AbstractIllager> { - match self { - AnyEntity::AbstractIllager(abstract_illager) => return Some(abstract_illager), - AnyEntity::Vindicator(vindicator) => return Some(&mut vindicator.abstract_illager), - AnyEntity::Pillager(pillager) => return Some(&mut pillager.abstract_illager), - _ => (), - } - if let Some(spellcaster_illager) = >::try_as_entity_mut(self) { - return Some(&mut spellcaster_illager.abstract_illager) - } - None - } -} - #[derive(Default)] #[MinecraftEntity( ancestors { AbstractIllager, Monster, PathfinderMob, Mob, LivingEntity, Entity }, @@ -99,35 +49,15 @@ pub struct Pillager { #[derive(Default)] #[MinecraftEntity( - inheritable, ancestors { AbstractIllager, Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, + ancestors { AbstractIllager, Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity }, + descendants { Illusioner, Ravager, Evoker }, )] pub struct SpellcasterIllager { pub abstract_illager: AbstractIllager, pub spell: u8, } -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&SpellcasterIllager> { - match self { - AnyEntity::SpellcasterIllager(spellcaster_illager) => Some(spellcaster_illager), - AnyEntity::Illusioner(illusioner) => Some(&illusioner.spellcaster_illager), - AnyEntity::Ravager(ravager) => Some(&ravager.spellcaster_illager), - AnyEntity::Evoker(evoker) => Some(&evoker.spellcaster_illager), - _ => None, - } - } - - fn try_as_entity_mut(&mut self) -> Option<&mut SpellcasterIllager> { - match self { - AnyEntity::SpellcasterIllager(spellcaster_illager) => Some(spellcaster_illager), - AnyEntity::Illusioner(illusioner) => Some(&mut illusioner.spellcaster_illager), - AnyEntity::Ravager(ravager) => Some(&mut ravager.spellcaster_illager), - AnyEntity::Evoker(evoker) => Some(&mut evoker.spellcaster_illager), - _ => None, - } - } -} - #[derive(Default)] #[MinecraftEntity( ancestors { SpellcasterIllager, AbstractIllager, Raider, Monster, PathfinderMob, Mob, LivingEntity, Entity }, diff --git a/minecraft-entities/src/monsters/skeleton.rs b/minecraft-entities/src/monsters/skeleton.rs index 4f6c9b63..c5ea250f 100644 --- a/minecraft-entities/src/monsters/skeleton.rs +++ b/minecraft-entities/src/monsters/skeleton.rs @@ -2,34 +2,14 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - inheritable, ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, + ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, + descendants { Skeleton, WitherSkeleton, Stray }, )] pub struct AbstractSkeleton { pub monster: Monster, } -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&AbstractSkeleton> { - match self { - AnyEntity::AbstractSkeleton(abstract_skeleton) => Some(&abstract_skeleton), - AnyEntity::Skeleton(skeleton) => Some(&skeleton.abstract_skeleton), - AnyEntity::WitherSkeleton(wither_skeleton) => Some(&wither_skeleton.abstract_skeleton), - AnyEntity::Stray(stray) => Some(&stray.abstract_skeleton), - _ => None, - } - } - - fn try_as_entity_mut(&mut self) -> Option<&mut AbstractSkeleton> { - match self { - AnyEntity::AbstractSkeleton(abstract_skeleton) => Some(abstract_skeleton), - AnyEntity::Skeleton(skeleton) => Some(&mut skeleton.abstract_skeleton), - AnyEntity::WitherSkeleton(wither_skeleton) => Some(&mut wither_skeleton.abstract_skeleton), - AnyEntity::Stray(stray) => Some(&mut stray.abstract_skeleton), - _ => None, - } - } -} - #[derive(Default)] #[MinecraftEntity( ancestors { AbstractSkeleton, Monster, PathfinderMob, Mob, LivingEntity, Entity }, diff --git a/minecraft-entities/src/monsters/zombies.rs b/minecraft-entities/src/monsters/zombies.rs index 2739d8c1..ff2cd43c 100644 --- a/minecraft-entities/src/monsters/zombies.rs +++ b/minecraft-entities/src/monsters/zombies.rs @@ -2,7 +2,9 @@ use super::*; #[derive(Default)] #[MinecraftEntity( - inheritable, ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, + inheritable, + ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, + descendants { ZombieVillager, Husk, Drowned, ZombifiedPiglin }, )] pub struct Zombie { pub monster: Monster, @@ -11,30 +13,6 @@ pub struct Zombie { pub is_becoming_drowned: bool, } -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&Zombie> { - match self { - AnyEntity::Zombie(zombie) => Some(&zombie), - AnyEntity::ZombieVillager(zombie_villager) => Some(&zombie_villager.zombie), - AnyEntity::Husk(husk) => Some(&husk.zombie), - AnyEntity::Drowned(drowned) => Some(&drowned.zombie), - AnyEntity::ZombifiedPiglin(zombified_piglin) => Some(&zombified_piglin.zombie), - _ => None, - } - } - - fn try_as_entity_mut(&mut self) -> Option<&mut Zombie> { - match self { - AnyEntity::Zombie(zombie) => Some(zombie), - AnyEntity::ZombieVillager(zombie_villager) => Some(&mut zombie_villager.zombie), - AnyEntity::Husk(husk) => Some(&mut husk.zombie), - AnyEntity::Drowned(drowned) => Some(&mut drowned.zombie), - AnyEntity::ZombifiedPiglin(zombified_piglin) => Some(&mut zombified_piglin.zombie), - _ => None, - } - } -} - #[derive(Default)] #[MinecraftEntity( ancestors { Zombie, Monster, PathfinderMob, Mob, LivingEntity, Entity }, diff --git a/minecraft-entities/src/thrown_item_projectile.rs b/minecraft-entities/src/thrown_item_projectile.rs index c1ef51ac..e07e3c8e 100644 --- a/minecraft-entities/src/thrown_item_projectile.rs +++ b/minecraft-entities/src/thrown_item_projectile.rs @@ -1,7 +1,9 @@ use super::*; #[MinecraftEntity( - inheritable, ancestors { Entity }, + inheritable, + ancestors { Entity }, + descendants { ThrownEgg, ThrownEnderPearl, ThrownExperienceBottle, ThrownPotion, Snowball }, )] pub struct ThrownItemProjectile { pub entity: Entity, @@ -17,32 +19,6 @@ impl Default for ThrownItemProjectile { } } -impl TryAsEntityRef for AnyEntity { - fn try_as_entity_ref(&self) -> Option<&ThrownItemProjectile> { - match self { - AnyEntity::ThrownItemProjectile(throwable) => Some(throwable), - AnyEntity::ThrownEgg(egg) => Some(&egg.thrown_item_projectile), - AnyEntity::ThrownEnderPearl(ender_pearl) => Some(&ender_pearl.thrown_item_projectile), - AnyEntity::ThrownExperienceBottle(experience_bottle) => Some(&experience_bottle.thrown_item_projectile), - AnyEntity::ThrownPotion(potion) => Some(&potion.thrown_item_projectile), - AnyEntity::Snowball(snowball) => Some(&snowball.thrown_item_projectile), - _ => None, - } - } - - fn try_as_entity_mut(&mut self) -> Option<&mut ThrownItemProjectile> { - match self { - AnyEntity::ThrownItemProjectile(throwable) => Some(throwable), - AnyEntity::ThrownEgg(egg) => Some(&mut egg.thrown_item_projectile), - AnyEntity::ThrownEnderPearl(ender_pearl) => Some(&mut ender_pearl.thrown_item_projectile), - AnyEntity::ThrownExperienceBottle(experience_bottle) => Some(&mut experience_bottle.thrown_item_projectile), - AnyEntity::ThrownPotion(potion) => Some(&mut potion.thrown_item_projectile), - AnyEntity::Snowball(snowball) => Some(&mut snowball.thrown_item_projectile), - _ => None, - } - } -} - #[MinecraftEntity( ancestors { ThrownItemProjectile, Entity }, )] From 1535c6a1c5f16d8f0dbb29503e57f4d25f0f2dae Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 02:39:39 +0100 Subject: [PATCH 39/89] Remove old code --- minecraft-entities/src/lib.rs | 230 ---------------------------------- 1 file changed, 230 deletions(-) diff --git a/minecraft-entities/src/lib.rs b/minecraft-entities/src/lib.rs index 2c0fe26b..e026f4d6 100644 --- a/minecraft-entities/src/lib.rs +++ b/minecraft-entities/src/lib.rs @@ -227,233 +227,3 @@ pub enum AnyEntity { TropicalFish(TropicalFish), Tadpole(Tadpole), } - -#[allow(clippy::single_match)] -impl AnyEntity { - pub fn as_entity(&self) -> &Entity { - match self { - AnyEntity::Entity(entity) => entity, - AnyEntity::Interaction(interaction) => interaction.get_entity(), - AnyEntity::Display(display) => display.get_entity(), - AnyEntity::BlockDisplay(block_display) => block_display.get_entity(), - AnyEntity::ItemDisplay(item_display) => item_display.get_entity(), - AnyEntity::TextDisplay(text_display) => text_display.get_entity(), - AnyEntity::ThrownItemProjectile(throw_item_projectile) => throw_item_projectile.get_entity(), - AnyEntity::ThrownEgg(throw_egg) => throw_egg.get_entity(), - AnyEntity::ThrownEnderPearl(throw_ender_pearl) => throw_ender_pearl.get_entity(), - AnyEntity::ThrownExperienceBottle(throw_experience_bottle) => throw_experience_bottle.get_entity(), - AnyEntity::ThrownPotion(throw_potion) => throw_potion.get_entity(), - AnyEntity::Snowball(snowball) => snowball.get_entity(), - AnyEntity::AbstractArrow(abstract_arrow) => abstract_arrow.get_entity(), - AnyEntity::Arrow(arrow) => arrow.get_entity(), - AnyEntity::SpectralArrow(spectral_arrow) => spectral_arrow.get_entity(), - AnyEntity::ThrownTrident(throw_trident) => throw_trident.get_entity(), - AnyEntity::Boat(boat) => boat.get_entity(), - AnyEntity::ChestBoat(chest_boat) => chest_boat.get_entity(), - AnyEntity::LivingEntity(living_entity) => living_entity.get_entity(), - AnyEntity::Player(player) => player.get_entity(), - AnyEntity::Mob(mob) => mob.get_entity(), - AnyEntity::AmbientCreature(ambient_creature) => ambient_creature.get_entity(), - AnyEntity::Bat(bat) => bat.get_entity(), - AnyEntity::PathfinderMob(pathfinder_mob) => pathfinder_mob.get_entity(), - AnyEntity::WaterAnimal(water_animal) => water_animal.get_entity(), - AnyEntity::Squid(squid) => squid.get_entity(), - AnyEntity::AgeableMob(ageable_mob) => ageable_mob.get_entity(), - AnyEntity::Animal(animal) => animal.get_entity(), - AnyEntity::Sniffer(sniffer) => sniffer.get_entity(), - AnyEntity::AbstractHorse(abstract_horse) => abstract_horse.get_entity(), - AnyEntity::ZombieHorse(zombie_horse) => zombie_horse.get_entity(), - AnyEntity::Horse(horse) => horse.get_entity(), - AnyEntity::SkeletonHorse(skeleton_horse) => skeleton_horse.get_entity(), - AnyEntity::Camel(camel) => camel.get_entity(), - AnyEntity::ChestedHorse(chested_horse) => chested_horse.get_entity(), - AnyEntity::Donkey(donkey) => donkey.get_entity(), - AnyEntity::Llama(llama) => llama.get_entity(), - AnyEntity::TraderLlama(trader_llama) => trader_llama.get_entity(), - AnyEntity::Mule(mule) => mule.get_entity(), - AnyEntity::Axolotl(axolotl) => axolotl.get_entity(), - AnyEntity::Bee(bee) => bee.get_entity(), - AnyEntity::Fox(fox) => fox.get_entity(), - AnyEntity::Frog(frog) => frog.get_entity(), - AnyEntity::Ocelot(ocelot) => ocelot.get_entity(), - AnyEntity::Panda(panda) => panda.get_entity(), - AnyEntity::Pig(pig) => pig.get_entity(), - AnyEntity::Rabbit(rabbit) => rabbit.get_entity(), - AnyEntity::Turtle(turtle) => turtle.get_entity(), - AnyEntity::PolarBear(polar_bear) => polar_bear.get_entity(), - AnyEntity::Chicken(chicken) => chicken.get_entity(), - AnyEntity::Cow(cow) => cow.get_entity(), - AnyEntity::Hoglin(hoglin) => hoglin.get_entity(), - AnyEntity::Mooshroom(mooshroom) => mooshroom.get_entity(), - AnyEntity::Sheep(sheep) => sheep.get_entity(), - AnyEntity::Strider(strider) => strider.get_entity(), - AnyEntity::TameableAnimal(tameable_animal) => tameable_animal.get_entity(), - AnyEntity::Cat(cat) => cat.get_entity(), - AnyEntity::Wolf(wolf) => wolf.get_entity(), - AnyEntity::Parrot(parrot) => parrot.get_entity(), - AnyEntity::AbstractVillager(abstract_villager) => abstract_villager.get_entity(), - AnyEntity::Villager(villager) => villager.get_entity(), - AnyEntity::WanderingTrader(wandering_trader) => wandering_trader.get_entity(), - AnyEntity::AbstractGolem(abstract_golem) => abstract_golem.get_entity(), - AnyEntity::IronGolem(iron_golem) => iron_golem.get_entity(), - AnyEntity::SnowGolem(snow_golem) => snow_golem.get_entity(), - AnyEntity::Shulker(shulker) => shulker.get_entity(), - AnyEntity::Monster(monster) => monster.get_entity(), - AnyEntity::BasePiglin(base_piglin) => base_piglin.get_entity(), - AnyEntity::Piglin(piglin) => piglin.get_entity(), - AnyEntity::PiglinBrute(piglin_brute) => piglin_brute.get_entity(), - AnyEntity::Blaze(blaze) => blaze.get_entity(), - AnyEntity::Creeper(creeper) => creeper.get_entity(), - AnyEntity::Endermite(endermite) => endermite.get_entity(), - AnyEntity::Giant(giant) => giant.get_entity(), - AnyEntity::Goat(goat) => goat.get_entity(), - AnyEntity::Guardian(guardian) => guardian.get_entity(), - AnyEntity::ElderGuardian(elder_guardian) => elder_guardian.get_entity(), - AnyEntity::Silverfish(silverfish) => silverfish.get_entity(), - AnyEntity::Raider(raider) => raider.get_entity(), - AnyEntity::AbstractIllager(abstract_illager) => abstract_illager.get_entity(), - AnyEntity::Vindicator(vindicator) => vindicator.get_entity(), - AnyEntity::Pillager(pillager) => pillager.get_entity(), - AnyEntity::SpellcasterIllager(spellcaster_illager) => spellcaster_illager.get_entity(), - AnyEntity::Evoker(evoker) => evoker.get_entity(), - AnyEntity::Illusioner(illusioner) => illusioner.get_entity(), - AnyEntity::Ravager(ravager) => ravager.get_entity(), - AnyEntity::Witch(witch) => witch.get_entity(), - AnyEntity::EvokerFangs(evoker_fangs) => evoker_fangs.get_entity(), - AnyEntity::Vex(vex) => vex.get_entity(), - AnyEntity::Skeleton(skeleton) => skeleton.get_entity(), - AnyEntity::AbstractSkeleton(abstract_skeleton) => abstract_skeleton.get_entity(), - AnyEntity::WitherSkeleton(wither_skeleton) => wither_skeleton.get_entity(), - AnyEntity::Stray(stray) => stray.get_entity(), - AnyEntity::Spider(spider) => spider.get_entity(), - AnyEntity::Warden(warden) => warden.get_entity(), - AnyEntity::Wither(wither) => wither.get_entity(), - AnyEntity::Zoglin(zoglin) => zoglin.get_entity(), - AnyEntity::Zombie(zombie) => zombie.get_entity(), - AnyEntity::ZombieVillager(zombie_villager) => zombie_villager.get_entity(), - AnyEntity::Husk(husk) => husk.get_entity(), - AnyEntity::Drowned(drowned) => drowned.get_entity(), - AnyEntity::ZombifiedPiglin(zombified_piglin) => zombified_piglin.get_entity(), - AnyEntity::Enderman(enderman) => enderman.get_entity(), - AnyEntity::EnderDragon(ender_dragon) => ender_dragon.get_entity(), - AnyEntity::Flying(flying) => flying.get_entity(), - AnyEntity::Ghast(ghast) => ghast.get_entity(), - AnyEntity::Phantom(phantom) => phantom.get_entity(), - AnyEntity::Slime(slime) => slime.get_entity(), - AnyEntity::LlamaSpit(llama_spit) => llama_spit.get_entity(), - AnyEntity::EyeOfEnder(eye_of_ender) => eye_of_ender.get_entity(), - AnyEntity::FallingBlock(falling_block) => falling_block.get_entity(), - AnyEntity::AreaEffectCloud(area_effect_cloud) => area_effect_cloud.get_entity(), - AnyEntity::FishingHook(fishing_hook) => fishing_hook.get_entity(), - AnyEntity::EndCrystal(end_crystal) => end_crystal.get_entity(), - AnyEntity::DragonFireball(dragon_fireball) => dragon_fireball.get_entity(), - AnyEntity::SmallFireball(small_fireball) => small_fireball.get_entity(), - AnyEntity::Fireball(fireball) => fireball.get_entity(), - AnyEntity::WitherSkull(wither_skull) => wither_skull.get_entity(), - AnyEntity::FireworkRocket(firework_rocket) => firework_rocket.get_entity(), - AnyEntity::ItemFrame(item_frame) => item_frame.get_entity(), - AnyEntity::GlowingItemFrame(glowing_item_frame) => glowing_item_frame.get_entity(), - AnyEntity::Painting(painting) => painting.get_entity(), - AnyEntity::ItemEntity(item_entity) => item_entity.get_entity(), - AnyEntity::ArmorStand(armor_stand) => armor_stand.get_entity(), - AnyEntity::Dolphin(dolphin) => dolphin.get_entity(), - AnyEntity::AbstractFish(abstract_fish) => abstract_fish.get_entity(), - AnyEntity::Cod(cod) => cod.get_entity(), - AnyEntity::PufferFish(pufferfish) => pufferfish.get_entity(), - AnyEntity::Salmon(salmon) => salmon.get_entity(), - AnyEntity::TropicalFish(tropical_fish) => tropical_fish.get_entity(), - AnyEntity::Tadpole(tadpole) => tadpole.get_entity(), - } - } - - pub fn as_display(&self) -> Option<&Display> { - match self { - AnyEntity::Display(display) => Some(display), - AnyEntity::BlockDisplay(block_display) => Some(&block_display.display), - AnyEntity::ItemDisplay(item_display) => Some(&item_display.display), - AnyEntity::TextDisplay(text_display) => Some(&text_display.display), - _ => None, - } - } - - pub fn as_thrown_item_projectile(&self) -> Option<&ThrownItemProjectile> { - match self { - AnyEntity::ThrownItemProjectile(throw_item_projectile) => Some(throw_item_projectile), - AnyEntity::ThrownEgg(throw_egg) => Some(&throw_egg.thrown_item_projectile), - AnyEntity::ThrownEnderPearl(throw_ender_pearl) => Some(&throw_ender_pearl.thrown_item_projectile), - AnyEntity::ThrownExperienceBottle(throw_experience_bottle) => Some(&throw_experience_bottle.thrown_item_projectile), - AnyEntity::ThrownPotion(throw_potion) => Some(&throw_potion.thrown_item_projectile), - AnyEntity::Snowball(snowball) => Some(&snowball.thrown_item_projectile), - _ => None, - } - } - - pub fn as_abstract_arrow(&self) -> Option<&AbstractArrow> { - match self { - AnyEntity::AbstractArrow(abstract_arrow) => Some(abstract_arrow), - AnyEntity::Arrow(arrow) => Some(&arrow.abstract_arrow), - AnyEntity::SpectralArrow(spectral_arrow) => Some(&spectral_arrow.abstract_arrow), - AnyEntity::ThrownTrident(throw_trident) => Some(&throw_trident.abstract_arrow), - _ => None, - } - } - - pub fn as_boat(&self) -> Option<&Boat> { - match self { - AnyEntity::Boat(boat) => Some(boat), - AnyEntity::ChestBoat(chest_boat) => Some(&chest_boat.boat), - _ => None, - } - } - - pub fn as_living_entity(&self) -> Option<&LivingEntity> { - match self { - AnyEntity::LivingEntity(living_entity) => return Some(living_entity), - AnyEntity::Player(player) => return Some(&player.living_entity), - _ => (), - }; - if let Some(mob) = self.as_mob() { - return Some(&mob.living_entity); - } - None - } - - pub fn as_mob(&self) -> Option<&Mob> { - match self { - AnyEntity::Mob(mob) => return Some(mob), - AnyEntity::PathfinderMob(pathfinder_mob) => return Some(&pathfinder_mob.mob), - _ => (), - }; - if let Some(ambient_creature) = self.as_ambient_creature() { - return Some(&ambient_creature.mob); - } - None - } - - pub fn as_ambient_creature(&self) -> Option<&AmbientCreature> { - match self { - AnyEntity::AmbientCreature(ambient_creature) => Some(ambient_creature), - AnyEntity::Bat(bat) => Some(&bat.ambient_creature), - _ => None, - } - } - - pub fn as_pathfinder_mob(&self) -> Option<&PathfinderMob> { - match self { - AnyEntity::PathfinderMob(pathfinder_mob) => return Some(pathfinder_mob), - _ => (), - } - if let Some(water_animal) = self.as_water_animal() { - return Some(&water_animal.pathfinder_mob); - } - None - } - - pub fn as_water_animal(&self) -> Option<&WaterAnimal> { - match self { - AnyEntity::WaterAnimal(water_animal) => Some(water_animal), - AnyEntity::Squid(squid) => Some(&squid.water_animal), - _ => None, - } - } -} From 7d93051826eb5be96f6fe15151dff323d010eb89 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 03:09:46 +0100 Subject: [PATCH 40/89] Add tests --- minecraft-entities-derive/examples/main.rs | 9 +++++++-- minecraft-entities-derive/src/lib.rs | 20 +++++++++++++++++--- minecraft-entities/src/monsters/enderman.rs | 1 + minecraft-entities/src/monsters/spider.rs | 1 + minecraft-entities/src/monsters/wither.rs | 1 + 5 files changed, 27 insertions(+), 5 deletions(-) diff --git a/minecraft-entities-derive/examples/main.rs b/minecraft-entities-derive/examples/main.rs index 3b874bea..b87426f4 100644 --- a/minecraft-entities-derive/examples/main.rs +++ b/minecraft-entities-derive/examples/main.rs @@ -49,9 +49,9 @@ impl Handler { // Entity #[MinecraftEntity( + inheritable, ancestors { }, descendants { Animal... }, - inheritable, defines { on_moved(self, from: f32, to: f32); on_spawned(self); @@ -74,9 +74,9 @@ impl Handler { // Animal #[MinecraftEntity( + inheritable, ancestors { Entity }, descendants { Cow }, - inheritable, defines { Entity.on_spawned(self); on_hit(self, damage: usize); @@ -131,3 +131,8 @@ impl Handler { fn main() { } + +#[test] +fn test() { + +} diff --git a/minecraft-entities-derive/src/lib.rs b/minecraft-entities-derive/src/lib.rs index d7444d6d..bcc5130d 100644 --- a/minecraft-entities-derive/src/lib.rs +++ b/minecraft-entities-derive/src/lib.rs @@ -95,9 +95,9 @@ pub fn MinecraftEntity(attr: proc_macro::TokenStream, item: proc_macro::TokenStr if !matches!(group_attrs.next(), Some(TokenTree::Punct(punct)) if punct.as_char() == '.') { abort!(dot.span(), "this dot needs to come with two other dots"); } - descendants.push(ident); - } else { wildcard_descendants.push(ident); + } else { + descendants.push(ident); } if matches!(group_attrs.peek(), Some(TokenTree::Punct(punct)) if punct.as_char() == ',') { group_attrs.next(); @@ -163,6 +163,7 @@ pub fn MinecraftEntity(attr: proc_macro::TokenStream, item: proc_macro::TokenStr let mut to_replace = HashMap::new(); let this = struct_name.clone(); let this_snake = Ident::new(&struct_name.to_string().to_case(Case::Snake), struct_name.span()); + let this_test = Ident::new(&format!("test_entity_{}", struct_name.to_string().to_case(Case::Snake)), struct_name.span()); to_replace.insert("This", this.clone()); to_replace.insert("ThisDescendant", Ident::new(&format!("{}Descendant", struct_name), struct_name.span())); to_replace.insert("ThisMethods", Ident::new(&format!("{}Methods", struct_name), struct_name.span())); @@ -173,6 +174,7 @@ pub fn MinecraftEntity(attr: proc_macro::TokenStream, item: proc_macro::TokenStr if !ancestors.is_empty() { // Generate code for parent let parent = ancestors.remove(0); + let parent_snake = Ident::new(&parent.to_string().to_case(Case::Snake), parent.span()); let code: TokenStream = r#" #[automatically_derived] impl ParentDescendant for This { @@ -192,6 +194,18 @@ pub fn MinecraftEntity(attr: proc_macro::TokenStream, item: proc_macro::TokenStr let code: TokenStream = code.into_iter().collect(); println!("{}", code); codes.push(code); + + let code = quote! { + #[cfg(test)] + #[automatically_derived] + #[test] + fn #this_test() { + let #this_snake: AnyEntity = AnyEntity::#this(<#this as std::default::Default>::default()); + let #parent_snake: Option<&#parent> = #this_snake.try_as_entity_ref(); + assert!(#parent_snake.is_some(), "Please add {} to {} list", stringify!(#this), stringify!(#parent)); + } + }; + codes.push(code); } // Generate code for higher inheritance levels @@ -202,7 +216,7 @@ pub fn MinecraftEntity(attr: proc_macro::TokenStream, item: proc_macro::TokenStr fn get_inherited_mut(&mut self) -> &mut Inherited { self.parent.get_inherited_mut() } } "#.parse().unwrap(); - for inherited in ancestors { + for inherited in &ancestors { to_replace.insert("InheritedDescendant", Ident::new(&format!("{}Descendant", inherited), inherited.span())); to_replace.insert("Inherited", inherited.clone()); to_replace.insert("get_inherited", Ident::new(&format!("get_{}", inherited.to_string().to_case(Case::Snake)), inherited.span())); diff --git a/minecraft-entities/src/monsters/enderman.rs b/minecraft-entities/src/monsters/enderman.rs index cc244ac9..e0e2d109 100644 --- a/minecraft-entities/src/monsters/enderman.rs +++ b/minecraft-entities/src/monsters/enderman.rs @@ -2,6 +2,7 @@ use minecraft_protocol::ids::blocks::Block; use super::*; +#[derive(Default)] #[MinecraftEntity( ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] diff --git a/minecraft-entities/src/monsters/spider.rs b/minecraft-entities/src/monsters/spider.rs index f076cfd7..d62fc4d7 100644 --- a/minecraft-entities/src/monsters/spider.rs +++ b/minecraft-entities/src/monsters/spider.rs @@ -1,5 +1,6 @@ use super::*; +#[derive(Default)] #[MinecraftEntity( ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] diff --git a/minecraft-entities/src/monsters/wither.rs b/minecraft-entities/src/monsters/wither.rs index 5da7fa2f..0edc9c8c 100644 --- a/minecraft-entities/src/monsters/wither.rs +++ b/minecraft-entities/src/monsters/wither.rs @@ -1,5 +1,6 @@ use super::*; +#[derive(Default)] #[MinecraftEntity( ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, )] From be6993303750b4dfdb173a18856cc58d18cecfeb Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 03:25:02 +0100 Subject: [PATCH 41/89] Make tests pass --- minecraft-entities/src/animals/mod.rs | 4 ++-- minecraft-entities/src/entity.rs | 2 +- minecraft-entities/src/fire_entities.rs | 2 +- minecraft-entities/src/mobs/golems.rs | 2 +- minecraft-entities/src/mobs/mod.rs | 6 +++--- minecraft-entities/src/monsters/mod.rs | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/minecraft-entities/src/animals/mod.rs b/minecraft-entities/src/animals/mod.rs index ae316075..8576968c 100644 --- a/minecraft-entities/src/animals/mod.rs +++ b/minecraft-entities/src/animals/mod.rs @@ -49,7 +49,7 @@ pub use water_animal::*; #[MinecraftEntity( inheritable, ancestors { AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, - descendants { TameableAnimal... }, + descendants { Axolotl, Bee, Chicken, Cow, Fox, Frog, Goat, Hoglin, Ocelot, Panda, Pig, PolarBear, Rabbit, Sheep, Sniffer, Strider, Turtle, AbstractHorse..., TameableAnimal... }, )] pub struct Animal { pub ageable_mob: AgeableMob, @@ -59,7 +59,7 @@ pub struct Animal { #[MinecraftEntity( inheritable, ancestors { Animal, AgeableMob, PathfinderMob, Mob, LivingEntity, Entity }, - descendants { } + descendants { Cat, Parrot, Wolf } )] pub struct TameableAnimal { pub animal: Animal, diff --git a/minecraft-entities/src/entity.rs b/minecraft-entities/src/entity.rs index 29f47726..20644851 100644 --- a/minecraft-entities/src/entity.rs +++ b/minecraft-entities/src/entity.rs @@ -2,7 +2,7 @@ use super::*; #[MinecraftEntity( inheritable, - descendants { }, + descendants { AbstractArrow..., Boat..., Display, FallingBlock, LlamaSpit, Painting, DragonFireball, Fireball..., FireworkRocket, SmallFireball, Interaction..., ItemEntity, ItemFrame..., LivingEntity... EndCrystal, EvokerFangs, WitherSkull, AreaEffectCloud, FishingHook, EyeOfEnder, ThrownItemProjectile... }, )] pub struct Entity { pub position: Position, diff --git a/minecraft-entities/src/fire_entities.rs b/minecraft-entities/src/fire_entities.rs index 0b8d8265..4342a970 100644 --- a/minecraft-entities/src/fire_entities.rs +++ b/minecraft-entities/src/fire_entities.rs @@ -19,7 +19,7 @@ pub struct SmallFireball { #[derive(Default)] #[MinecraftEntity( - ancestors { Entity }, + ancestors { Entity }, )] pub struct Fireball { pub entity: Entity, diff --git a/minecraft-entities/src/mobs/golems.rs b/minecraft-entities/src/mobs/golems.rs index f5971d69..fa283721 100644 --- a/minecraft-entities/src/mobs/golems.rs +++ b/minecraft-entities/src/mobs/golems.rs @@ -4,7 +4,7 @@ use super::*; #[MinecraftEntity( inheritable, ancestors { PathfinderMob, Mob, LivingEntity, Entity }, - descendants { IronGolem, SnowGolem }, + descendants { IronGolem, SnowGolem, Shulker }, )] pub struct AbstractGolem { pub pathfinder_mob: PathfinderMob, diff --git a/minecraft-entities/src/mobs/mod.rs b/minecraft-entities/src/mobs/mod.rs index aa25494a..e350db03 100644 --- a/minecraft-entities/src/mobs/mod.rs +++ b/minecraft-entities/src/mobs/mod.rs @@ -17,7 +17,7 @@ pub use bat::*; #[MinecraftEntity( inheritable, ancestors { LivingEntity, Entity }, - descendants { AmbientCreature..., PathfinderMob... }, + descendants { AmbientCreature..., PathfinderMob..., EnderDragon, Flying..., Slime }, )] pub struct Mob { pub living_entity: LivingEntity, @@ -40,7 +40,7 @@ pub struct AmbientCreature { #[MinecraftEntity( inheritable, ancestors { Mob, LivingEntity, Entity }, - descendants { AgeableMob... }, + descendants { WaterAnimal..., AgeableMob..., Monster..., AbstractGolem... }, )] pub struct PathfinderMob { pub mob: Mob, @@ -50,7 +50,7 @@ pub struct PathfinderMob { #[MinecraftEntity( inheritable, ancestors { PathfinderMob, Mob, LivingEntity, Entity }, - descendants { AbstractVillager... }, + descendants { Animal..., AbstractVillager... }, )] pub struct AgeableMob { pub pathfinder_mob: PathfinderMob, diff --git a/minecraft-entities/src/monsters/mod.rs b/minecraft-entities/src/monsters/mod.rs index 042dfc84..487ccff8 100644 --- a/minecraft-entities/src/monsters/mod.rs +++ b/minecraft-entities/src/monsters/mod.rs @@ -37,7 +37,7 @@ pub use enderman::*; #[MinecraftEntity( inheritable, ancestors { PathfinderMob, Mob, LivingEntity, Entity }, - descendants { BasePiglin..., Guardian... }, + descendants { Blaze, Creeper, Enderman, Endermite, Giant, Raider, Silverfish, Spider, Vex, Warden, Wither, Zoglin, Zombie, AbstractSkeleton...,BasePiglin..., Guardian... }, )] pub struct Monster { pub pathfinder_mob: PathfinderMob, From 7d05ad6a420b627f0ee8d5b85bf1daf6df11f0a2 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 03:27:23 +0100 Subject: [PATCH 42/89] Fix compiling --- minecraft-entities/src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/minecraft-entities/src/lib.rs b/minecraft-entities/src/lib.rs index e026f4d6..886307a4 100644 --- a/minecraft-entities/src/lib.rs +++ b/minecraft-entities/src/lib.rs @@ -227,3 +227,9 @@ pub enum AnyEntity { TropicalFish(TropicalFish), Tadpole(Tadpole), } + +impl AnyEntity { + pub fn as_entity(&self) -> &Entity { + self.try_as_entity_ref().unwrap() + } +} From 65d605d183a5eddb09a21175ebd48e03a0098245 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 03:27:47 +0100 Subject: [PATCH 43/89] Remove println --- minecraft-entities-derive/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/minecraft-entities-derive/src/lib.rs b/minecraft-entities-derive/src/lib.rs index bcc5130d..ddbca58c 100644 --- a/minecraft-entities-derive/src/lib.rs +++ b/minecraft-entities-derive/src/lib.rs @@ -192,7 +192,6 @@ pub fn MinecraftEntity(attr: proc_macro::TokenStream, item: proc_macro::TokenStr replace_idents(element, &to_replace); } let code: TokenStream = code.into_iter().collect(); - println!("{}", code); codes.push(code); let code = quote! { From 28f0468a5e3d592949c7f7079eaf6e9222693355 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 14:59:15 +0100 Subject: [PATCH 44/89] Add mutate and observe --- minecraft-entities/src/lib.rs | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/minecraft-entities/src/lib.rs b/minecraft-entities/src/lib.rs index 886307a4..030fbd53 100644 --- a/minecraft-entities/src/lib.rs +++ b/minecraft-entities/src/lib.rs @@ -58,13 +58,14 @@ pub trait TryAsEntityRef { fn try_as_entity_mut(&mut self) -> Option<&mut T>; } + pub trait WorldTest { - fn observe_entity(&self, eid: Eid, observer: fn(&AnyEntity)) -> dyn std::future::Future; - fn mutate_entity(&self, eid: Eid, mutator: fn(&mut AnyEntity)) -> dyn std::future::Future; + fn observe_entity(&self, eid: Eid, observer: &dyn FnOnce(&AnyEntity)) -> Pin>>; + fn mutate_entity(&self, eid: Eid, mutator: &dyn FnOnce(&mut AnyEntity)) -> Pin>>; } pub struct Handler where AnyEntity: TryAsEntityRef { - id: Eid, + eid: Eid, world: &'static dyn WorldTest, entity: std::marker::PhantomData, } @@ -72,7 +73,7 @@ pub struct Handler where AnyEntity: TryAsEntityRef { impl Handler where AnyEntity: TryAsEntityRef { pub fn assume(id: Eid, world: &'static dyn WorldTest) -> Self { Self { - id, + eid: id, world, entity: std::marker::PhantomData, } @@ -80,17 +81,22 @@ impl Handler where AnyEntity: TryAsEntityRef { fn assume_other(self) -> Handler where AnyEntity: TryAsEntityRef { Handler { - id: self.id, + eid: self.eid, world: self.world, entity: std::marker::PhantomData, } } pub async fn observe(&self, observer: fn(&T)) { - //let fut = self.world.observe_entity(self.id, |entity| { - // - //}); - //fut.await; + self.world.observe_entity(self.eid, &|entity| { + observer(entity.try_as_entity_ref().unwrap()) + }).await; + } + + pub async fn mutate(&self, mutator: fn(&mut T)) { + self.world.mutate_entity(self.eid, &|entity| { + mutator(entity.try_as_entity_mut().unwrap()) + }).await; } } From 4e2ab8bda3abb7b70039a73e8452b060c7e04c0b Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 15:03:08 +0100 Subject: [PATCH 45/89] Fix warnings --- minecraft-entities-derive/src/lib.rs | 16 ++++++++-------- minecraft-entities/src/lib.rs | 10 ++++++++-- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/minecraft-entities-derive/src/lib.rs b/minecraft-entities-derive/src/lib.rs index ddbca58c..c14f078d 100644 --- a/minecraft-entities-derive/src/lib.rs +++ b/minecraft-entities-derive/src/lib.rs @@ -41,11 +41,11 @@ pub fn MinecraftEntity(attr: proc_macro::TokenStream, item: proc_macro::TokenStr // Get struct name let mut items = item.clone().into_iter(); match items.next() { - Some(TokenTree::Ident(ident)) if ident.to_string() == "pub" => (), + Some(TokenTree::Ident(ident)) if ident == "pub" => (), Some(TokenTree::Punct(punct)) if punct.as_char() == '#' => { items.next(); match items.next() { - Some(TokenTree::Ident(ident)) if ident.to_string() == "pub" => (), + Some(TokenTree::Ident(ident)) if ident == "pub" => (), Some(other) => abort!(other.span(), "expected struct to be public"), None => panic!("expected public struct, found nothing"), } @@ -54,7 +54,7 @@ pub fn MinecraftEntity(attr: proc_macro::TokenStream, item: proc_macro::TokenStr None => panic!("expected public struct, found nothing"), } match items.next() { - Some(TokenTree::Ident(ident)) if ident.to_string() == "struct" => (), + Some(TokenTree::Ident(ident)) if ident == "struct" => (), Some(other) => abort!(other.span(), "expected struct, found {:?}"), None => panic!("expected struct, found nothing"), } @@ -124,7 +124,7 @@ pub fn MinecraftEntity(attr: proc_macro::TokenStream, item: proc_macro::TokenStr abort!(params.span(), "expected parenthesis"); } let mut params = params.stream().into_iter().peekable(); - if matches!(params.peek(), Some(TokenTree::Ident(ident)) if ident.to_string() == "self") { + if matches!(params.peek(), Some(TokenTree::Ident(ident)) if ident == "self") { params.next(); if matches!(params.peek(), Some(TokenTree::Punct(punct)) if punct.as_char() == ',') { params.next(); @@ -264,7 +264,7 @@ pub fn MinecraftEntity(attr: proc_macro::TokenStream, item: proc_macro::TokenStr replace_idents(element, &to_replace); } let mut inner_codes = TokenStream::new(); - for (_, method, args) in defines.iter().filter(|(ty, _, _)| ty.to_string() == struct_name.to_string()) { + for (_, method, args) in defines.iter().filter(|(ty, _, _)| ty == &struct_name) { let inner_code: TokenStream = match args.len() { 0 => String::from(r#" fn method(self) -> Pin>> {{ @@ -318,7 +318,7 @@ pub fn MinecraftEntity(attr: proc_macro::TokenStream, item: proc_macro::TokenStr replace_idents(element, &to_replace); } let mut inner_codes = TokenStream::new(); - for (_, method, args) in defines.iter().filter(|(ty, _, _)| ty.to_string() == struct_name.to_string()) { + for (_, method, args) in defines.iter().filter(|(ty, _, _)| ty == &struct_name) { let inner_code: TokenStream = match args.len() { 0 => String::from(r#"pub method: CallBack>,"#), 1 => format!(r#"pub method: CallBack1, {}>,"#, args[0].1), @@ -356,7 +356,7 @@ pub fn MinecraftEntity(attr: proc_macro::TokenStream, item: proc_macro::TokenStr replace_idents(element, &to_replace); } let mut inner_codes = TokenStream::new(); - for (_, method, args) in defines.iter().filter(|(ty, _, _)| ty.to_string() == ascendant.to_string()) { + for (_, method, args) in defines.iter().filter(|(ty, _, _)| ty == ascendant) { let inner_code: TokenStream = match args.len() { 0 => r#"method: |s| Box::pin(s.assume_other::().method()),"#, 1 => r#"method: |s, arg1| Box::pin(s.assume_other::().method(arg1)),"#, @@ -380,7 +380,7 @@ pub fn MinecraftEntity(attr: proc_macro::TokenStream, item: proc_macro::TokenStr let TokenTree::Group(ref mut group) = code.get_mut(i).unwrap() else {unreachable!()}; *group = Group::new(group.delimiter(), group.stream().into_iter().chain(inner_codes.into_iter()).collect()); - if ascendant.to_string() != struct_name.to_string() { + if ascendant != &struct_name { let inner_code: TokenStream = r#"..*ASCENDANT_METHODS_FOR_PARENT"#.parse().unwrap(); to_replace.insert("ASCENDANT_METHODS_FOR_PARENT", Ident::new(&format!("{}_METHODS_FOR_{}", ascendant.to_string().to_case(Case::ScreamingSnake), hierarchy[1].to_string().to_case(Case::ScreamingSnake)), ascendant.span())); let mut inner_code = inner_code.clone().into_iter().collect::>(); diff --git a/minecraft-entities/src/lib.rs b/minecraft-entities/src/lib.rs index 030fbd53..b3feca10 100644 --- a/minecraft-entities/src/lib.rs +++ b/minecraft-entities/src/lib.rs @@ -44,14 +44,20 @@ pub(crate) use minecraft_protocol::{ nbt::NbtTag, packets::UUID }; +use std::{pin::Pin, future::Future}; pub type Eid = u32; - -use std::{pin::Pin, future::Future, sync::{Mutex, Arc}}; +#[allow(dead_code)] type CallBack = fn(O) -> Pin>>; +#[allow(dead_code)] type CallBack1 = fn(O, I) -> Pin>>; +#[allow(dead_code)] type CallBack2 = fn(O, I, J) -> Pin>>; +#[allow(dead_code)] +type CallBack3 = fn(O, I, J) -> Pin>>; +#[allow(dead_code)] +type CallBack4 = fn(O, I, J) -> Pin>>; pub trait TryAsEntityRef { fn try_as_entity_ref(&self) -> Option<&T>; From 1dcc179dc949a97744a3d1991041a6a467860089 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 15:09:35 +0100 Subject: [PATCH 46/89] Impl EntityWorldInterface on World --- minecraft-entities/src/lib.rs | 6 +++--- minecraft-server/src/ecs.rs | 10 ++++++++++ minecraft-server/src/player_handler/connect.rs | 6 +++--- minecraft-server/src/player_handler/handshake.rs | 2 +- minecraft-server/src/player_handler/play.rs | 4 ++-- minecraft-server/src/server_behavior.rs | 6 +++--- 6 files changed, 22 insertions(+), 12 deletions(-) diff --git a/minecraft-entities/src/lib.rs b/minecraft-entities/src/lib.rs index b3feca10..30a92ec6 100644 --- a/minecraft-entities/src/lib.rs +++ b/minecraft-entities/src/lib.rs @@ -65,19 +65,19 @@ pub trait TryAsEntityRef { } -pub trait WorldTest { +pub trait EntityWorldInterface { fn observe_entity(&self, eid: Eid, observer: &dyn FnOnce(&AnyEntity)) -> Pin>>; fn mutate_entity(&self, eid: Eid, mutator: &dyn FnOnce(&mut AnyEntity)) -> Pin>>; } pub struct Handler where AnyEntity: TryAsEntityRef { eid: Eid, - world: &'static dyn WorldTest, + world: &'static dyn EntityWorldInterface, entity: std::marker::PhantomData, } impl Handler where AnyEntity: TryAsEntityRef { - pub fn assume(id: Eid, world: &'static dyn WorldTest) -> Self { + pub fn assume(id: Eid, world: &'static dyn EntityWorldInterface) -> Self { Self { eid: id, world, diff --git a/minecraft-server/src/ecs.rs b/minecraft-server/src/ecs.rs index b0d1c482..a10bb5d3 100644 --- a/minecraft-server/src/ecs.rs +++ b/minecraft-server/src/ecs.rs @@ -53,3 +53,13 @@ impl Entities { self.entities.write().await.remove(&eid) } } + +impl EntityWorldInterface for World { + fn observe_entity(&self, eid: Eid, observer: &dyn FnOnce(&AnyEntity)) -> Pin>> { + todo!() + } + + fn mutate_entity(&self, eid: Eid, mutator: &dyn FnOnce(&mut AnyEntity)) -> Pin>> { + todo!() + } +} diff --git a/minecraft-server/src/player_handler/connect.rs b/minecraft-server/src/player_handler/connect.rs index cdf4b170..84d99f66 100644 --- a/minecraft-server/src/player_handler/connect.rs +++ b/minecraft-server/src/player_handler/connect.rs @@ -4,7 +4,7 @@ pub async fn handle_connection( mut stream: TcpStream, addr: SocketAddr, server_msg_rcvr: BroadcastReceiver, - world: Arc, + world: &'static World, ) -> Result<(), ()> { // Receive handshake let packet = receive_packet(&mut stream).await?; @@ -12,9 +12,9 @@ pub async fn handle_connection( match next_state { ConnectionState::Login => { let player_info = login(&mut stream, addr).await?; - let (player_info, change_receiver) = handshake(&mut stream, player_info, Arc::clone(&world)).await?; + let (player_info, change_receiver) = handshake(&mut stream, player_info, world).await?; let uuid = player_info.uuid; - let r = handle_player(stream, player_info, server_msg_rcvr, Arc::clone(&world), change_receiver).await; + let r = handle_player(stream, player_info, server_msg_rcvr, world, change_receiver).await; world.remove_loader(uuid).await; r }, diff --git a/minecraft-server/src/player_handler/handshake.rs b/minecraft-server/src/player_handler/handshake.rs index 086869a6..442ebe93 100644 --- a/minecraft-server/src/player_handler/handshake.rs +++ b/minecraft-server/src/player_handler/handshake.rs @@ -14,7 +14,7 @@ pub struct PlayerInfo { pub(super) allow_server_listing: bool, } -pub async fn handshake(stream: &mut TcpStream, logged_in_player_info: LoggedInPlayerInfo, world: Arc) -> Result<(PlayerInfo, MpscReceiver), ()> { +pub async fn handshake(stream: &mut TcpStream, logged_in_player_info: LoggedInPlayerInfo, world: &'static World) -> Result<(PlayerInfo, MpscReceiver), ()> { // Receive client informations let packet = receive_packet(stream).await?; debug!("Packet received"); diff --git a/minecraft-server/src/player_handler/play.rs b/minecraft-server/src/player_handler/play.rs index 52b5bf74..25141213 100644 --- a/minecraft-server/src/player_handler/play.rs +++ b/minecraft-server/src/player_handler/play.rs @@ -1,7 +1,7 @@ use super::*; struct PlayerHandler { - world: Arc, + world: &'static World, game_mode: Gamemode, info: PlayerInfo, position: Position, @@ -155,7 +155,7 @@ impl PlayerHandler { } } -pub async fn handle_player(stream: TcpStream, player_info: PlayerInfo, mut server_msg_rcvr: BroadcastReceiver, world: Arc, mut change_receiver: MpscReceiver) -> Result<(), ()> { +pub async fn handle_player(stream: TcpStream, player_info: PlayerInfo, mut server_msg_rcvr: BroadcastReceiver, world: &'static World, mut change_receiver: MpscReceiver) -> Result<(), ()> { let (packet_sender, mut packet_receiver) = mpsc_channel(100); let mut handler = PlayerHandler { diff --git a/minecraft-server/src/server_behavior.rs b/minecraft-server/src/server_behavior.rs index 7072b4e0..38e37d63 100644 --- a/minecraft-server/src/server_behavior.rs +++ b/minecraft-server/src/server_behavior.rs @@ -10,7 +10,7 @@ pub enum ServerMessage { } pub struct ServerBehavior { - world: Arc, + world: &'static World, player_handlers: Vec, listener: TcpListener, message_receiver: BroadcastReceiver, @@ -31,7 +31,7 @@ impl ServerBehavior { }); ServerBehavior { - world: Arc::new(World::new()), + world: Box::leak(Box::new(World::new())), listener, player_handlers: Vec::new(), message_receiver: receiver, @@ -49,7 +49,7 @@ impl ServerBehavior { } else { debug!("Accepted connection from: {addr}"); let server_msg_rcvr = self.message_receiver.resubscribe(); - self.player_handlers.push(Box::pin(handle_connection(stream, addr, server_msg_rcvr, Arc::clone(&self.world)))); + self.player_handlers.push(Box::pin(handle_connection(stream, addr, server_msg_rcvr, self.world))); } } Ready(Err(e)) => error!("Failed to accept connection: {e}"), From 154dbbe0e8f26dc8842b2eaf47e0a38d117eba72 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 17:31:26 +0100 Subject: [PATCH 47/89] Finish observe and mutate --- minecraft-entities/src/lib.rs | 18 +++++++++--------- minecraft-server/src/ecs.rs | 10 ---------- minecraft-server/src/world/mod.rs | 14 ++++++++++++++ 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/minecraft-entities/src/lib.rs b/minecraft-entities/src/lib.rs index 30a92ec6..70ca8449 100644 --- a/minecraft-entities/src/lib.rs +++ b/minecraft-entities/src/lib.rs @@ -66,8 +66,8 @@ pub trait TryAsEntityRef { pub trait EntityWorldInterface { - fn observe_entity(&self, eid: Eid, observer: &dyn FnOnce(&AnyEntity)) -> Pin>>; - fn mutate_entity(&self, eid: Eid, mutator: &dyn FnOnce(&mut AnyEntity)) -> Pin>>; + fn observe_entity(&'static self, eid: Eid, observer: Box) -> Pin>>; + fn mutate_entity(&'static self, eid: Eid, mutator: Box) -> Pin>>; } pub struct Handler where AnyEntity: TryAsEntityRef { @@ -76,7 +76,7 @@ pub struct Handler where AnyEntity: TryAsEntityRef { entity: std::marker::PhantomData, } -impl Handler where AnyEntity: TryAsEntityRef { +impl Handler where AnyEntity: TryAsEntityRef { pub fn assume(id: Eid, world: &'static dyn EntityWorldInterface) -> Self { Self { eid: id, @@ -93,16 +93,16 @@ impl Handler where AnyEntity: TryAsEntityRef { } } - pub async fn observe(&self, observer: fn(&T)) { - self.world.observe_entity(self.eid, &|entity| { + pub async fn observe(&self, observer: impl FnOnce(&T) + 'static) { + self.world.observe_entity(self.eid, Box::new(move |entity| { observer(entity.try_as_entity_ref().unwrap()) - }).await; + })).await; } - pub async fn mutate(&self, mutator: fn(&mut T)) { - self.world.mutate_entity(self.eid, &|entity| { + pub async fn mutate(&self, mutator: impl FnOnce(&mut T) + 'static) { + self.world.mutate_entity(self.eid, Box::new(move |entity| { mutator(entity.try_as_entity_mut().unwrap()) - }).await; + })).await; } } diff --git a/minecraft-server/src/ecs.rs b/minecraft-server/src/ecs.rs index a10bb5d3..b0d1c482 100644 --- a/minecraft-server/src/ecs.rs +++ b/minecraft-server/src/ecs.rs @@ -53,13 +53,3 @@ impl Entities { self.entities.write().await.remove(&eid) } } - -impl EntityWorldInterface for World { - fn observe_entity(&self, eid: Eid, observer: &dyn FnOnce(&AnyEntity)) -> Pin>> { - todo!() - } - - fn mutate_entity(&self, eid: Eid, mutator: &dyn FnOnce(&mut AnyEntity)) -> Pin>> { - todo!() - } -} diff --git a/minecraft-server/src/world/mod.rs b/minecraft-server/src/world/mod.rs index 687c8b99..fdd33644 100644 --- a/minecraft-server/src/world/mod.rs +++ b/minecraft-server/src/world/mod.rs @@ -79,6 +79,20 @@ impl World { } } +impl EntityWorldInterface for World { + fn observe_entity(&'static self, eid: Eid, observer: Box) -> Pin>> { + Box::pin(async move { + self.entities.observe_entity(eid, observer).await; + }) + } + + fn mutate_entity(&'static self, eid: Eid, mutator: Box) -> Pin>> { + Box::pin(async move { + self.entities.mutate_entity(eid, mutator).await; + }) + } +} + #[cfg(test)] mod tests { use super::*; From 17227a76829e09bd95e1f98f211e0e06b0f02703 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 17:37:41 +0100 Subject: [PATCH 48/89] Add spawn method --- minecraft-server/src/ecs.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/minecraft-server/src/ecs.rs b/minecraft-server/src/ecs.rs index b0d1c482..cfe069c8 100644 --- a/minecraft-server/src/ecs.rs +++ b/minecraft-server/src/ecs.rs @@ -3,7 +3,9 @@ use crate::*; use minecraft_protocol::packets::UUID; use tokio::sync::RwLock; -pub struct Entities { +pub struct Entities { + eid_counter: std::sync::atomic::AtomicU32, + uuid_counter: std::sync::atomic::AtomicU64, pub entities: RwLock>, /// A hashmap of chunk positions to get a list of entities in a chunk @@ -16,6 +18,8 @@ pub struct Entities { impl Entities { pub fn new() -> Entities { Entities { + eid_counter: std::sync::atomic::AtomicU32::new(0), + uuid_counter: std::sync::atomic::AtomicU64::new(0), entities: RwLock::new(HashMap::new()), chunks: RwLock::new(HashMap::new()), uuids: RwLock::new(HashMap::new()), @@ -45,7 +49,19 @@ impl Entities { Some(r) } else { None - } + } + } + + pub async fn spawn(&self, entity: AnyEntity) -> Eid { + let eid = self.eid_counter.fetch_add(1, std::sync::atomic::Ordering::SeqCst); + let uid = self.uuid_counter.fetch_add(1, std::sync::atomic::Ordering::SeqCst) as u128; + let mut entities = self.entities.write().await; + let mut chunks = self.chunks.write().await; + let mut uuids = self.uuids.write().await; + chunks.entry(entity.as_entity().position.chunk()).or_insert(HashSet::new()).insert(eid); + entities.insert(eid, entity); + uuids.insert(uid, eid); + eid } /// Remove an entity From 7248670a9fb3f19dfdbf9391e883ee05a6322761 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 18:03:58 +0100 Subject: [PATCH 49/89] Add AnyEntity.as_network --- .../src/animals/water_animal.rs | 4 +- minecraft-entities/src/lib.rs | 139 +++++++++++++++++- 2 files changed, 140 insertions(+), 3 deletions(-) diff --git a/minecraft-entities/src/animals/water_animal.rs b/minecraft-entities/src/animals/water_animal.rs index 3645aa2e..2073ac7f 100644 --- a/minecraft-entities/src/animals/water_animal.rs +++ b/minecraft-entities/src/animals/water_animal.rs @@ -33,7 +33,7 @@ pub struct Squid { #[MinecraftEntity( inheritable, ancestors { WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, - descendants { Cod, PufferFish, Salmon, TropicalFish, Tadpole... }, + descendants { Cod, Pufferfish, Salmon, TropicalFish, Tadpole... }, )] pub struct AbstractFish { pub water_animal: WaterAnimal, @@ -52,7 +52,7 @@ pub struct Cod { #[MinecraftEntity( ancestors { AbstractFish, WaterAnimal, PathfinderMob, Mob, LivingEntity, Entity }, )] -pub struct PufferFish { +pub struct Pufferfish { pub abstract_fish: AbstractFish, pub puff_state: usize, } diff --git a/minecraft-entities/src/lib.rs b/minecraft-entities/src/lib.rs index 70ca8449..e5ec6eca 100644 --- a/minecraft-entities/src/lib.rs +++ b/minecraft-entities/src/lib.rs @@ -234,7 +234,7 @@ pub enum AnyEntity { Dolphin(Dolphin), AbstractFish(AbstractFish), Cod(Cod), - PufferFish(PufferFish), + Pufferfish(Pufferfish), Salmon(Salmon), TropicalFish(TropicalFish), Tadpole(Tadpole), @@ -244,4 +244,141 @@ impl AnyEntity { pub fn as_entity(&self) -> &Entity { self.try_as_entity_ref().unwrap() } + + pub fn as_network(&self) -> Option { + use minecraft_protocol::ids::entities::Entity::*; + match self { + AnyEntity::Entity(_) => None, + AnyEntity::Interaction(_) => Some(Interaction), + AnyEntity::Display(_) => None, + AnyEntity::BlockDisplay(_) => Some(BlockDisplay), + AnyEntity::ItemDisplay(_) => Some(ItemDisplay), + AnyEntity::TextDisplay(_) => Some(TextDisplay), + AnyEntity::ThrownItemProjectile(_) => None, + AnyEntity::ThrownEgg(_) => Some(Egg), + AnyEntity::ThrownEnderPearl(_) => Some(EnderPearl), + AnyEntity::ThrownExperienceBottle(_) => Some(ExperienceBottle), + AnyEntity::ThrownPotion(_) => Some(Potion), + AnyEntity::Snowball(_) => Some(Snowball), + AnyEntity::AbstractArrow(_) => Some(Arrow), // Default to arrow + AnyEntity::Arrow(_) => Some(Arrow), + AnyEntity::SpectralArrow(_) => Some(SpectralArrow), + AnyEntity::ThrownTrident(_) => Some(Trident), + AnyEntity::Boat(_) => Some(Boat), + AnyEntity::ChestBoat(_) => Some(ChestBoat), + AnyEntity::LivingEntity(_) => None, + AnyEntity::Player(_) => Some(Player), + AnyEntity::Mob(_) => None, + AnyEntity::AmbientCreature(_) => None, + AnyEntity::Bat(_) => Some(Bat), + AnyEntity::PathfinderMob(_) => None, + AnyEntity::WaterAnimal(_) => None, + AnyEntity::Squid(_) => Some(Squid), + AnyEntity::AgeableMob(_) => None, + AnyEntity::Animal(_) => None, + AnyEntity::Sniffer(_) => Some(Sniffer), + AnyEntity::AbstractHorse(_) => None, + AnyEntity::Horse(_) => Some(Horse), + AnyEntity::ZombieHorse(_) => Some(ZombieHorse), + AnyEntity::SkeletonHorse(_) => Some(SkeletonHorse), + AnyEntity::Camel(_) => Some(Camel), + AnyEntity::ChestedHorse(_) => None, + AnyEntity::Donkey(_) => Some(Donkey), + AnyEntity::Llama(_) => Some(Llama), + AnyEntity::TraderLlama(_) => Some(TraderLlama), + AnyEntity::Mule(_) => Some(Mule), + AnyEntity::Axolotl(_) => Some(Axolotl), + AnyEntity::Bee(_) => Some(Bee), + AnyEntity::Fox(_) => Some(Fox), + AnyEntity::Frog(_) => Some(Frog), + AnyEntity::Ocelot(_) => Some(Ocelot), + AnyEntity::Panda(_) => Some(Panda), + AnyEntity::Pig(_) => Some(Pig), + AnyEntity::Rabbit(_) => Some(Rabbit), + AnyEntity::Turtle(_) => Some(Turtle), + AnyEntity::PolarBear(_) => Some(PolarBear), + AnyEntity::Chicken(_) => Some(Chicken), + AnyEntity::Cow(_) => Some(Cow), + AnyEntity::Hoglin(_) => Some(Hoglin), + AnyEntity::Mooshroom(_) => Some(Mooshroom), + AnyEntity::Sheep(_) => Some(Sheep), + AnyEntity::Strider(_) => Some(Strider), + AnyEntity::TameableAnimal(_) => None, + AnyEntity::Cat(_) => Some(Cat), + AnyEntity::Wolf(_) => Some(Wolf), + AnyEntity::Parrot(_) => Some(Parrot), + AnyEntity::AbstractVillager(_) => None, + AnyEntity::Villager(_) => Some(Villager), + AnyEntity::WanderingTrader(_) => Some(WanderingTrader), + AnyEntity::AbstractGolem(_) => None, + AnyEntity::IronGolem(_) => Some(IronGolem), + AnyEntity::SnowGolem(_) => Some(SnowGolem), + AnyEntity::Shulker(_) => Some(Shulker), + AnyEntity::Monster(_) => None, + AnyEntity::BasePiglin(_) => None, + AnyEntity::Piglin(_) => Some(Piglin), + AnyEntity::PiglinBrute(_) => Some(PiglinBrute), + AnyEntity::Blaze(_) => Some(Blaze), + AnyEntity::Creeper(_) => Some(Creeper), + AnyEntity::Endermite(_) => Some(Endermite), + AnyEntity::Giant(_) => Some(Giant), + AnyEntity::Goat(_) => Some(Goat), + AnyEntity::Guardian(_) => Some(Guardian), + AnyEntity::ElderGuardian(_) => Some(ElderGuardian), + AnyEntity::Silverfish(_) => Some(Silverfish), + AnyEntity::Raider(_) => None, + AnyEntity::AbstractIllager(_) => None, + AnyEntity::Vindicator(_) => Some(Vindicator), + AnyEntity::Pillager(_) => Some(Pillager), + AnyEntity::SpellcasterIllager(_) => None, + AnyEntity::Evoker(_) => Some(Evoker), + AnyEntity::Illusioner(_) => Some(Illusioner), + AnyEntity::Ravager(_) => Some(Ravager), + AnyEntity::Witch(_) => Some(Witch), + AnyEntity::EvokerFangs(_) => Some(EvokerFangs), + AnyEntity::Vex(_) => Some(Vex), + AnyEntity::Skeleton(_) => Some(Skeleton), + AnyEntity::AbstractSkeleton(_) => None, + AnyEntity::WitherSkeleton(_) => Some(WitherSkeleton), + AnyEntity::Stray(_) => Some(Stray), + AnyEntity::Spider(_) => Some(Spider), + AnyEntity::Warden(_) => Some(Warden), + AnyEntity::Wither(_) => Some(Wither), + AnyEntity::Zoglin(_) => Some(Zoglin), + AnyEntity::Zombie(_) => Some(Zombie), + AnyEntity::ZombieVillager(_) => Some(ZombieVillager), + AnyEntity::Husk(_) => Some(Husk), + AnyEntity::Drowned(_) => Some(Drowned), + AnyEntity::ZombifiedPiglin(_) => Some(ZombifiedPiglin), + AnyEntity::Enderman(_) => Some(Enderman), + AnyEntity::EnderDragon(_) => Some(EnderDragon), + AnyEntity::Flying(_) => None, + AnyEntity::Ghast(_) => Some(Ghast), + AnyEntity::Phantom(_) => Some(Phantom), + AnyEntity::Slime(_) => Some(Slime), + AnyEntity::LlamaSpit(_) => Some(LlamaSpit), + AnyEntity::EyeOfEnder(_) => Some(EyeOfEnder), + AnyEntity::FallingBlock(_) => Some(FallingBlock), + AnyEntity::AreaEffectCloud(_) => Some(AreaEffectCloud), + AnyEntity::FishingHook(_) => Some(FishingBobber), + AnyEntity::EndCrystal(_) => Some(EndCrystal), + AnyEntity::DragonFireball(_) => Some(DragonFireball), + AnyEntity::SmallFireball(_) => Some(SmallFireball), + AnyEntity::Fireball(_) => Some(Fireball), + AnyEntity::WitherSkull(_) => Some(WitherSkull), + AnyEntity::FireworkRocket(_) => Some(FireworkRocket), + AnyEntity::ItemFrame(_) => Some(ItemFrame), + AnyEntity::GlowingItemFrame(_) => Some(GlowItemFrame), + AnyEntity::Painting(_) => Some(Painting), + AnyEntity::ItemEntity(_) => Some(Item), + AnyEntity::ArmorStand(_) => Some(ArmorStand), + AnyEntity::Dolphin(_) => Some(Dolphin), + AnyEntity::AbstractFish(_) => None, + AnyEntity::Cod(_) => Some(Cod), + AnyEntity::Pufferfish(_) => Some(Pufferfish), + AnyEntity::Salmon(_) => Some(Salmon), + AnyEntity::TropicalFish(_) => Some(TropicalFish), + AnyEntity::Tadpole(_) => Some(Tadpole), + } + } } From 0b0f86fbd7a38196a64d2754ecce07594820da98 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 18:04:31 +0100 Subject: [PATCH 50/89] Rename as_network to to_network --- minecraft-entities/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/minecraft-entities/src/lib.rs b/minecraft-entities/src/lib.rs index e5ec6eca..0d3247cb 100644 --- a/minecraft-entities/src/lib.rs +++ b/minecraft-entities/src/lib.rs @@ -245,7 +245,7 @@ impl AnyEntity { self.try_as_entity_ref().unwrap() } - pub fn as_network(&self) -> Option { + pub fn to_network(&self) -> Option { use minecraft_protocol::ids::entities::Entity::*; match self { AnyEntity::Entity(_) => None, From b2df45a94a64efe61d9479f7a79b5b0f8e32f27f Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 18:05:50 +0100 Subject: [PATCH 51/89] Move ecs.rs --- minecraft-server/src/main.rs | 1 - minecraft-server/src/prelude.rs | 2 +- minecraft-server/src/{ => world}/ecs.rs | 0 minecraft-server/src/world/mod.rs | 2 ++ 4 files changed, 3 insertions(+), 2 deletions(-) rename minecraft-server/src/{ => world}/ecs.rs (100%) diff --git a/minecraft-server/src/main.rs b/minecraft-server/src/main.rs index 4f554561..0e35ebac 100644 --- a/minecraft-server/src/main.rs +++ b/minecraft-server/src/main.rs @@ -3,7 +3,6 @@ mod player_handler; mod server_behavior; mod prelude; -mod ecs; mod world; use crate::prelude::*; diff --git a/minecraft-server/src/prelude.rs b/minecraft-server/src/prelude.rs index 12714819..1d5e137c 100644 --- a/minecraft-server/src/prelude.rs +++ b/minecraft-server/src/prelude.rs @@ -1,4 +1,4 @@ -pub use crate::{ecs::*, player_handler::*, server_behavior::*, world::*}; +pub use crate::{player_handler::*, server_behavior::*, world::*}; pub use futures::FutureExt; pub use log::{debug, error, info, trace, warn}; pub use minecraft_protocol::{ diff --git a/minecraft-server/src/ecs.rs b/minecraft-server/src/world/ecs.rs similarity index 100% rename from minecraft-server/src/ecs.rs rename to minecraft-server/src/world/ecs.rs diff --git a/minecraft-server/src/world/mod.rs b/minecraft-server/src/world/mod.rs index fdd33644..c03cd8ab 100644 --- a/minecraft-server/src/world/mod.rs +++ b/minecraft-server/src/world/mod.rs @@ -6,6 +6,8 @@ mod loading_manager; use loading_manager::*; mod map; use map::*; +mod ecs; +use ecs::*; /// World is the union of the map and entities. /// World handles loaded chunks and entities. From eacba032e0f28d34d6a14ee530faa7b1820e8ccb Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 18:35:56 +0100 Subject: [PATCH 52/89] Send spawning entities to client --- minecraft-entities/src/entity.rs | 4 +++ minecraft-entities/src/lib.rs | 4 +++ minecraft-entities/src/living_entity.rs | 2 ++ minecraft-positions/src/lib.rs | 7 +++++ minecraft-server/src/player_handler/play.rs | 26 ++++++++++++++++-- minecraft-server/src/prelude.rs | 5 +++- minecraft-server/src/world/change_event.rs | 29 ++++++++++++++++++++- minecraft-server/src/world/ecs.rs | 8 +++--- minecraft-server/src/world/mod.rs | 26 ++++++++++++++++-- 9 files changed, 101 insertions(+), 10 deletions(-) diff --git a/minecraft-entities/src/entity.rs b/minecraft-entities/src/entity.rs index 20644851..0954c9a3 100644 --- a/minecraft-entities/src/entity.rs +++ b/minecraft-entities/src/entity.rs @@ -6,6 +6,8 @@ use super::*; )] pub struct Entity { pub position: Position, + pub pitch: f32, + pub yaw: f32, pub is_on_fire: bool, pub is_crouching: bool, pub is_sprinting: bool, @@ -26,6 +28,8 @@ impl Default for Entity { fn default() -> Self { Entity { position: Position { x: 0.0, y: 0.0, z: 0.0 }, + pitch: 0.0, + yaw: 0.0, is_on_fire: false, is_crouching: false, is_sprinting: false, diff --git a/minecraft-entities/src/lib.rs b/minecraft-entities/src/lib.rs index 0d3247cb..28cb748a 100644 --- a/minecraft-entities/src/lib.rs +++ b/minecraft-entities/src/lib.rs @@ -245,6 +245,10 @@ impl AnyEntity { self.try_as_entity_ref().unwrap() } + pub fn as_other(&self) -> Option<&O> where AnyEntity: TryAsEntityRef { + self.try_as_entity_ref() + } + pub fn to_network(&self) -> Option { use minecraft_protocol::ids::entities::Entity::*; match self { diff --git a/minecraft-entities/src/living_entity.rs b/minecraft-entities/src/living_entity.rs index 136e4c95..d0d06d33 100644 --- a/minecraft-entities/src/living_entity.rs +++ b/minecraft-entities/src/living_entity.rs @@ -7,6 +7,7 @@ use super::*; )] pub struct LivingEntity { pub entity: Entity, + pub head_yaw: f32, pub is_hand_active: bool, pub active_hand: Hand, pub is_riptide_spinning: bool, @@ -22,6 +23,7 @@ impl Default for LivingEntity { fn default() -> Self { LivingEntity { entity: Entity::default(), + head_yaw: 0.0, is_hand_active: false, active_hand: Hand::MainHand, is_riptide_spinning: false, diff --git a/minecraft-positions/src/lib.rs b/minecraft-positions/src/lib.rs index 3d3f0ce8..e67cc314 100644 --- a/minecraft-positions/src/lib.rs +++ b/minecraft-positions/src/lib.rs @@ -105,6 +105,13 @@ impl Position { cz: (self.z.floor() as i32).div_euclid(16), } } + + pub fn chunk_column(&self) -> ChunkColumnPosition { + ChunkColumnPosition { + cx: (self.x.floor() as i32).div_euclid(16), + cz: (self.z.floor() as i32).div_euclid(16), + } + } } impl std::ops::Add for Position { diff --git a/minecraft-server/src/player_handler/play.rs b/minecraft-server/src/player_handler/play.rs index 25141213..56090c0a 100644 --- a/minecraft-server/src/player_handler/play.rs +++ b/minecraft-server/src/player_handler/play.rs @@ -30,13 +30,31 @@ impl PlayerHandler { } } - async fn on_block_change(&mut self, position: BlockPosition, block: BlockWithState) { + async fn on_block_changed(&mut self, position: BlockPosition, block: BlockWithState) { self.send_packet(PlayClientbound::BlockUpdate { location: position.into(), block_state: block, }).await; } + async fn on_entity_spawned(&mut self, eid: Eid, uuid: UUID, ty: NetworkEntity, position: Position, pitch: f32, yaw: f32, head_yaw: f32, data: u32, velocity: (), metadata: ()) { + self.send_packet(PlayClientbound::SpawnEntity { + id: VarInt(eid as i32), + uuid, + entity_type: ty, + x: position.x, + y: position.y, + z: position.z, + pitch: (pitch * (256.0 / 360.0)) as u8, + yaw: (yaw * (256.0 / 360.0)) as u8, + head_yaw: (head_yaw * (256.0 / 360.0)) as u8, + data: VarInt(data as i32), + velocity_x: 0, + velocity_y: 0, + velocity_z: 0, + }).await; + } + async fn on_move(&mut self) { let new_center_chunk = self.position.chunk(); @@ -225,7 +243,11 @@ pub async fn handle_player(stream: TcpStream, player_info: PlayerInfo, mut serve receive_change_fut = Box::pin(change_receiver.recv().fuse()); match change { - WorldChange::BlockChange(position, block) => handler.on_block_change(position, block).await, + WorldChange::Block(position, block) => handler.on_block_changed(position, block).await, + WorldChange::EntitySpawned { eid, uuid: uid, ty, position, pitch, yaw, head_yaw, data, velocity, metadata } => handler.on_entity_spawned(eid, uid, ty, position, pitch, yaw, head_yaw, data, velocity, metadata).await, + WorldChange::EntityDispawned { eid } => todo!(), + WorldChange::EntityMetadata { eid, metadata } => todo!(), + WorldChange::EntityMoved { eid, position, pitch, yaw, head_yaw } => todo!(), } }, Event::Message(Err(recv_error)) => { diff --git a/minecraft-server/src/prelude.rs b/minecraft-server/src/prelude.rs index 1d5e137c..fade910b 100644 --- a/minecraft-server/src/prelude.rs +++ b/minecraft-server/src/prelude.rs @@ -22,7 +22,10 @@ pub use minecraft_protocol::{ status::{ClientboundPacket as StatusClientbound, ServerboundPacket as StatusServerbound}, Array, ConnectionState, Map, RawBytes, VarInt, VarLong, UUID, Position as NetworkPosition }, - ids::block_states::BlockWithState, + ids::{ + block_states::BlockWithState, + entities::Entity as NetworkEntity, + }, MinecraftPacketPart, }; pub use std::{ diff --git a/minecraft-server/src/world/change_event.rs b/minecraft-server/src/world/change_event.rs index 6ac08fcf..86d41e53 100644 --- a/minecraft-server/src/world/change_event.rs +++ b/minecraft-server/src/world/change_event.rs @@ -2,5 +2,32 @@ use crate::prelude::*; #[derive(Debug, Clone)] pub enum WorldChange { - BlockChange(BlockPosition, BlockWithState), + Block(BlockPosition, BlockWithState), + EntitySpawned { + eid: Eid, + uuid: UUID, + ty: NetworkEntity, + position: Position, + pitch: f32, + yaw: f32, + head_yaw: f32, + data: u32, + velocity: (), + metadata: (), + }, + EntityDispawned { + eid: Eid, + }, + EntityMetadata { + eid: Eid, + metadata: (), + }, + // TODO packet without this + EntityMoved { + eid: Eid, + position: Position, + pitch: f32, + yaw: f32, + head_yaw: f32, + }, } diff --git a/minecraft-server/src/world/ecs.rs b/minecraft-server/src/world/ecs.rs index cfe069c8..b44c62c8 100644 --- a/minecraft-server/src/world/ecs.rs +++ b/minecraft-server/src/world/ecs.rs @@ -52,16 +52,16 @@ impl Entities { } } - pub async fn spawn(&self, entity: AnyEntity) -> Eid { + pub async fn spawn_entity(&self, entity: AnyEntity) -> (Eid, UUID) { let eid = self.eid_counter.fetch_add(1, std::sync::atomic::Ordering::SeqCst); - let uid = self.uuid_counter.fetch_add(1, std::sync::atomic::Ordering::SeqCst) as u128; + let uuid = self.uuid_counter.fetch_add(1, std::sync::atomic::Ordering::SeqCst) as u128; let mut entities = self.entities.write().await; let mut chunks = self.chunks.write().await; let mut uuids = self.uuids.write().await; chunks.entry(entity.as_entity().position.chunk()).or_insert(HashSet::new()).insert(eid); entities.insert(eid, entity); - uuids.insert(uid, eid); - eid + uuids.insert(uuid, eid); + (eid, uuid) } /// Remove an entity diff --git a/minecraft-server/src/world/mod.rs b/minecraft-server/src/world/mod.rs index c03cd8ab..0fbb2120 100644 --- a/minecraft-server/src/world/mod.rs +++ b/minecraft-server/src/world/mod.rs @@ -40,7 +40,7 @@ impl World { pub async fn set_block(&self, position: BlockPosition, block: BlockWithState) { self.map.set_block(position.clone(), block.clone()).await; - self.notify(&position.chunk_column(), WorldChange::BlockChange(position, block)).await; + self.notify(&position.chunk_column(), WorldChange::Block(position, block)).await; } pub async fn add_loader(&self, uuid: UUID) -> MpscReceiver { @@ -69,6 +69,28 @@ impl World { } } + pub async fn spawn_entity(&self, entity: AnyEntity) -> Eid { + let position = entity.as_entity().position.clone(); + let ty = entity.to_network().unwrap(); // TODO: error handling + let pitch = entity.as_entity().pitch; + let yaw = entity.as_entity().yaw; + let head_yaw = entity.as_other::().map(|e| e.head_yaw).unwrap_or(0.0); + let (eid, uuid) = self.entities.spawn_entity(entity).await; + self.notify(&position.chunk_column(), WorldChange::EntitySpawned { + eid, + uuid, + ty, + position, + pitch, + yaw, + head_yaw, + data: 0, + velocity: (), + metadata: (), + }).await; + eid + } + async fn notify(&self, position: &ChunkColumnPosition, change: WorldChange) { let loading_manager = self.loading_manager.read().await; let mut senders = self.change_senders.write().await; @@ -110,7 +132,7 @@ mod tests { world.update_loaded_chunks(2, vec![ChunkColumnPosition{cx: 1, cz: 1}].into_iter().collect()).await; world.set_block(BlockPosition{x: 1, y: 1, z: 1}, BlockWithState::Air).await; - assert!(matches!(receiver1.try_recv(), Ok(WorldChange::BlockChange(BlockPosition{x: 1, y: 1, z: 1}, BlockWithState::Air)))); + assert!(matches!(receiver1.try_recv(), Ok(WorldChange::Block(BlockPosition{x: 1, y: 1, z: 1}, BlockWithState::Air)))); assert!(matches!(receiver2.try_recv(), Err(TryRecvError::Empty))); } } From a2daf456b4f1a50410f5965110266446e5a8101e Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 18:54:25 +0100 Subject: [PATCH 53/89] Allow summoning zombies --- minecraft-server/src/player_handler/play.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/minecraft-server/src/player_handler/play.rs b/minecraft-server/src/player_handler/play.rs index 56090c0a..df7b5088 100644 --- a/minecraft-server/src/player_handler/play.rs +++ b/minecraft-server/src/player_handler/play.rs @@ -168,6 +168,13 @@ impl PlayerHandler { self.world.set_block(location.into(), BlockWithState::Air).await; } } + ChatMessage { message, .. } => { + if message == "summon" { + let mut zombie = Zombie::default(); + zombie.get_entity_mut().position = self.position.clone(); + self.world.spawn_entity(AnyEntity::Zombie(zombie)).await; + } + } packet => warn!("Unsupported packet received: {packet:?}"), } } From 4a6bd21e85f77bbcbd637c354ed3d61485c1b4e1 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 21:07:24 +0100 Subject: [PATCH 54/89] Add entity tasks --- minecraft-server/src/world/ecs.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/minecraft-server/src/world/ecs.rs b/minecraft-server/src/world/ecs.rs index b44c62c8..6b5a6674 100644 --- a/minecraft-server/src/world/ecs.rs +++ b/minecraft-server/src/world/ecs.rs @@ -3,6 +3,8 @@ use crate::*; use minecraft_protocol::packets::UUID; use tokio::sync::RwLock; +pub type EntityTask = Pin + Send + Sync + 'static>>; + pub struct Entities { eid_counter: std::sync::atomic::AtomicU32, uuid_counter: std::sync::atomic::AtomicU64, @@ -11,8 +13,7 @@ pub struct Entities { /// A hashmap of chunk positions to get a list of entities in a chunk pub chunks: RwLock>>, pub uuids: RwLock>, - - // TODO: pub entities_by_tag: RwLock>>, + pub entity_tasks: RwLock>>, } impl Entities { @@ -23,6 +24,7 @@ impl Entities { entities: RwLock::new(HashMap::new()), chunks: RwLock::new(HashMap::new()), uuids: RwLock::new(HashMap::new()), + entity_tasks: RwLock::new(HashMap::new()), } } @@ -66,6 +68,13 @@ impl Entities { /// Remove an entity pub async fn remove_entity(&self, eid: Eid) -> Option { - self.entities.write().await.remove(&eid) + let entity = self.entities.write().await.remove(&eid); + let mut chunks = self.chunks.write().await; + chunks.values_mut().for_each(|set| { set.remove(&eid); }); + chunks.retain(|_,v| !v.is_empty()); + drop(chunks); + self.uuids.write().await.retain(|_,v| *v != eid); + self.entity_tasks.write().await.remove(&eid); + entity } } From 6984f3e662779c54df3089cf82b47dce0410aaf2 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 21:10:05 +0100 Subject: [PATCH 55/89] Turn entity crates to module --- Cargo.toml | 1 - minecraft-entities/Cargo.toml | 12 ------------ minecraft-server/Cargo.toml | 1 - .../src/entities}/animals/axolotl.rs | 0 .../src/entities}/animals/bee.rs | 0 .../src/entities}/animals/cat.rs | 0 .../src/entities}/animals/chicken.rs | 0 .../src/entities}/animals/cow.rs | 0 .../src/entities}/animals/fox.rs | 0 .../src/entities}/animals/frog.rs | 0 .../src/entities}/animals/goat.rs | 0 .../src/entities}/animals/hoglin.rs | 0 .../src/entities}/animals/horses.rs | 0 .../src/entities}/animals/mod.rs | 0 .../src/entities}/animals/ocelot.rs | 0 .../src/entities}/animals/panda.rs | 0 .../src/entities}/animals/parrot.rs | 0 .../src/entities}/animals/pig.rs | 0 .../src/entities}/animals/polar_bear.rs | 0 .../src/entities}/animals/rabbit.rs | 0 .../src/entities}/animals/sheep.rs | 0 .../src/entities}/animals/sniffer.rs | 0 .../src/entities}/animals/strider.rs | 0 .../src/entities}/animals/turtle.rs | 0 .../src/entities}/animals/water_animal.rs | 0 .../src/entities}/animals/wolf.rs | 0 .../src => minecraft-server/src/entities}/arrow.rs | 0 .../src => minecraft-server/src/entities}/block.rs | 0 .../src => minecraft-server/src/entities}/boat.rs | 0 .../src => minecraft-server/src/entities}/display.rs | 0 .../src => minecraft-server/src/entities}/entity.rs | 0 .../src/entities}/fire_entities.rs | 0 .../src/entities}/interaction.rs | 0 .../src => minecraft-server/src/entities}/item.rs | 0 .../src/entities}/living_entity.rs | 0 .../src/entities}/mobs/bat.rs | 0 .../src/entities}/mobs/ender_dragon.rs | 0 .../src/entities}/mobs/flying.rs | 0 .../src/entities}/mobs/golems.rs | 0 .../src/entities}/mobs/mod.rs | 0 .../src/entities}/mobs/slime.rs | 0 .../src/entities}/mobs/villagers.rs | 0 .../lib.rs => minecraft-server/src/entities/mod.rs | 0 .../src/entities}/monsters/blaze.rs | 0 .../src/entities}/monsters/creeper.rs | 0 .../src/entities}/monsters/enderman.rs | 0 .../src/entities}/monsters/endermite.rs | 0 .../src/entities}/monsters/giant.rs | 0 .../src/entities}/monsters/guardian.rs | 0 .../src/entities}/monsters/mod.rs | 0 .../src/entities}/monsters/piglin.rs | 0 .../src/entities}/monsters/raider.rs | 0 .../src/entities}/monsters/silverfish.rs | 0 .../src/entities}/monsters/skeleton.rs | 0 .../src/entities}/monsters/spider.rs | 0 .../src/entities}/monsters/vex.rs | 0 .../src/entities}/monsters/warden.rs | 0 .../src/entities}/monsters/wither.rs | 0 .../src/entities}/monsters/zoglin.rs | 0 .../src/entities}/monsters/zombies.rs | 0 .../src/entities}/particles.rs | 0 .../src => minecraft-server/src/entities}/player.rs | 0 .../src => minecraft-server/src/entities}/shulker.rs | 0 .../src/entities}/thrown_item_projectile.rs | 0 minecraft-server/src/main.rs | 1 + minecraft-server/src/prelude.rs | 3 +-- 66 files changed, 2 insertions(+), 16 deletions(-) delete mode 100644 minecraft-entities/Cargo.toml rename {minecraft-entities/src => minecraft-server/src/entities}/animals/axolotl.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/animals/bee.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/animals/cat.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/animals/chicken.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/animals/cow.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/animals/fox.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/animals/frog.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/animals/goat.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/animals/hoglin.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/animals/horses.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/animals/mod.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/animals/ocelot.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/animals/panda.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/animals/parrot.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/animals/pig.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/animals/polar_bear.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/animals/rabbit.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/animals/sheep.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/animals/sniffer.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/animals/strider.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/animals/turtle.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/animals/water_animal.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/animals/wolf.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/arrow.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/block.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/boat.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/display.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/entity.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/fire_entities.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/interaction.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/item.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/living_entity.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/mobs/bat.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/mobs/ender_dragon.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/mobs/flying.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/mobs/golems.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/mobs/mod.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/mobs/slime.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/mobs/villagers.rs (100%) rename minecraft-entities/src/lib.rs => minecraft-server/src/entities/mod.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/monsters/blaze.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/monsters/creeper.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/monsters/enderman.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/monsters/endermite.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/monsters/giant.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/monsters/guardian.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/monsters/mod.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/monsters/piglin.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/monsters/raider.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/monsters/silverfish.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/monsters/skeleton.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/monsters/spider.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/monsters/vex.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/monsters/warden.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/monsters/wither.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/monsters/zoglin.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/monsters/zombies.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/particles.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/player.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/shulker.rs (100%) rename {minecraft-entities/src => minecraft-server/src/entities}/thrown_item_projectile.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index 6181c714..d234a39c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,6 @@ members = [ "minecraft-protocol", "minecraft-protocol-derive", "minecraft-server", - "minecraft-entities", "minecraft-entities-derive", "minecraft-positions" ] diff --git a/minecraft-entities/Cargo.toml b/minecraft-entities/Cargo.toml deleted file mode 100644 index d3c140cc..00000000 --- a/minecraft-entities/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "minecraft-entities" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -minecraft-protocol = { path = "../minecraft-protocol" } -minecraft-positions = { path = "../minecraft-positions" } -minecraft-entities-derive = { path="../minecraft-entities-derive" } -tokio = { version = "1.33.0", features = ["full"] } diff --git a/minecraft-server/Cargo.toml b/minecraft-server/Cargo.toml index c2526501..04ba5ef9 100644 --- a/minecraft-server/Cargo.toml +++ b/minecraft-server/Cargo.toml @@ -11,6 +11,5 @@ log = "0.4.20" tokio = { version = "1.33.0", features = ["full"] } futures = "0.3.29" minecraft-protocol = { path="../minecraft-protocol" } -minecraft-entities = { path="../minecraft-entities" } minecraft-positions = { path="../minecraft-positions" } rand = "0.8.4" diff --git a/minecraft-entities/src/animals/axolotl.rs b/minecraft-server/src/entities/animals/axolotl.rs similarity index 100% rename from minecraft-entities/src/animals/axolotl.rs rename to minecraft-server/src/entities/animals/axolotl.rs diff --git a/minecraft-entities/src/animals/bee.rs b/minecraft-server/src/entities/animals/bee.rs similarity index 100% rename from minecraft-entities/src/animals/bee.rs rename to minecraft-server/src/entities/animals/bee.rs diff --git a/minecraft-entities/src/animals/cat.rs b/minecraft-server/src/entities/animals/cat.rs similarity index 100% rename from minecraft-entities/src/animals/cat.rs rename to minecraft-server/src/entities/animals/cat.rs diff --git a/minecraft-entities/src/animals/chicken.rs b/minecraft-server/src/entities/animals/chicken.rs similarity index 100% rename from minecraft-entities/src/animals/chicken.rs rename to minecraft-server/src/entities/animals/chicken.rs diff --git a/minecraft-entities/src/animals/cow.rs b/minecraft-server/src/entities/animals/cow.rs similarity index 100% rename from minecraft-entities/src/animals/cow.rs rename to minecraft-server/src/entities/animals/cow.rs diff --git a/minecraft-entities/src/animals/fox.rs b/minecraft-server/src/entities/animals/fox.rs similarity index 100% rename from minecraft-entities/src/animals/fox.rs rename to minecraft-server/src/entities/animals/fox.rs diff --git a/minecraft-entities/src/animals/frog.rs b/minecraft-server/src/entities/animals/frog.rs similarity index 100% rename from minecraft-entities/src/animals/frog.rs rename to minecraft-server/src/entities/animals/frog.rs diff --git a/minecraft-entities/src/animals/goat.rs b/minecraft-server/src/entities/animals/goat.rs similarity index 100% rename from minecraft-entities/src/animals/goat.rs rename to minecraft-server/src/entities/animals/goat.rs diff --git a/minecraft-entities/src/animals/hoglin.rs b/minecraft-server/src/entities/animals/hoglin.rs similarity index 100% rename from minecraft-entities/src/animals/hoglin.rs rename to minecraft-server/src/entities/animals/hoglin.rs diff --git a/minecraft-entities/src/animals/horses.rs b/minecraft-server/src/entities/animals/horses.rs similarity index 100% rename from minecraft-entities/src/animals/horses.rs rename to minecraft-server/src/entities/animals/horses.rs diff --git a/minecraft-entities/src/animals/mod.rs b/minecraft-server/src/entities/animals/mod.rs similarity index 100% rename from minecraft-entities/src/animals/mod.rs rename to minecraft-server/src/entities/animals/mod.rs diff --git a/minecraft-entities/src/animals/ocelot.rs b/minecraft-server/src/entities/animals/ocelot.rs similarity index 100% rename from minecraft-entities/src/animals/ocelot.rs rename to minecraft-server/src/entities/animals/ocelot.rs diff --git a/minecraft-entities/src/animals/panda.rs b/minecraft-server/src/entities/animals/panda.rs similarity index 100% rename from minecraft-entities/src/animals/panda.rs rename to minecraft-server/src/entities/animals/panda.rs diff --git a/minecraft-entities/src/animals/parrot.rs b/minecraft-server/src/entities/animals/parrot.rs similarity index 100% rename from minecraft-entities/src/animals/parrot.rs rename to minecraft-server/src/entities/animals/parrot.rs diff --git a/minecraft-entities/src/animals/pig.rs b/minecraft-server/src/entities/animals/pig.rs similarity index 100% rename from minecraft-entities/src/animals/pig.rs rename to minecraft-server/src/entities/animals/pig.rs diff --git a/minecraft-entities/src/animals/polar_bear.rs b/minecraft-server/src/entities/animals/polar_bear.rs similarity index 100% rename from minecraft-entities/src/animals/polar_bear.rs rename to minecraft-server/src/entities/animals/polar_bear.rs diff --git a/minecraft-entities/src/animals/rabbit.rs b/minecraft-server/src/entities/animals/rabbit.rs similarity index 100% rename from minecraft-entities/src/animals/rabbit.rs rename to minecraft-server/src/entities/animals/rabbit.rs diff --git a/minecraft-entities/src/animals/sheep.rs b/minecraft-server/src/entities/animals/sheep.rs similarity index 100% rename from minecraft-entities/src/animals/sheep.rs rename to minecraft-server/src/entities/animals/sheep.rs diff --git a/minecraft-entities/src/animals/sniffer.rs b/minecraft-server/src/entities/animals/sniffer.rs similarity index 100% rename from minecraft-entities/src/animals/sniffer.rs rename to minecraft-server/src/entities/animals/sniffer.rs diff --git a/minecraft-entities/src/animals/strider.rs b/minecraft-server/src/entities/animals/strider.rs similarity index 100% rename from minecraft-entities/src/animals/strider.rs rename to minecraft-server/src/entities/animals/strider.rs diff --git a/minecraft-entities/src/animals/turtle.rs b/minecraft-server/src/entities/animals/turtle.rs similarity index 100% rename from minecraft-entities/src/animals/turtle.rs rename to minecraft-server/src/entities/animals/turtle.rs diff --git a/minecraft-entities/src/animals/water_animal.rs b/minecraft-server/src/entities/animals/water_animal.rs similarity index 100% rename from minecraft-entities/src/animals/water_animal.rs rename to minecraft-server/src/entities/animals/water_animal.rs diff --git a/minecraft-entities/src/animals/wolf.rs b/minecraft-server/src/entities/animals/wolf.rs similarity index 100% rename from minecraft-entities/src/animals/wolf.rs rename to minecraft-server/src/entities/animals/wolf.rs diff --git a/minecraft-entities/src/arrow.rs b/minecraft-server/src/entities/arrow.rs similarity index 100% rename from minecraft-entities/src/arrow.rs rename to minecraft-server/src/entities/arrow.rs diff --git a/minecraft-entities/src/block.rs b/minecraft-server/src/entities/block.rs similarity index 100% rename from minecraft-entities/src/block.rs rename to minecraft-server/src/entities/block.rs diff --git a/minecraft-entities/src/boat.rs b/minecraft-server/src/entities/boat.rs similarity index 100% rename from minecraft-entities/src/boat.rs rename to minecraft-server/src/entities/boat.rs diff --git a/minecraft-entities/src/display.rs b/minecraft-server/src/entities/display.rs similarity index 100% rename from minecraft-entities/src/display.rs rename to minecraft-server/src/entities/display.rs diff --git a/minecraft-entities/src/entity.rs b/minecraft-server/src/entities/entity.rs similarity index 100% rename from minecraft-entities/src/entity.rs rename to minecraft-server/src/entities/entity.rs diff --git a/minecraft-entities/src/fire_entities.rs b/minecraft-server/src/entities/fire_entities.rs similarity index 100% rename from minecraft-entities/src/fire_entities.rs rename to minecraft-server/src/entities/fire_entities.rs diff --git a/minecraft-entities/src/interaction.rs b/minecraft-server/src/entities/interaction.rs similarity index 100% rename from minecraft-entities/src/interaction.rs rename to minecraft-server/src/entities/interaction.rs diff --git a/minecraft-entities/src/item.rs b/minecraft-server/src/entities/item.rs similarity index 100% rename from minecraft-entities/src/item.rs rename to minecraft-server/src/entities/item.rs diff --git a/minecraft-entities/src/living_entity.rs b/minecraft-server/src/entities/living_entity.rs similarity index 100% rename from minecraft-entities/src/living_entity.rs rename to minecraft-server/src/entities/living_entity.rs diff --git a/minecraft-entities/src/mobs/bat.rs b/minecraft-server/src/entities/mobs/bat.rs similarity index 100% rename from minecraft-entities/src/mobs/bat.rs rename to minecraft-server/src/entities/mobs/bat.rs diff --git a/minecraft-entities/src/mobs/ender_dragon.rs b/minecraft-server/src/entities/mobs/ender_dragon.rs similarity index 100% rename from minecraft-entities/src/mobs/ender_dragon.rs rename to minecraft-server/src/entities/mobs/ender_dragon.rs diff --git a/minecraft-entities/src/mobs/flying.rs b/minecraft-server/src/entities/mobs/flying.rs similarity index 100% rename from minecraft-entities/src/mobs/flying.rs rename to minecraft-server/src/entities/mobs/flying.rs diff --git a/minecraft-entities/src/mobs/golems.rs b/minecraft-server/src/entities/mobs/golems.rs similarity index 100% rename from minecraft-entities/src/mobs/golems.rs rename to minecraft-server/src/entities/mobs/golems.rs diff --git a/minecraft-entities/src/mobs/mod.rs b/minecraft-server/src/entities/mobs/mod.rs similarity index 100% rename from minecraft-entities/src/mobs/mod.rs rename to minecraft-server/src/entities/mobs/mod.rs diff --git a/minecraft-entities/src/mobs/slime.rs b/minecraft-server/src/entities/mobs/slime.rs similarity index 100% rename from minecraft-entities/src/mobs/slime.rs rename to minecraft-server/src/entities/mobs/slime.rs diff --git a/minecraft-entities/src/mobs/villagers.rs b/minecraft-server/src/entities/mobs/villagers.rs similarity index 100% rename from minecraft-entities/src/mobs/villagers.rs rename to minecraft-server/src/entities/mobs/villagers.rs diff --git a/minecraft-entities/src/lib.rs b/minecraft-server/src/entities/mod.rs similarity index 100% rename from minecraft-entities/src/lib.rs rename to minecraft-server/src/entities/mod.rs diff --git a/minecraft-entities/src/monsters/blaze.rs b/minecraft-server/src/entities/monsters/blaze.rs similarity index 100% rename from minecraft-entities/src/monsters/blaze.rs rename to minecraft-server/src/entities/monsters/blaze.rs diff --git a/minecraft-entities/src/monsters/creeper.rs b/minecraft-server/src/entities/monsters/creeper.rs similarity index 100% rename from minecraft-entities/src/monsters/creeper.rs rename to minecraft-server/src/entities/monsters/creeper.rs diff --git a/minecraft-entities/src/monsters/enderman.rs b/minecraft-server/src/entities/monsters/enderman.rs similarity index 100% rename from minecraft-entities/src/monsters/enderman.rs rename to minecraft-server/src/entities/monsters/enderman.rs diff --git a/minecraft-entities/src/monsters/endermite.rs b/minecraft-server/src/entities/monsters/endermite.rs similarity index 100% rename from minecraft-entities/src/monsters/endermite.rs rename to minecraft-server/src/entities/monsters/endermite.rs diff --git a/minecraft-entities/src/monsters/giant.rs b/minecraft-server/src/entities/monsters/giant.rs similarity index 100% rename from minecraft-entities/src/monsters/giant.rs rename to minecraft-server/src/entities/monsters/giant.rs diff --git a/minecraft-entities/src/monsters/guardian.rs b/minecraft-server/src/entities/monsters/guardian.rs similarity index 100% rename from minecraft-entities/src/monsters/guardian.rs rename to minecraft-server/src/entities/monsters/guardian.rs diff --git a/minecraft-entities/src/monsters/mod.rs b/minecraft-server/src/entities/monsters/mod.rs similarity index 100% rename from minecraft-entities/src/monsters/mod.rs rename to minecraft-server/src/entities/monsters/mod.rs diff --git a/minecraft-entities/src/monsters/piglin.rs b/minecraft-server/src/entities/monsters/piglin.rs similarity index 100% rename from minecraft-entities/src/monsters/piglin.rs rename to minecraft-server/src/entities/monsters/piglin.rs diff --git a/minecraft-entities/src/monsters/raider.rs b/minecraft-server/src/entities/monsters/raider.rs similarity index 100% rename from minecraft-entities/src/monsters/raider.rs rename to minecraft-server/src/entities/monsters/raider.rs diff --git a/minecraft-entities/src/monsters/silverfish.rs b/minecraft-server/src/entities/monsters/silverfish.rs similarity index 100% rename from minecraft-entities/src/monsters/silverfish.rs rename to minecraft-server/src/entities/monsters/silverfish.rs diff --git a/minecraft-entities/src/monsters/skeleton.rs b/minecraft-server/src/entities/monsters/skeleton.rs similarity index 100% rename from minecraft-entities/src/monsters/skeleton.rs rename to minecraft-server/src/entities/monsters/skeleton.rs diff --git a/minecraft-entities/src/monsters/spider.rs b/minecraft-server/src/entities/monsters/spider.rs similarity index 100% rename from minecraft-entities/src/monsters/spider.rs rename to minecraft-server/src/entities/monsters/spider.rs diff --git a/minecraft-entities/src/monsters/vex.rs b/minecraft-server/src/entities/monsters/vex.rs similarity index 100% rename from minecraft-entities/src/monsters/vex.rs rename to minecraft-server/src/entities/monsters/vex.rs diff --git a/minecraft-entities/src/monsters/warden.rs b/minecraft-server/src/entities/monsters/warden.rs similarity index 100% rename from minecraft-entities/src/monsters/warden.rs rename to minecraft-server/src/entities/monsters/warden.rs diff --git a/minecraft-entities/src/monsters/wither.rs b/minecraft-server/src/entities/monsters/wither.rs similarity index 100% rename from minecraft-entities/src/monsters/wither.rs rename to minecraft-server/src/entities/monsters/wither.rs diff --git a/minecraft-entities/src/monsters/zoglin.rs b/minecraft-server/src/entities/monsters/zoglin.rs similarity index 100% rename from minecraft-entities/src/monsters/zoglin.rs rename to minecraft-server/src/entities/monsters/zoglin.rs diff --git a/minecraft-entities/src/monsters/zombies.rs b/minecraft-server/src/entities/monsters/zombies.rs similarity index 100% rename from minecraft-entities/src/monsters/zombies.rs rename to minecraft-server/src/entities/monsters/zombies.rs diff --git a/minecraft-entities/src/particles.rs b/minecraft-server/src/entities/particles.rs similarity index 100% rename from minecraft-entities/src/particles.rs rename to minecraft-server/src/entities/particles.rs diff --git a/minecraft-entities/src/player.rs b/minecraft-server/src/entities/player.rs similarity index 100% rename from minecraft-entities/src/player.rs rename to minecraft-server/src/entities/player.rs diff --git a/minecraft-entities/src/shulker.rs b/minecraft-server/src/entities/shulker.rs similarity index 100% rename from minecraft-entities/src/shulker.rs rename to minecraft-server/src/entities/shulker.rs diff --git a/minecraft-entities/src/thrown_item_projectile.rs b/minecraft-server/src/entities/thrown_item_projectile.rs similarity index 100% rename from minecraft-entities/src/thrown_item_projectile.rs rename to minecraft-server/src/entities/thrown_item_projectile.rs diff --git a/minecraft-server/src/main.rs b/minecraft-server/src/main.rs index 0e35ebac..db0828d8 100644 --- a/minecraft-server/src/main.rs +++ b/minecraft-server/src/main.rs @@ -4,6 +4,7 @@ mod player_handler; mod server_behavior; mod prelude; mod world; +mod entities; use crate::prelude::*; diff --git a/minecraft-server/src/prelude.rs b/minecraft-server/src/prelude.rs index fade910b..67738215 100644 --- a/minecraft-server/src/prelude.rs +++ b/minecraft-server/src/prelude.rs @@ -1,4 +1,4 @@ -pub use crate::{player_handler::*, server_behavior::*, world::*}; +pub use crate::{entities::*, player_handler::*, server_behavior::*, world::*}; pub use futures::FutureExt; pub use log::{debug, error, info, trace, warn}; pub use minecraft_protocol::{ @@ -57,6 +57,5 @@ pub use tokio::{ }, }; pub use minecraft_positions::*; -pub use minecraft_entities::*; pub const MAX_PLAYERS: usize = 1001; From 04f26e31cb996c3ec12465ccb6abc56fd3422f2e Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 21:11:06 +0100 Subject: [PATCH 56/89] Fix compilation --- minecraft-server/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/minecraft-server/Cargo.toml b/minecraft-server/Cargo.toml index 04ba5ef9..2c37ee16 100644 --- a/minecraft-server/Cargo.toml +++ b/minecraft-server/Cargo.toml @@ -12,4 +12,5 @@ tokio = { version = "1.33.0", features = ["full"] } futures = "0.3.29" minecraft-protocol = { path="../minecraft-protocol" } minecraft-positions = { path="../minecraft-positions" } +minecraft-entities-derive = { path="../minecraft-entities-derive" } rand = "0.8.4" From 14dea99c6facde01f81892aaf029f57210c8f1c9 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 21:19:12 +0100 Subject: [PATCH 57/89] Simplify observers --- minecraft-server/src/entities/mod.rs | 29 ++++++++++++---------------- minecraft-server/src/world/mod.rs | 23 +++++++++------------- 2 files changed, 21 insertions(+), 31 deletions(-) diff --git a/minecraft-server/src/entities/mod.rs b/minecraft-server/src/entities/mod.rs index 28cb748a..65b621b3 100644 --- a/minecraft-server/src/entities/mod.rs +++ b/minecraft-server/src/entities/mod.rs @@ -33,9 +33,9 @@ pub use fire_entities::*; mod item; pub use item::*; -pub(crate) use minecraft_positions::*; -pub(crate) use minecraft_entities_derive::MinecraftEntity; -pub(crate) use minecraft_protocol::{ +pub use minecraft_positions::*; +pub use minecraft_entities_derive::MinecraftEntity; +pub use minecraft_protocol::{ components::{ entity::Pose, slots::{Slot, SlotItem, Hand} @@ -44,6 +44,7 @@ pub(crate) use minecraft_protocol::{ nbt::NbtTag, packets::UUID }; +pub use crate::prelude::*; use std::{pin::Pin, future::Future}; pub type Eid = u32; @@ -64,20 +65,14 @@ pub trait TryAsEntityRef { fn try_as_entity_mut(&mut self) -> Option<&mut T>; } - -pub trait EntityWorldInterface { - fn observe_entity(&'static self, eid: Eid, observer: Box) -> Pin>>; - fn mutate_entity(&'static self, eid: Eid, mutator: Box) -> Pin>>; -} - pub struct Handler where AnyEntity: TryAsEntityRef { eid: Eid, - world: &'static dyn EntityWorldInterface, + world: &'static World, entity: std::marker::PhantomData, } impl Handler where AnyEntity: TryAsEntityRef { - pub fn assume(id: Eid, world: &'static dyn EntityWorldInterface) -> Self { + pub fn assume(id: Eid, world: &'static World) -> Self { Self { eid: id, world, @@ -93,16 +88,16 @@ impl Handler where AnyEntity: TryAsEntityRef { } } - pub async fn observe(&self, observer: impl FnOnce(&T) + 'static) { - self.world.observe_entity(self.eid, Box::new(move |entity| { + pub async fn observe(&self, observer: impl FnOnce(&T) -> R) -> Option { + self.world.observe_entity(self.eid, move |entity| { observer(entity.try_as_entity_ref().unwrap()) - })).await; + }).await } - pub async fn mutate(&self, mutator: impl FnOnce(&mut T) + 'static) { - self.world.mutate_entity(self.eid, Box::new(move |entity| { + pub async fn mutate(&self, mutator: impl FnOnce(&mut T) -> R) -> Option { + self.world.mutate_entity(self.eid, move |entity| { mutator(entity.try_as_entity_mut().unwrap()) - })).await; + }).await } } diff --git a/minecraft-server/src/world/mod.rs b/minecraft-server/src/world/mod.rs index 0fbb2120..db919a08 100644 --- a/minecraft-server/src/world/mod.rs +++ b/minecraft-server/src/world/mod.rs @@ -91,6 +91,15 @@ impl World { eid } + pub async fn observe_entity(&self, eid: Eid, observer: impl FnOnce(&AnyEntity) -> R) -> Option { + self.entities.observe_entity(eid, observer).await + } + + pub async fn mutate_entity(&self, eid: Eid, mutator: impl FnOnce(&mut AnyEntity) -> R) -> Option { + // TODO change events + self.entities.mutate_entity(eid, mutator).await + } + async fn notify(&self, position: &ChunkColumnPosition, change: WorldChange) { let loading_manager = self.loading_manager.read().await; let mut senders = self.change_senders.write().await; @@ -103,20 +112,6 @@ impl World { } } -impl EntityWorldInterface for World { - fn observe_entity(&'static self, eid: Eid, observer: Box) -> Pin>> { - Box::pin(async move { - self.entities.observe_entity(eid, observer).await; - }) - } - - fn mutate_entity(&'static self, eid: Eid, mutator: Box) -> Pin>> { - Box::pin(async move { - self.entities.mutate_entity(eid, mutator).await; - }) - } -} - #[cfg(test)] mod tests { use super::*; From c035549c3af34fad14ff83744fa9ef08a966bc0b Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 21:26:07 +0100 Subject: [PATCH 58/89] Add ability to insert tasks --- minecraft-server/src/entities/entity.rs | 9 +++++++++ minecraft-server/src/entities/mod.rs | 4 ++-- minecraft-server/src/world/ecs.rs | 18 ++++++++++++++---- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/minecraft-server/src/entities/entity.rs b/minecraft-server/src/entities/entity.rs index 0954c9a3..87efbc0a 100644 --- a/minecraft-server/src/entities/entity.rs +++ b/minecraft-server/src/entities/entity.rs @@ -3,6 +3,9 @@ use super::*; #[MinecraftEntity( inheritable, descendants { AbstractArrow..., Boat..., Display, FallingBlock, LlamaSpit, Painting, DragonFireball, Fireball..., FireworkRocket, SmallFireball, Interaction..., ItemEntity, ItemFrame..., LivingEntity... EndCrystal, EvokerFangs, WitherSkull, AreaEffectCloud, FishingHook, EyeOfEnder, ThrownItemProjectile... }, + defines { + init(self); + } )] pub struct Entity { pub position: Position, @@ -24,6 +27,12 @@ pub struct Entity { pub ticks_frozen: u32, } +impl Handler { + async fn init(self) { + println!("Entity initialized"); + } +} + impl Default for Entity { fn default() -> Self { Entity { diff --git a/minecraft-server/src/entities/mod.rs b/minecraft-server/src/entities/mod.rs index 65b621b3..bf409e06 100644 --- a/minecraft-server/src/entities/mod.rs +++ b/minecraft-server/src/entities/mod.rs @@ -66,8 +66,8 @@ pub trait TryAsEntityRef { } pub struct Handler where AnyEntity: TryAsEntityRef { - eid: Eid, - world: &'static World, + pub eid: Eid, + pub world: &'static World, entity: std::marker::PhantomData, } diff --git a/minecraft-server/src/world/ecs.rs b/minecraft-server/src/world/ecs.rs index 6b5a6674..7b7643e0 100644 --- a/minecraft-server/src/world/ecs.rs +++ b/minecraft-server/src/world/ecs.rs @@ -29,12 +29,12 @@ impl Entities { } /// Observe an entity through a closure - pub async fn observe_entity(&self, eid: Eid, observer: impl FnOnce(&AnyEntity) -> R) -> Option { + pub(super) async fn observe_entity(&self, eid: Eid, observer: impl FnOnce(&AnyEntity) -> R) -> Option { self.entities.read().await.get(&eid).map(observer) } /// Mutate an entity through a closure - pub async fn mutate_entity(&self, eid: Eid, mutator: impl FnOnce(&mut AnyEntity) -> R) -> Option { + pub(super) async fn mutate_entity(&self, eid: Eid, mutator: impl FnOnce(&mut AnyEntity) -> R) -> Option { let mut entities = self.entities.write().await; if let Some(entity) = entities.get_mut(&eid) { @@ -54,7 +54,7 @@ impl Entities { } } - pub async fn spawn_entity(&self, entity: AnyEntity) -> (Eid, UUID) { + pub(super) async fn spawn_entity(&self, entity: AnyEntity) -> (Eid, UUID) { let eid = self.eid_counter.fetch_add(1, std::sync::atomic::Ordering::SeqCst); let uuid = self.uuid_counter.fetch_add(1, std::sync::atomic::Ordering::SeqCst) as u128; let mut entities = self.entities.write().await; @@ -66,8 +66,12 @@ impl Entities { (eid, uuid) } + pub async fn insert_entity_task(&self, eid: Eid, name: &'static str, task: EntityTask) { + self.entity_tasks.write().await.entry(eid).or_insert(HashMap::new()).insert(name, task); + } + /// Remove an entity - pub async fn remove_entity(&self, eid: Eid) -> Option { + pub(super) async fn remove_entity(&self, eid: Eid) -> Option { let entity = self.entities.write().await.remove(&eid); let mut chunks = self.chunks.write().await; chunks.values_mut().for_each(|set| { set.remove(&eid); }); @@ -78,3 +82,9 @@ impl Entities { entity } } + +impl Handler where AnyEntity: TryAsEntityRef { + async fn insert_task(&self, name: &'static str, task: EntityTask) { + self.world.entities.insert_entity_task(self.eid, name, task).await; + } +} From bf662b93fd42746838e0e5c8bac4d3b72ab73885 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sat, 11 Nov 2023 23:59:20 +0100 Subject: [PATCH 59/89] Add gravity --- minecraft-entities-derive/src/lib.rs | 10 +-- minecraft-server/src/entities/entity.rs | 8 +- minecraft-server/src/entities/mod.rs | 27 ++++-- .../src/entities/tasks/gravity.rs | 18 ++++ minecraft-server/src/entities/tasks/mod.rs | 4 + minecraft-server/src/player_handler/play.rs | 42 +++++++-- minecraft-server/src/server_behavior.rs | 2 +- minecraft-server/src/world/change.rs | 87 +++++++++++++++++++ minecraft-server/src/world/change_event.rs | 33 ------- minecraft-server/src/world/ecs.rs | 28 ++++-- minecraft-server/src/world/mod.rs | 53 +++++++++-- 11 files changed, 239 insertions(+), 73 deletions(-) create mode 100644 minecraft-server/src/entities/tasks/gravity.rs create mode 100644 minecraft-server/src/entities/tasks/mod.rs create mode 100644 minecraft-server/src/world/change.rs delete mode 100644 minecraft-server/src/world/change_event.rs diff --git a/minecraft-entities-derive/src/lib.rs b/minecraft-entities-derive/src/lib.rs index c14f078d..f8278b0d 100644 --- a/minecraft-entities-derive/src/lib.rs +++ b/minecraft-entities-derive/src/lib.rs @@ -267,27 +267,27 @@ pub fn MinecraftEntity(attr: proc_macro::TokenStream, item: proc_macro::TokenStr for (_, method, args) in defines.iter().filter(|(ty, _, _)| ty == &struct_name) { let inner_code: TokenStream = match args.len() { 0 => String::from(r#" - fn method(self) -> Pin>> {{ + fn method(self) -> Pin + Sync + Send>> {{ (Self::methods().method)(self.into()) }} "#), 1 => format!(r#" - fn method(self, arg1: {}) -> Pin>> {{ + fn method(self, arg1: {}) -> Pin + Sync + Send>> {{ (Self::methods().method)(self.into(), arg1) }} "#, args[0].1), 2 => format!(r#" - fn method(self, arg1: {}, arg2: {}) -> Pin>> {{ + fn method(self, arg1: {}, arg2: {}) -> Pin + Sync + Send>> {{ (Self::methods().method)(self.into(), arg1, arg2) }} "#, args[0].1, args[1].1), 3 => format!(r#" - fn method(self, arg1: {}, arg2: {}, arg3: {}) -> Pin>> {{ + fn method(self, arg1: {}, arg2: {}, arg3: {}) -> Pin + Sync + Send>> {{ (Self::methods().method)(self.into(), arg1, arg2, arg3) }} "#, args[0].1, args[1].1, args[2].1), 4 => format!(r#" - fn method(self, arg1: {}, arg2: {}, arg3: {}, arg4: {}) -> Pin>> {{ + fn method(self, arg1: {}, arg2: {}, arg3: {}, arg4: {}) -> Pin + Sync + Send>> {{ (Self::methods().method)(self.into(), arg1, arg2, arg3, arg4) }} "#, args[0].1, args[1].1, args[2].1, args[3].1), diff --git a/minecraft-server/src/entities/entity.rs b/minecraft-server/src/entities/entity.rs index 87efbc0a..73684d2a 100644 --- a/minecraft-server/src/entities/entity.rs +++ b/minecraft-server/src/entities/entity.rs @@ -4,11 +4,12 @@ use super::*; inheritable, descendants { AbstractArrow..., Boat..., Display, FallingBlock, LlamaSpit, Painting, DragonFireball, Fireball..., FireworkRocket, SmallFireball, Interaction..., ItemEntity, ItemFrame..., LivingEntity... EndCrystal, EvokerFangs, WitherSkull, AreaEffectCloud, FishingHook, EyeOfEnder, ThrownItemProjectile... }, defines { - init(self); + init(self, server_msg_rcvr: BroadcastReceiver); } )] pub struct Entity { pub position: Position, + pub velocity: Position, pub pitch: f32, pub yaw: f32, pub is_on_fire: bool, @@ -28,8 +29,8 @@ pub struct Entity { } impl Handler { - async fn init(self) { - println!("Entity initialized"); + async fn init(self, server_msg_rcvr: BroadcastReceiver) { + self.insert_task("gravity", tokio::spawn(gravity_task(self.clone(), server_msg_rcvr))).await; } } @@ -37,6 +38,7 @@ impl Default for Entity { fn default() -> Self { Entity { position: Position { x: 0.0, y: 0.0, z: 0.0 }, + velocity: Position { x: 0.0, y: 0.0, z: 0.0 }, pitch: 0.0, yaw: 0.0, is_on_fire: false, diff --git a/minecraft-server/src/entities/mod.rs b/minecraft-server/src/entities/mod.rs index bf409e06..be07a9a8 100644 --- a/minecraft-server/src/entities/mod.rs +++ b/minecraft-server/src/entities/mod.rs @@ -33,6 +33,9 @@ pub use fire_entities::*; mod item; pub use item::*; +mod tasks; +pub use tasks::*; + pub use minecraft_positions::*; pub use minecraft_entities_derive::MinecraftEntity; pub use minecraft_protocol::{ @@ -50,15 +53,15 @@ use std::{pin::Pin, future::Future}; pub type Eid = u32; #[allow(dead_code)] -type CallBack = fn(O) -> Pin>>; +type CallBack = fn(O) -> Pin + Sync + Send>>; #[allow(dead_code)] -type CallBack1 = fn(O, I) -> Pin>>; +type CallBack1 = fn(O, I) -> Pin + Sync + Send>>; #[allow(dead_code)] -type CallBack2 = fn(O, I, J) -> Pin>>; +type CallBack2 = fn(O, I, J) -> Pin + Sync + Send>>; #[allow(dead_code)] -type CallBack3 = fn(O, I, J) -> Pin>>; +type CallBack3 = fn(O, I, J) -> Pin + Sync + Send>>; #[allow(dead_code)] -type CallBack4 = fn(O, I, J) -> Pin>>; +type CallBack4 = fn(O, I, J) -> Pin + Sync + Send>>; pub trait TryAsEntityRef { fn try_as_entity_ref(&self) -> Option<&T>; @@ -71,7 +74,17 @@ pub struct Handler where AnyEntity: TryAsEntityRef { entity: std::marker::PhantomData, } -impl Handler where AnyEntity: TryAsEntityRef { +impl Clone for Handler where AnyEntity: TryAsEntityRef { + fn clone(&self) -> Self { + Self { + eid: self.eid, + world: self.world, + entity: std::marker::PhantomData, + } + } +} + +impl Handler where AnyEntity: TryAsEntityRef { pub fn assume(id: Eid, world: &'static World) -> Self { Self { eid: id, @@ -94,7 +107,7 @@ impl Handler where AnyEntity: TryAsEntityRef { }).await } - pub async fn mutate(&self, mutator: impl FnOnce(&mut T) -> R) -> Option { + pub async fn mutate(&self, mutator: impl FnOnce(&mut T) -> (R, EntityChanges)) -> Option { self.world.mutate_entity(self.eid, move |entity| { mutator(entity.try_as_entity_mut().unwrap()) }).await diff --git a/minecraft-server/src/entities/tasks/gravity.rs b/minecraft-server/src/entities/tasks/gravity.rs new file mode 100644 index 00000000..d3df0e79 --- /dev/null +++ b/minecraft-server/src/entities/tasks/gravity.rs @@ -0,0 +1,18 @@ +use super::*; + +pub async fn gravity_task(h: Handler, mut server_msg_rcvr: BroadcastReceiver) where AnyEntity: TryAsEntityRef { + loop { + let msg = server_msg_rcvr.recv().await.unwrap(); + + if !matches!(&msg, &ServerMessage::Tick) { + continue; + } + + h.mutate(|entity| { + let entity = entity.get_entity_mut(); + entity.velocity.y -= 9.81/20.0; + entity.position += entity.velocity.clone(); + ((), EntityChanges::position()+EntityChanges::velocity()) + }).await; + } +} diff --git a/minecraft-server/src/entities/tasks/mod.rs b/minecraft-server/src/entities/tasks/mod.rs new file mode 100644 index 00000000..064cd8f6 --- /dev/null +++ b/minecraft-server/src/entities/tasks/mod.rs @@ -0,0 +1,4 @@ +pub use super::*; + +mod gravity; +pub use gravity::*; diff --git a/minecraft-server/src/player_handler/play.rs b/minecraft-server/src/player_handler/play.rs index df7b5088..d8d98403 100644 --- a/minecraft-server/src/player_handler/play.rs +++ b/minecraft-server/src/player_handler/play.rs @@ -10,6 +10,9 @@ struct PlayerHandler { on_ground: bool, packet_sender: MpscSender>, + // TODO: make this a hashmap + entity_prev_positions: HashMap, + render_distance: i32, loaded_chunks: HashSet, center_chunk: ChunkPosition, @@ -37,7 +40,8 @@ impl PlayerHandler { }).await; } - async fn on_entity_spawned(&mut self, eid: Eid, uuid: UUID, ty: NetworkEntity, position: Position, pitch: f32, yaw: f32, head_yaw: f32, data: u32, velocity: (), metadata: ()) { + async fn on_entity_spawned(&mut self, eid: Eid, uuid: UUID, ty: NetworkEntity, position: Position, pitch: f32, yaw: f32, head_yaw: f32, data: u32, velocity: Position, metadata: ()) { + self.entity_prev_positions.insert(eid, position.clone()); self.send_packet(PlayClientbound::SpawnEntity { id: VarInt(eid as i32), uuid, @@ -49,9 +53,29 @@ impl PlayerHandler { yaw: (yaw * (256.0 / 360.0)) as u8, head_yaw: (head_yaw * (256.0 / 360.0)) as u8, data: VarInt(data as i32), - velocity_x: 0, - velocity_y: 0, - velocity_z: 0, + velocity_x: (velocity.x * 8000.0) as i16, + velocity_y: (velocity.y * 8000.0) as i16, + velocity_z: (velocity.z * 8000.0) as i16, + }).await; + } + + async fn on_entity_moved(&mut self, eid: Eid, position: Position) { + let prev_position = self.entity_prev_positions.insert(eid, position.clone()).unwrap_or_else(|| position.clone()); + self.send_packet(PlayClientbound::UpdateEntityPosition { + entity_id: VarInt(eid as i32), + delta_x: (position.x * 4096.0 - prev_position.x * 4096.0) as i16, + delta_y: (position.y * 4096.0 - prev_position.y * 4096.0) as i16, + delta_z: (position.z * 4096.0 - prev_position.z * 4096.0) as i16, + on_ground: true, // TODO + }).await; + } + + async fn on_entity_velocity_changes(&mut self, eid: Eid, velocity: Position) { + self.send_packet(PlayClientbound::SetEntityVelocity { + entity_id: VarInt(eid as i32), + velocity_x: (velocity.x * 8000.0) as i16, + velocity_y: (velocity.y * 8000.0) as i16, + velocity_z: (velocity.z * 8000.0) as i16, }).await; } @@ -171,7 +195,9 @@ impl PlayerHandler { ChatMessage { message, .. } => { if message == "summon" { let mut zombie = Zombie::default(); - zombie.get_entity_mut().position = self.position.clone(); + let mut position = self.position.clone(); + position.y += 20.0; + zombie.get_entity_mut().position = position; self.world.spawn_entity(AnyEntity::Zombie(zombie)).await; } } @@ -192,6 +218,8 @@ pub async fn handle_player(stream: TcpStream, player_info: PlayerInfo, mut serve on_ground: false, packet_sender, + entity_prev_positions: HashMap::new(), + center_chunk: ChunkPosition { cx: 0, cy: 11, cz: 0 }, render_distance: player_info.render_distance.clamp(4, 15) as i32, loaded_chunks: HashSet::new(), @@ -254,7 +282,9 @@ pub async fn handle_player(stream: TcpStream, player_info: PlayerInfo, mut serve WorldChange::EntitySpawned { eid, uuid: uid, ty, position, pitch, yaw, head_yaw, data, velocity, metadata } => handler.on_entity_spawned(eid, uid, ty, position, pitch, yaw, head_yaw, data, velocity, metadata).await, WorldChange::EntityDispawned { eid } => todo!(), WorldChange::EntityMetadata { eid, metadata } => todo!(), - WorldChange::EntityMoved { eid, position, pitch, yaw, head_yaw } => todo!(), + WorldChange::EntityPosition { eid, position } => handler.on_entity_moved(eid, position).await, + WorldChange::EntityVelocity { eid, velocity } => handler.on_entity_velocity_changes(eid, velocity).await, + WorldChange::EntityPitch { eid, pitch, yaw, head_yaw } => todo!(), } }, Event::Message(Err(recv_error)) => { diff --git a/minecraft-server/src/server_behavior.rs b/minecraft-server/src/server_behavior.rs index 38e37d63..0a2a23eb 100644 --- a/minecraft-server/src/server_behavior.rs +++ b/minecraft-server/src/server_behavior.rs @@ -31,7 +31,7 @@ impl ServerBehavior { }); ServerBehavior { - world: Box::leak(Box::new(World::new())), + world: Box::leak(Box::new(World::new(receiver.resubscribe()))), listener, player_handlers: Vec::new(), message_receiver: receiver, diff --git a/minecraft-server/src/world/change.rs b/minecraft-server/src/world/change.rs new file mode 100644 index 00000000..49ba04ba --- /dev/null +++ b/minecraft-server/src/world/change.rs @@ -0,0 +1,87 @@ +use crate::prelude::*; + +#[derive(Debug, Clone)] +pub enum WorldChange { + Block(BlockPosition, BlockWithState), + EntitySpawned { + eid: Eid, + uuid: UUID, + ty: NetworkEntity, + position: Position, + pitch: f32, + yaw: f32, + head_yaw: f32, + data: u32, + velocity: Position, + metadata: (), + }, + EntityDispawned { + eid: Eid, + }, + EntityMetadata { + eid: Eid, + metadata: (), + }, + EntityPosition { + eid: Eid, + position: Position, + }, + EntityVelocity { + eid: Eid, + velocity: Position, + }, + EntityPitch { + eid: Eid, + pitch: f32, + yaw: f32, + head_yaw: f32, + }, +} + +pub struct EntityChanges(u8); + +impl EntityChanges { + pub const fn other() -> EntityChanges { + EntityChanges(0) + } + + pub const fn position() -> EntityChanges { + EntityChanges(1) + } + + pub const fn velocity() -> EntityChanges { + EntityChanges(1 << 1) + } + + pub const fn pitch() -> EntityChanges { + EntityChanges(1 << 2) + } + + pub const fn metadata() -> EntityChanges { + EntityChanges(1 << 3) + } + + pub fn has_position_changed(&self) -> bool { + self.0 & 1 != 0 + } + + pub fn has_velocity_changed(&self) -> bool { + self.0 & (1 << 1) != 0 + } + + pub fn has_pitch_changed(&self) -> bool { + self.0 & (1 << 2) != 0 + } + + pub fn has_metadata_changed(&self) -> bool { + self.0 & (1 << 3) != 0 + } +} + +impl std::ops::Add for EntityChanges { + type Output = EntityChanges; + + fn add(self, rhs: EntityChanges) -> EntityChanges { + EntityChanges(self.0 | rhs.0) + } +} diff --git a/minecraft-server/src/world/change_event.rs b/minecraft-server/src/world/change_event.rs deleted file mode 100644 index 86d41e53..00000000 --- a/minecraft-server/src/world/change_event.rs +++ /dev/null @@ -1,33 +0,0 @@ -use crate::prelude::*; - -#[derive(Debug, Clone)] -pub enum WorldChange { - Block(BlockPosition, BlockWithState), - EntitySpawned { - eid: Eid, - uuid: UUID, - ty: NetworkEntity, - position: Position, - pitch: f32, - yaw: f32, - head_yaw: f32, - data: u32, - velocity: (), - metadata: (), - }, - EntityDispawned { - eid: Eid, - }, - EntityMetadata { - eid: Eid, - metadata: (), - }, - // TODO packet without this - EntityMoved { - eid: Eid, - position: Position, - pitch: f32, - yaw: f32, - head_yaw: f32, - }, -} diff --git a/minecraft-server/src/world/ecs.rs b/minecraft-server/src/world/ecs.rs index 7b7643e0..d725bfe6 100644 --- a/minecraft-server/src/world/ecs.rs +++ b/minecraft-server/src/world/ecs.rs @@ -4,6 +4,7 @@ use minecraft_protocol::packets::UUID; use tokio::sync::RwLock; pub type EntityTask = Pin + Send + Sync + 'static>>; +pub type EntityTaskHandle = tokio::task::JoinHandle<()>; pub struct Entities { eid_counter: std::sync::atomic::AtomicU32, @@ -13,7 +14,7 @@ pub struct Entities { /// A hashmap of chunk positions to get a list of entities in a chunk pub chunks: RwLock>>, pub uuids: RwLock>, - pub entity_tasks: RwLock>>, + pub entity_tasks: RwLock>>, } impl Entities { @@ -34,7 +35,7 @@ impl Entities { } /// Mutate an entity through a closure - pub(super) async fn mutate_entity(&self, eid: Eid, mutator: impl FnOnce(&mut AnyEntity) -> R) -> Option { + pub(super) async fn mutate_entity(&self, eid: Eid, mutator: impl FnOnce(&mut AnyEntity) -> (R, EntityChanges)) -> Option<(R, EntityChanges)> { let mut entities = self.entities.write().await; if let Some(entity) = entities.get_mut(&eid) { @@ -45,8 +46,8 @@ impl Entities { let new_chunk = entity.as_entity().position.chunk(); drop(entities); let mut chunks = self.chunks.write().await; - chunks.get_mut(&old_chunk).unwrap().remove(&eid); - chunks.get_mut(&new_chunk).unwrap().insert(eid); + chunks.entry(old_chunk).and_modify(|set| { set.remove(&eid); }); // TODO: ensure it gets removed + chunks.entry(new_chunk).or_insert(HashSet::new()).insert(eid); } Some(r) } else { @@ -54,7 +55,7 @@ impl Entities { } } - pub(super) async fn spawn_entity(&self, entity: AnyEntity) -> (Eid, UUID) { + pub(super) async fn spawn_entity(&self, entity: AnyEntity, world: &'static World, receiver: BroadcastReceiver) -> (Eid, UUID) { let eid = self.eid_counter.fetch_add(1, std::sync::atomic::Ordering::SeqCst); let uuid = self.uuid_counter.fetch_add(1, std::sync::atomic::Ordering::SeqCst) as u128; let mut entities = self.entities.write().await; @@ -63,11 +64,20 @@ impl Entities { chunks.entry(entity.as_entity().position.chunk()).or_insert(HashSet::new()).insert(eid); entities.insert(eid, entity); uuids.insert(uuid, eid); + drop(entities); + drop(chunks); + drop(uuids); + let h = Handler::::assume(eid, world); // TODO other than zombie + h.init(receiver).await; (eid, uuid) } - pub async fn insert_entity_task(&self, eid: Eid, name: &'static str, task: EntityTask) { - self.entity_tasks.write().await.entry(eid).or_insert(HashMap::new()).insert(name, task); + pub(super) async fn insert_entity_task(&self, eid: Eid, name: &'static str, handle: EntityTaskHandle) { + let mut entity_tasks = self.entity_tasks.write().await; + let old = entity_tasks.entry(eid).or_insert(HashMap::new()).insert(name, handle); + if let Some(old) = old { + old.abort(); + } } /// Remove an entity @@ -84,7 +94,7 @@ impl Entities { } impl Handler where AnyEntity: TryAsEntityRef { - async fn insert_task(&self, name: &'static str, task: EntityTask) { - self.world.entities.insert_entity_task(self.eid, name, task).await; + pub async fn insert_task(&self, name: &'static str, handle: EntityTaskHandle) { + self.world.entities.insert_entity_task(self.eid, name, handle).await; } } diff --git a/minecraft-server/src/world/mod.rs b/minecraft-server/src/world/mod.rs index db919a08..de90410f 100644 --- a/minecraft-server/src/world/mod.rs +++ b/minecraft-server/src/world/mod.rs @@ -1,7 +1,7 @@ use crate::prelude::*; -mod change_event; -pub use change_event::*; +mod change; +pub use change::*; mod loading_manager; use loading_manager::*; mod map; @@ -18,15 +18,17 @@ pub struct World { loading_manager: RwLock, change_senders: RwLock>>, + receiver: BroadcastReceiver, } impl World { - pub fn new() -> World { + pub fn new(receiver: BroadcastReceiver) -> World { World { map: WorldMap::new(4), entities: Entities::new(), loading_manager: RwLock::new(WorldLoadingManager::default()), change_senders: RwLock::new(HashMap::new()), + receiver, } } @@ -69,13 +71,14 @@ impl World { } } - pub async fn spawn_entity(&self, entity: AnyEntity) -> Eid { + pub async fn spawn_entity(&'static self, entity: AnyEntity) -> Eid { let position = entity.as_entity().position.clone(); + let velocity = entity.as_entity().velocity.clone(); let ty = entity.to_network().unwrap(); // TODO: error handling let pitch = entity.as_entity().pitch; let yaw = entity.as_entity().yaw; let head_yaw = entity.as_other::().map(|e| e.head_yaw).unwrap_or(0.0); - let (eid, uuid) = self.entities.spawn_entity(entity).await; + let (eid, uuid) = self.entities.spawn_entity(entity, self, self.receiver.resubscribe()).await; self.notify(&position.chunk_column(), WorldChange::EntitySpawned { eid, uuid, @@ -85,7 +88,7 @@ impl World { yaw, head_yaw, data: 0, - velocity: (), + velocity, metadata: (), }).await; eid @@ -95,9 +98,41 @@ impl World { self.entities.observe_entity(eid, observer).await } - pub async fn mutate_entity(&self, eid: Eid, mutator: impl FnOnce(&mut AnyEntity) -> R) -> Option { + pub async fn mutate_entity(&self, eid: Eid, mutator: impl FnOnce(&mut AnyEntity) -> (R, EntityChanges)) -> Option { // TODO change events - self.entities.mutate_entity(eid, mutator).await + match self.entities.mutate_entity(eid, mutator).await { + Some((r, changes)) => { + // TODO: make only one lookup and group into a single message with optional fields + let position = self.entities.observe_entity(eid, |e| e.as_entity().position.clone()).await?; + if changes.has_position_changed() { + self.notify(&position.chunk_column(), WorldChange::EntityPosition { + eid, + position: position.clone(), + }).await; + } + if changes.has_velocity_changed() { + let velocity = self.entities.observe_entity(eid, |e| e.as_entity().velocity.clone()).await?; + self.notify(&position.chunk_column(), WorldChange::EntityVelocity { + eid, + velocity, + }).await; + } + if changes.has_pitch_changed() { + let (pitch, yaw, head_yaw) = self.entities.observe_entity(eid, |e| (e.as_entity().pitch, e.as_entity().yaw, e.as_other::().map(|e| e.head_yaw).unwrap_or(0.0))).await?; + self.notify(&position.chunk_column(), WorldChange::EntityPitch { + eid, + pitch, + yaw, + head_yaw, + }).await; + } + if changes.has_metadata_changed() { + todo!() + } + Some(r) + }, + None => None, + } } async fn notify(&self, position: &ChunkColumnPosition, change: WorldChange) { @@ -119,7 +154,7 @@ mod tests { #[tokio::test] async fn test_world_notifications() { - let world = World::new(); + let world = World::new(broadcast_channel(100).1); let mut receiver1 = world.add_loader(1).await; let mut receiver2 = world.add_loader(2).await; From fef36c64a90f6de0cfcdb33366347ad8571f21be Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sun, 12 Nov 2023 00:01:56 +0100 Subject: [PATCH 60/89] Fix example --- minecraft-entities-derive/examples/main.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/minecraft-entities-derive/examples/main.rs b/minecraft-entities-derive/examples/main.rs index b87426f4..c20ef6f4 100644 --- a/minecraft-entities-derive/examples/main.rs +++ b/minecraft-entities-derive/examples/main.rs @@ -1,9 +1,9 @@ use minecraft_entities_derive::*; use std::{pin::Pin, future::Future, sync::{Mutex, Arc}}; -type CallBack = fn(O) -> Pin>>; -type CallBack1 = fn(O, I) -> Pin>>; -type CallBack2 = fn(O, I, J) -> Pin>>; +type CallBack = fn(O) -> Pin + Sync + Send>>; +type CallBack1 = fn(O, I) -> Pin + Sync + Send>>; +type CallBack2 = fn(O, I, J) -> Pin + Sync + Send>>; type Eid = u32; trait TryAsEntityRef { @@ -11,11 +11,6 @@ trait TryAsEntityRef { fn try_as_entity_mut(&mut self) -> Option<&mut T>; } -trait WorldTest { - fn observe_entity(&self, eid: Eid, observer: fn(&AnyEntity)) -> dyn std::future::Future; - fn mutate_entity(&self, eid: Eid, mutator: fn(&mut AnyEntity)) -> dyn std::future::Future; -} - enum AnyEntity { Entity(Entity), Animal(Animal), From 9722729d3779db36543f6d715a499215250bc2e7 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sun, 12 Nov 2023 00:43:04 +0100 Subject: [PATCH 61/89] Run TODO to Issue --- .github/workflows/todo.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .github/workflows/todo.yml diff --git a/.github/workflows/todo.yml b/.github/workflows/todo.yml new file mode 100644 index 00000000..4affcc8d --- /dev/null +++ b/.github/workflows/todo.yml @@ -0,0 +1,11 @@ +name: "Run TODO to Issue" +on: ["push"] +jobs: + build: + runs-on: "ubuntu-latest" + steps: + - uses: "actions/checkout@v3" + - name: "TODO to Issue" + uses: "alstr/todo-to-issue-action@v4" + with: + IDENTIFIERS: '[{"name": "TODO", "labels": []}, {"name": "FIXME", "labels": ["bug"]}]' From 018e09977e69cf219a8f7a06f39c2d467b348e66 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sun, 12 Nov 2023 03:13:16 +0100 Subject: [PATCH 62/89] Implement collision detection --- minecraft-server/src/main.rs | 154 ++++++++++++++++++++++++++++++++++- 1 file changed, 151 insertions(+), 3 deletions(-) diff --git a/minecraft-server/src/main.rs b/minecraft-server/src/main.rs index db0828d8..0be1e3b6 100644 --- a/minecraft-server/src/main.rs +++ b/minecraft-server/src/main.rs @@ -8,9 +8,6 @@ mod entities; use crate::prelude::*; -struct Map { - -} fn min(a: f32, b: f32, c: f32) -> f32 { fn min2(a: f32, b: f32) -> f32 { @@ -23,6 +20,157 @@ fn min(a: f32, b: f32, c: f32) -> f32 { min2(min2(a, b), c) } +fn min_options(a: Option, b: Option, c: Option) -> Option { + match (a, b, c) { + (Some(a), Some(b), Some(c)) => Some(min(a, b, c)), + (Some(a), Some(b), None) => Some(min(a, b, 1.0)), + (Some(a), None, Some(c)) => Some(min(a, 1.0, c)), + (None, Some(b), Some(c)) => Some(min(1.0, b, c)), + (Some(a), None, None) => Some(a), + (None, Some(b), None) => Some(b), + (None, None, Some(c)) => Some(c), + (None, None, None) => None, + } +} + +fn min_options2(a: Option, b: Option) -> Option { + match (a, b) { + (Some(a), Some(b)) => Some(min(a, b, 1.0)), + (Some(a), None) => Some(a), + (None, Some(b)) => Some(b), + (None, None) => None, + } +} + +struct CollisionShape { + x1: f32, + y1: f32, + z1: f32, + x2: f32, + y2: f32, + z2: f32, +} + +struct Point { + x: f32, + y: f32, + z: f32, +} + +struct PointIter<'a> { + shape: &'a CollisionShape, + index: usize, +} + +impl<'a> Iterator for PointIter<'a> { + type Item = Point; + + fn next(&mut self) -> Option { + if self.index < 8 { + let result = Point { + x: if self.index & 1 == 0 { self.shape.x1 } else { self.shape.x2 }, + y: if self.index & 2 == 0 { self.shape.y1 } else { self.shape.y2 }, + z: if self.index & 4 == 0 { self.shape.z1 } else { self.shape.z2 }, + }; + Some(result) + } else { + None + } + } +} + +impl CollisionShape { + const fn points(&self) -> PointIter { + PointIter { + shape: self, + index: 0, + } + } +} + +struct Translation { + x: f32, + y: f32, + z: f32, +} + +fn is_inside(shape: &CollisionShape, point: Point) -> bool { + (shape.x1..=shape.x2).contains(&point.x) && (shape.y1..=shape.y2).contains(&point.y) && (shape.z1..=shape.z2).contains(&point.z) +} + +fn translation_limit_y(shape: &CollisionShape, translation: &Translation, point: &Point) -> Option { + let y = if translation.y < 0.0 { shape.y1 } else { shape.y2 }; + let translated_ratio = (y - shape.y1) / translation.y; + if !(0.0..=1.0).contains(&translated_ratio) { + return None; + } + let translated_x1 = shape.x1 + (shape.x2 - shape.x1) * translated_ratio; + let translated_x2 = shape.x2 + (shape.x2 - shape.x1) * translated_ratio; + let translated_z1 = shape.z1 + (shape.z2 - shape.z1) * translated_ratio; + let translated_z2 = shape.z2 + (shape.z2 - shape.z1) * translated_ratio; + if (translated_x1..=translated_x2).contains(&point.x) && (translated_z1..=translated_z2).contains(&point.z) { + Some(translated_ratio) + } else { + None + } +} + +fn translation_limit_x(shape: &CollisionShape, translation: &Translation, point: &Point) -> Option { + let x = if translation.x < 0.0 { shape.x1 } else { shape.x2 }; + let translated_ratio = (x - shape.x1) / translation.x; + if !(0.0..=1.0).contains(&translated_ratio) { + return None; + } + let translated_y1 = shape.y1 + (shape.y2 - shape.y1) * translated_ratio; + let translated_y2 = shape.y2 + (shape.y2 - shape.y1) * translated_ratio; + let translated_z1 = shape.z1 + (shape.z2 - shape.z1) * translated_ratio; + let translated_z2 = shape.z2 + (shape.z2 - shape.z1) * translated_ratio; + if (translated_y1..=translated_y2).contains(&point.y) && (translated_z1..=translated_z2).contains(&point.z) { + Some(translated_ratio) + } else { + None + } +} + +fn translation_limit_z(shape: &CollisionShape, translation: &Translation, point: &Point) -> Option { + let z = if translation.z < 0.0 { shape.z1 } else { shape.z2 }; + let translated_ratio = (z - shape.z1) / translation.z; + if !(0.0..=1.0).contains(&translated_ratio) { + return None; + } + let translated_x1 = shape.x1 + (shape.x2 - shape.x1) * translated_ratio; + let translated_x2 = shape.x2 + (shape.x2 - shape.x1) * translated_ratio; + let translated_y1 = shape.y1 + (shape.y2 - shape.y1) * translated_ratio; + let translated_y2 = shape.y2 + (shape.y2 - shape.y1) * translated_ratio; + if (translated_x1..=translated_x2).contains(&point.x) && (translated_y1..=translated_y2).contains(&point.y) { + Some(translated_ratio) + } else { + None + } +} + +fn translation_limit(shape: &CollisionShape, translation: &Translation, point: &Point) -> Option { + min_options( + translation_limit_x(shape, translation, point), + translation_limit_y(shape, translation, point), + translation_limit_z(shape, translation, point) + ) +} + +fn collide(translating: CollisionShape, translation: Translation, obstacle: CollisionShape) -> Option { + let mut limit = None; + + for point in obstacle.points() { + limit = min_options2(limit, translation_limit(&translating, &translation, &point)); + } + + limit.map(|limit| Translation { + x: translation.x * limit, + y: translation.y * limit, + z: translation.z * limit, + }) +} + fn ray_cast(position: (f32, f32, f32), movement: (f32, f32, f32)) -> Vec<(isize, isize, isize)> { let final_position = ((position.0+movement.0) as isize, (position.1+movement.1) as isize, (position.2+movement.2) as isize); let mut result = Vec::new(); From c52b94400a704f471ac97243f399d24069fa1c13 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Mon, 13 Nov 2023 00:40:41 +0100 Subject: [PATCH 63/89] Fix algorithm --- minecraft-server/src/main.rs | 87 +++++++++++++++++++++++++++++------- 1 file changed, 71 insertions(+), 16 deletions(-) diff --git a/minecraft-server/src/main.rs b/minecraft-server/src/main.rs index 0be1e3b6..23b356d3 100644 --- a/minecraft-server/src/main.rs +++ b/minecraft-server/src/main.rs @@ -42,6 +42,7 @@ fn min_options2(a: Option, b: Option) -> Option { } } +#[derive(Debug, Clone, PartialEq)] struct CollisionShape { x1: f32, y1: f32, @@ -72,6 +73,7 @@ impl<'a> Iterator for PointIter<'a> { y: if self.index & 2 == 0 { self.shape.y1 } else { self.shape.y2 }, z: if self.index & 4 == 0 { self.shape.z1 } else { self.shape.z2 }, }; + self.index += 1; Some(result) } else { None @@ -88,26 +90,54 @@ impl CollisionShape { } } +#[derive(Debug, Clone, PartialEq)] struct Translation { x: f32, y: f32, z: f32, } +impl std::ops::Add for Translation { + type Output = Translation; + + fn add(self, rhs: Translation) -> Self::Output { + Translation { + x: self.x + rhs.x, + y: self.y + rhs.y, + z: self.z + rhs.z, + } + } +} + +impl std::ops::Add for CollisionShape { + type Output = CollisionShape; + + fn add(self, rhs: Translation) -> Self::Output { + CollisionShape { + x1: self.x1 + rhs.x, + y1: self.y1 + rhs.y, + z1: self.z1 + rhs.z, + x2: self.x2 + rhs.x, + y2: self.y2 + rhs.y, + z2: self.z2 + rhs.z, + } + } +} + fn is_inside(shape: &CollisionShape, point: Point) -> bool { (shape.x1..=shape.x2).contains(&point.x) && (shape.y1..=shape.y2).contains(&point.y) && (shape.z1..=shape.z2).contains(&point.z) } fn translation_limit_y(shape: &CollisionShape, translation: &Translation, point: &Point) -> Option { let y = if translation.y < 0.0 { shape.y1 } else { shape.y2 }; - let translated_ratio = (y - shape.y1) / translation.y; + let translated_ratio = (point.y - y) / translation.y; if !(0.0..=1.0).contains(&translated_ratio) { return None; } - let translated_x1 = shape.x1 + (shape.x2 - shape.x1) * translated_ratio; - let translated_x2 = shape.x2 + (shape.x2 - shape.x1) * translated_ratio; - let translated_z1 = shape.z1 + (shape.z2 - shape.z1) * translated_ratio; - let translated_z2 = shape.z2 + (shape.z2 - shape.z1) * translated_ratio; + let translated_x1 = shape.x1 + translation.x * translated_ratio; + let translated_x2 = shape.x2 + translation.x * translated_ratio; + let translated_z1 = shape.z1 + translation.z * translated_ratio; + let translated_z2 = shape.z2 + translation.z * translated_ratio; if (translated_x1..=translated_x2).contains(&point.x) && (translated_z1..=translated_z2).contains(&point.z) { Some(translated_ratio) } else { @@ -117,14 +147,14 @@ fn translation_limit_y(shape: &CollisionShape, translation: &Translation, point: fn translation_limit_x(shape: &CollisionShape, translation: &Translation, point: &Point) -> Option { let x = if translation.x < 0.0 { shape.x1 } else { shape.x2 }; - let translated_ratio = (x - shape.x1) / translation.x; + let translated_ratio = (point.x - x) / translation.x; if !(0.0..=1.0).contains(&translated_ratio) { return None; } - let translated_y1 = shape.y1 + (shape.y2 - shape.y1) * translated_ratio; - let translated_y2 = shape.y2 + (shape.y2 - shape.y1) * translated_ratio; - let translated_z1 = shape.z1 + (shape.z2 - shape.z1) * translated_ratio; - let translated_z2 = shape.z2 + (shape.z2 - shape.z1) * translated_ratio; + let translated_y1 = shape.y1 + translation.y * translated_ratio; + let translated_y2 = shape.y2 + translation.y * translated_ratio; + let translated_z1 = shape.z1 + translation.z * translated_ratio; + let translated_z2 = shape.z2 + translation.z * translated_ratio; if (translated_y1..=translated_y2).contains(&point.y) && (translated_z1..=translated_z2).contains(&point.z) { Some(translated_ratio) } else { @@ -134,14 +164,14 @@ fn translation_limit_x(shape: &CollisionShape, translation: &Translation, point: fn translation_limit_z(shape: &CollisionShape, translation: &Translation, point: &Point) -> Option { let z = if translation.z < 0.0 { shape.z1 } else { shape.z2 }; - let translated_ratio = (z - shape.z1) / translation.z; + let translated_ratio = (point.z - z) / translation.z; if !(0.0..=1.0).contains(&translated_ratio) { return None; } - let translated_x1 = shape.x1 + (shape.x2 - shape.x1) * translated_ratio; - let translated_x2 = shape.x2 + (shape.x2 - shape.x1) * translated_ratio; - let translated_y1 = shape.y1 + (shape.y2 - shape.y1) * translated_ratio; - let translated_y2 = shape.y2 + (shape.y2 - shape.y1) * translated_ratio; + let translated_x1 = shape.x1 + translation.x * translated_ratio; + let translated_x2 = shape.x2 + translation.x * translated_ratio; + let translated_y1 = shape.y1 + translation.y * translated_ratio; + let translated_y2 = shape.y2 + translation.y * translated_ratio; if (translated_x1..=translated_x2).contains(&point.x) && (translated_y1..=translated_y2).contains(&point.y) { Some(translated_ratio) } else { @@ -157,11 +187,14 @@ fn translation_limit(shape: &CollisionShape, translation: &Translation, point: & ) } -fn collide(translating: CollisionShape, translation: Translation, obstacle: CollisionShape) -> Option { +fn collide(translating: &CollisionShape, translation: &Translation, obstacle: &CollisionShape) -> Option { let mut limit = None; for point in obstacle.points() { limit = min_options2(limit, translation_limit(&translating, &translation, &point)); + if limit.map(|l| l==0.0).unwrap_or(false) { + break; + } } limit.map(|limit| Translation { @@ -171,6 +204,28 @@ fn collide(translating: CollisionShape, translation: Translation, obstacle: Coll }) } +#[test] +fn test() { + let shape1 = CollisionShape { + x1: 0.0, + y1: 0.0, + z1: 0.0, + x2: 1.0, + y2: 1.0, + z2: 1.0, + }; + + // Boxes are just next to each other and pushing against each other + let shape2 = shape1.clone() + Translation { x: 1.0, y: 0.0, z: 0.0 }; + let translation = Translation { x: -1.0, y: 0.0, z: 0.0 }; + assert_eq!(collide(&shape2, &translation, &shape1), Some(Translation { x: 0.0, y: 0.0, z: 0.0 })); + + // Boxes are one block away but one comes and pushes the other + let shape2 = shape1.clone() + Translation { x: 2.0, y: 0.0, z: 0.0 }; + let translation = Translation { x: -2.0, y: 0.0, z: 0.0 }; + assert_eq!(collide(&shape2, &translation, &shape1), Some(Translation { x: -1.0, y: 0.0, z: 0.0 })); +} + fn ray_cast(position: (f32, f32, f32), movement: (f32, f32, f32)) -> Vec<(isize, isize, isize)> { let final_position = ((position.0+movement.0) as isize, (position.1+movement.1) as isize, (position.2+movement.2) as isize); let mut result = Vec::new(); From 91acc4015d6147f7e32fe00e78d8534b09b245ad Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Mon, 13 Nov 2023 00:42:22 +0100 Subject: [PATCH 64/89] Add test case --- minecraft-server/src/main.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/minecraft-server/src/main.rs b/minecraft-server/src/main.rs index 23b356d3..c8b88845 100644 --- a/minecraft-server/src/main.rs +++ b/minecraft-server/src/main.rs @@ -224,6 +224,11 @@ fn test() { let shape2 = shape1.clone() + Translation { x: 2.0, y: 0.0, z: 0.0 }; let translation = Translation { x: -2.0, y: 0.0, z: 0.0 }; assert_eq!(collide(&shape2, &translation, &shape1), Some(Translation { x: -1.0, y: 0.0, z: 0.0 })); + + // The other way around + let shape2 = shape1.clone() + Translation { x: -2.0, y: 0.0, z: 0.0 }; + let translation = Translation { x: 2.0, y: 0.0, z: 0.0 }; + assert_eq!(collide(&shape2, &translation, &shape1), Some(Translation { x: 1.0, y: 0.0, z: 0.0 })); } fn ray_cast(position: (f32, f32, f32), movement: (f32, f32, f32)) -> Vec<(isize, isize, isize)> { From c67a94ded6b68470592411eab3f01d9aac53aa0d Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Mon, 13 Nov 2023 00:43:44 +0100 Subject: [PATCH 65/89] Add test cases --- minecraft-server/src/main.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/minecraft-server/src/main.rs b/minecraft-server/src/main.rs index c8b88845..4999f618 100644 --- a/minecraft-server/src/main.rs +++ b/minecraft-server/src/main.rs @@ -229,6 +229,16 @@ fn test() { let shape2 = shape1.clone() + Translation { x: -2.0, y: 0.0, z: 0.0 }; let translation = Translation { x: 2.0, y: 0.0, z: 0.0 }; assert_eq!(collide(&shape2, &translation, &shape1), Some(Translation { x: 1.0, y: 0.0, z: 0.0 })); + + // From top + let shape2 = shape1.clone() + Translation { x: 0.0, y: 2.0, z: 0.0 }; + let translation = Translation { x: 0.0, y: -2.0, z: 0.0 }; + assert_eq!(collide(&shape2, &translation, &shape1), Some(Translation { x: 0.0, y: -1.0, z: 0.0 })); + + // On last axis + let shape2 = shape1.clone() + Translation { x: 0.0, y: 0.0, z: 2.0 }; + let translation = Translation { x: 0.0, y: 0.0, z: -2.0 }; + assert_eq!(collide(&shape2, &translation, &shape1), Some(Translation { x: 0.0, y: 0.0, z: -1.0 })); } fn ray_cast(position: (f32, f32, f32), movement: (f32, f32, f32)) -> Vec<(isize, isize, isize)> { From aeb796320e632acf21e2322ec52af349284cd94c Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Mon, 13 Nov 2023 00:46:24 +0100 Subject: [PATCH 66/89] Add test cases --- minecraft-server/src/main.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/minecraft-server/src/main.rs b/minecraft-server/src/main.rs index 4999f618..e305889b 100644 --- a/minecraft-server/src/main.rs +++ b/minecraft-server/src/main.rs @@ -239,6 +239,21 @@ fn test() { let shape2 = shape1.clone() + Translation { x: 0.0, y: 0.0, z: 2.0 }; let translation = Translation { x: 0.0, y: 0.0, z: -2.0 }; assert_eq!(collide(&shape2, &translation, &shape1), Some(Translation { x: 0.0, y: 0.0, z: -1.0 })); + + // Colliding on corner + let shape2 = shape1.clone() + Translation { x: 2.0, y: 2.0, z: 2.0 }; + let translation = Translation { x: -2.0, y: -2.0, z: -2.0 }; + assert_eq!(collide(&shape2, &translation, &shape1), Some(Translation { x: -1.0, y: -1.0, z: -1.0 })); + + // Colliding with offset on other axis + let shape2 = shape1.clone() + Translation { x: 2.0, y: 0.5, z: 0.0 }; + let translation = Translation { x: -2.0, y: 0.0, z: 0.0 }; + assert_eq!(collide(&shape2, &translation, &shape1), Some(Translation { x: -1.0, y: 0.0, z: 0.0 })); + + // Colliding when already inside + //let shape2 = shape1.clone() + Translation { x: 0.5, y: 0.5, z: 0.5 }; + //let translation = Translation { x: -0.5, y: -0.5, z: -0.5 }; + //assert_eq!(collide(&shape2, &translation, &shape1), Some(Translation { x: 0.0, y: 0.0, z: 0.0 })); } fn ray_cast(position: (f32, f32, f32), movement: (f32, f32, f32)) -> Vec<(isize, isize, isize)> { From f34d1f9b536df0fb9ce0fee5784d75c9829a9c4b Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Mon, 13 Nov 2023 13:13:42 +0100 Subject: [PATCH 67/89] Fix issue --- minecraft-server/src/main.rs | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/minecraft-server/src/main.rs b/minecraft-server/src/main.rs index e305889b..98f52705 100644 --- a/minecraft-server/src/main.rs +++ b/minecraft-server/src/main.rs @@ -129,10 +129,15 @@ fn is_inside(shape: &CollisionShape, point: Point) -> bool { } fn translation_limit_y(shape: &CollisionShape, translation: &Translation, point: &Point) -> Option { + if translation.y == 0.0 { + return None; + } let y = if translation.y < 0.0 { shape.y1 } else { shape.y2 }; let translated_ratio = (point.y - y) / translation.y; - if !(0.0..=1.0).contains(&translated_ratio) { + if translated_ratio >= 1.0 { return None; + } else if translated_ratio <= 0.0 { + return Some(0.0) } let translated_x1 = shape.x1 + translation.x * translated_ratio; let translated_x2 = shape.x2 + translation.x * translated_ratio; @@ -146,10 +151,15 @@ fn translation_limit_y(shape: &CollisionShape, translation: &Translation, point: } fn translation_limit_x(shape: &CollisionShape, translation: &Translation, point: &Point) -> Option { + if translation.x == 0.0 { + return None; + } let x = if translation.x < 0.0 { shape.x1 } else { shape.x2 }; let translated_ratio = (point.x - x) / translation.x; - if !(0.0..=1.0).contains(&translated_ratio) { + if translated_ratio >= 1.0 { return None; + } else if translated_ratio <= 0.0 { + return Some(0.0) } let translated_y1 = shape.y1 + translation.y * translated_ratio; let translated_y2 = shape.y2 + translation.y * translated_ratio; @@ -163,10 +173,15 @@ fn translation_limit_x(shape: &CollisionShape, translation: &Translation, point: } fn translation_limit_z(shape: &CollisionShape, translation: &Translation, point: &Point) -> Option { + if translation.z == 0.0 { + return None; + } let z = if translation.z < 0.0 { shape.z1 } else { shape.z2 }; let translated_ratio = (point.z - z) / translation.z; - if !(0.0..=1.0).contains(&translated_ratio) { + if translated_ratio >= 1.0 { return None; + } else if translated_ratio <= 0.0 { + return Some(0.0) } let translated_x1 = shape.x1 + translation.x * translated_ratio; let translated_x2 = shape.x2 + translation.x * translated_ratio; @@ -191,7 +206,7 @@ fn collide(translating: &CollisionShape, translation: &Translation, obstacle: &C let mut limit = None; for point in obstacle.points() { - limit = min_options2(limit, translation_limit(&translating, &translation, &point)); + limit = min_options2(limit, translation_limit(translating, translation, &point)); if limit.map(|l| l==0.0).unwrap_or(false) { break; } @@ -251,9 +266,9 @@ fn test() { assert_eq!(collide(&shape2, &translation, &shape1), Some(Translation { x: -1.0, y: 0.0, z: 0.0 })); // Colliding when already inside - //let shape2 = shape1.clone() + Translation { x: 0.5, y: 0.5, z: 0.5 }; - //let translation = Translation { x: -0.5, y: -0.5, z: -0.5 }; - //assert_eq!(collide(&shape2, &translation, &shape1), Some(Translation { x: 0.0, y: 0.0, z: 0.0 })); + let shape2 = shape1.clone() + Translation { x: 0.5, y: 0.5, z: 0.5 }; + let translation = Translation { x: -0.5, y: -0.5, z: -0.5 }; + assert_eq!(collide(&shape2, &translation, &shape1), Some(Translation { x: 0.0, y: 0.0, z: 0.0 })); } fn ray_cast(position: (f32, f32, f32), movement: (f32, f32, f32)) -> Vec<(isize, isize, isize)> { From 9be187123704eae555a5c1eb3b2df8531d483afa Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Mon, 13 Nov 2023 13:23:02 +0100 Subject: [PATCH 68/89] Optimization --- minecraft-server/src/main.rs | 123 +++++++++++++++++------------------ 1 file changed, 58 insertions(+), 65 deletions(-) diff --git a/minecraft-server/src/main.rs b/minecraft-server/src/main.rs index 98f52705..042d8205 100644 --- a/minecraft-server/src/main.rs +++ b/minecraft-server/src/main.rs @@ -8,29 +8,16 @@ mod entities; use crate::prelude::*; - -fn min(a: f32, b: f32, c: f32) -> f32 { - fn min2(a: f32, b: f32) -> f32 { - if a < b { - a - } else { - b - } +fn min2(a: f32, b: f32) -> f32 { + if a < b { + a + } else { + b } - min2(min2(a, b), c) } -fn min_options(a: Option, b: Option, c: Option) -> Option { - match (a, b, c) { - (Some(a), Some(b), Some(c)) => Some(min(a, b, c)), - (Some(a), Some(b), None) => Some(min(a, b, 1.0)), - (Some(a), None, Some(c)) => Some(min(a, 1.0, c)), - (None, Some(b), Some(c)) => Some(min(1.0, b, c)), - (Some(a), None, None) => Some(a), - (None, Some(b), None) => Some(b), - (None, None, Some(c)) => Some(c), - (None, None, None) => None, - } +fn min(a: f32, b: f32, c: f32) -> f32 { + min2(min2(a, b), c) } fn min_options2(a: Option, b: Option) -> Option { @@ -128,95 +115,93 @@ fn is_inside(shape: &CollisionShape, point: Point) -> bool { (shape.x1..=shape.x2).contains(&point.x) && (shape.y1..=shape.y2).contains(&point.y) && (shape.z1..=shape.z2).contains(&point.z) } -fn translation_limit_y(shape: &CollisionShape, translation: &Translation, point: &Point) -> Option { +fn translation_limit_y(shape: &CollisionShape, translation: &Translation, point: &Point) -> f32 { if translation.y == 0.0 { - return None; + return 1.0; } let y = if translation.y < 0.0 { shape.y1 } else { shape.y2 }; let translated_ratio = (point.y - y) / translation.y; if translated_ratio >= 1.0 { - return None; + return 1.0; } else if translated_ratio <= 0.0 { - return Some(0.0) + return 0.0; } let translated_x1 = shape.x1 + translation.x * translated_ratio; let translated_x2 = shape.x2 + translation.x * translated_ratio; let translated_z1 = shape.z1 + translation.z * translated_ratio; let translated_z2 = shape.z2 + translation.z * translated_ratio; if (translated_x1..=translated_x2).contains(&point.x) && (translated_z1..=translated_z2).contains(&point.z) { - Some(translated_ratio) + translated_ratio } else { - None + 1.0 } } -fn translation_limit_x(shape: &CollisionShape, translation: &Translation, point: &Point) -> Option { +fn translation_limit_x(shape: &CollisionShape, translation: &Translation, point: &Point) -> f32 { if translation.x == 0.0 { - return None; + return 1.0; } let x = if translation.x < 0.0 { shape.x1 } else { shape.x2 }; let translated_ratio = (point.x - x) / translation.x; if translated_ratio >= 1.0 { - return None; + return 1.0; } else if translated_ratio <= 0.0 { - return Some(0.0) + return 0.0; } let translated_y1 = shape.y1 + translation.y * translated_ratio; let translated_y2 = shape.y2 + translation.y * translated_ratio; let translated_z1 = shape.z1 + translation.z * translated_ratio; let translated_z2 = shape.z2 + translation.z * translated_ratio; if (translated_y1..=translated_y2).contains(&point.y) && (translated_z1..=translated_z2).contains(&point.z) { - Some(translated_ratio) + translated_ratio } else { - None + 1.0 } } -fn translation_limit_z(shape: &CollisionShape, translation: &Translation, point: &Point) -> Option { +fn translation_limit_z(shape: &CollisionShape, translation: &Translation, point: &Point) -> f32 { if translation.z == 0.0 { - return None; + return 1.0; } let z = if translation.z < 0.0 { shape.z1 } else { shape.z2 }; let translated_ratio = (point.z - z) / translation.z; if translated_ratio >= 1.0 { - return None; + return 1.0; } else if translated_ratio <= 0.0 { - return Some(0.0) + return 0.0; } let translated_x1 = shape.x1 + translation.x * translated_ratio; let translated_x2 = shape.x2 + translation.x * translated_ratio; let translated_y1 = shape.y1 + translation.y * translated_ratio; let translated_y2 = shape.y2 + translation.y * translated_ratio; if (translated_x1..=translated_x2).contains(&point.x) && (translated_y1..=translated_y2).contains(&point.y) { - Some(translated_ratio) + translated_ratio } else { - None + 1.0 } } -fn translation_limit(shape: &CollisionShape, translation: &Translation, point: &Point) -> Option { - min_options( +fn translation_limit(shape: &CollisionShape, translation: &Translation, point: &Point) -> f32 { + min( translation_limit_x(shape, translation, point), translation_limit_y(shape, translation, point), translation_limit_z(shape, translation, point) ) } -fn collide(translating: &CollisionShape, translation: &Translation, obstacle: &CollisionShape) -> Option { - let mut limit = None; +fn restrict(translating: &CollisionShape, translation: &mut Translation, obstacle: &CollisionShape) { + let mut limit = 1.0; for point in obstacle.points() { - limit = min_options2(limit, translation_limit(translating, translation, &point)); - if limit.map(|l| l==0.0).unwrap_or(false) { + limit = min2(limit, translation_limit(translating, translation, &point)); + if limit == 0.0 { break; } } - limit.map(|limit| Translation { - x: translation.x * limit, - y: translation.y * limit, - z: translation.z * limit, - }) + translation.x *= limit; + translation.y *= limit; + translation.z *= limit; } #[test] @@ -232,43 +217,51 @@ fn test() { // Boxes are just next to each other and pushing against each other let shape2 = shape1.clone() + Translation { x: 1.0, y: 0.0, z: 0.0 }; - let translation = Translation { x: -1.0, y: 0.0, z: 0.0 }; - assert_eq!(collide(&shape2, &translation, &shape1), Some(Translation { x: 0.0, y: 0.0, z: 0.0 })); + let mut translation = Translation { x: -1.0, y: 0.0, z: 0.0 }; + restrict(&shape2, &mut translation, &shape1); + assert_eq!(translation, Translation { x: 0.0, y: 0.0, z: 0.0 }); // Boxes are one block away but one comes and pushes the other let shape2 = shape1.clone() + Translation { x: 2.0, y: 0.0, z: 0.0 }; - let translation = Translation { x: -2.0, y: 0.0, z: 0.0 }; - assert_eq!(collide(&shape2, &translation, &shape1), Some(Translation { x: -1.0, y: 0.0, z: 0.0 })); + let mut translation = Translation { x: -2.0, y: 0.0, z: 0.0 }; + restrict(&shape2, &mut translation, &shape1); + assert_eq!(translation, Translation { x: -1.0, y: 0.0, z: 0.0 }); // The other way around let shape2 = shape1.clone() + Translation { x: -2.0, y: 0.0, z: 0.0 }; - let translation = Translation { x: 2.0, y: 0.0, z: 0.0 }; - assert_eq!(collide(&shape2, &translation, &shape1), Some(Translation { x: 1.0, y: 0.0, z: 0.0 })); + let mut translation = Translation { x: 2.0, y: 0.0, z: 0.0 }; + restrict(&shape2, &mut translation, &shape1); + assert_eq!(translation, Translation { x: 1.0, y: 0.0, z: 0.0 }); // From top let shape2 = shape1.clone() + Translation { x: 0.0, y: 2.0, z: 0.0 }; - let translation = Translation { x: 0.0, y: -2.0, z: 0.0 }; - assert_eq!(collide(&shape2, &translation, &shape1), Some(Translation { x: 0.0, y: -1.0, z: 0.0 })); + let mut translation = Translation { x: 0.0, y: -2.0, z: 0.0 }; + restrict(&shape2, &mut translation, &shape1); + assert_eq!(translation, Translation { x: 0.0, y: -1.0, z: 0.0 }); // On last axis let shape2 = shape1.clone() + Translation { x: 0.0, y: 0.0, z: 2.0 }; - let translation = Translation { x: 0.0, y: 0.0, z: -2.0 }; - assert_eq!(collide(&shape2, &translation, &shape1), Some(Translation { x: 0.0, y: 0.0, z: -1.0 })); + let mut translation = Translation { x: 0.0, y: 0.0, z: -2.0 }; + restrict(&shape2, &mut translation, &shape1); + assert_eq!(translation, Translation { x: 0.0, y: 0.0, z: -1.0 }); // Colliding on corner let shape2 = shape1.clone() + Translation { x: 2.0, y: 2.0, z: 2.0 }; - let translation = Translation { x: -2.0, y: -2.0, z: -2.0 }; - assert_eq!(collide(&shape2, &translation, &shape1), Some(Translation { x: -1.0, y: -1.0, z: -1.0 })); + let mut translation = Translation { x: -2.0, y: -2.0, z: -2.0 }; + restrict(&shape2, &mut translation, &shape1); + assert_eq!(translation, Translation { x: -1.0, y: -1.0, z: -1.0 }); // Colliding with offset on other axis let shape2 = shape1.clone() + Translation { x: 2.0, y: 0.5, z: 0.0 }; - let translation = Translation { x: -2.0, y: 0.0, z: 0.0 }; - assert_eq!(collide(&shape2, &translation, &shape1), Some(Translation { x: -1.0, y: 0.0, z: 0.0 })); + let mut translation = Translation { x: -2.0, y: 0.0, z: 0.0 }; + restrict(&shape2, &mut translation, &shape1); + assert_eq!(translation, Translation { x: -1.0, y: 0.0, z: 0.0 }); // Colliding when already inside let shape2 = shape1.clone() + Translation { x: 0.5, y: 0.5, z: 0.5 }; - let translation = Translation { x: -0.5, y: -0.5, z: -0.5 }; - assert_eq!(collide(&shape2, &translation, &shape1), Some(Translation { x: 0.0, y: 0.0, z: 0.0 })); + let mut translation = Translation { x: -0.5, y: -0.5, z: -0.5 }; + restrict(&shape2, &mut translation, &shape1); + assert_eq!(translation, Translation { x: 0.0, y: 0.0, z: 0.0 }); } fn ray_cast(position: (f32, f32, f32), movement: (f32, f32, f32)) -> Vec<(isize, isize, isize)> { From d066aa5fdef3c67f0a771cc40e7fde6cae1cda16 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Mon, 13 Nov 2023 14:27:09 +0100 Subject: [PATCH 69/89] Adapt ray_cast --- minecraft-server/src/main.rs | 124 ++++++++++++++++++++++++++++++----- 1 file changed, 108 insertions(+), 16 deletions(-) diff --git a/minecraft-server/src/main.rs b/minecraft-server/src/main.rs index 042d8205..df122e23 100644 --- a/minecraft-server/src/main.rs +++ b/minecraft-server/src/main.rs @@ -75,6 +75,20 @@ impl CollisionShape { index: 0, } } + + // TODO(perf): Return an iterator yielding blocks instead of a vec of blocks + fn containing_blocks(&self) -> Vec { + let mut result = Vec::new(); + for x in self.x1.floor() as i32..=self.x2.floor() as i32 { + for y in self.y1.floor() as i32..=self.y2.floor() as i32 { + for z in self.z1.floor() as i32..=self.z2.floor() as i32 { + let block = BlockPosition { x, y, z }; + result.push(block); + } + } + } + result + } } #[derive(Debug, Clone, PartialEq)] @@ -111,6 +125,44 @@ impl std::ops::Add for CollisionShape { } } +impl std::ops::Add<&Translation> for CollisionShape { + type Output = CollisionShape; + + fn add(self, rhs: &Translation) -> Self::Output { + CollisionShape { + x1: self.x1 + rhs.x, + y1: self.y1 + rhs.y, + z1: self.z1 + rhs.z, + x2: self.x2 + rhs.x, + y2: self.y2 + rhs.y, + z2: self.z2 + rhs.z, + } + } +} + +impl std::ops::AddAssign<&Translation> for CollisionShape { + fn add_assign(&mut self, rhs: &Translation) { + self.x1 += rhs.x; + self.y1 += rhs.y; + self.z1 += rhs.z; + self.x2 += rhs.x; + self.y2 += rhs.y; + self.z2 += rhs.z; + } +} + +impl std::ops::Mul for Translation { + type Output = Translation; + + fn mul(self, rhs: f32) -> Self::Output { + Translation { + x: self.x * rhs, + y: self.y * rhs, + z: self.z * rhs, + } + } +} + fn is_inside(shape: &CollisionShape, point: Point) -> bool { (shape.x1..=shape.x2).contains(&point.x) && (shape.y1..=shape.y2).contains(&point.y) && (shape.z1..=shape.z2).contains(&point.z) } @@ -264,29 +316,69 @@ fn test() { assert_eq!(translation, Translation { x: 0.0, y: 0.0, z: 0.0 }); } -fn ray_cast(position: (f32, f32, f32), movement: (f32, f32, f32)) -> Vec<(isize, isize, isize)> { - let final_position = ((position.0+movement.0) as isize, (position.1+movement.1) as isize, (position.2+movement.2) as isize); +fn ray_cast(position: CollisionShape, movement: Translation) -> Vec { + let final_position = position.clone() + &movement; let mut result = Vec::new(); - let mut next_position = position; - result.push((next_position.0 as isize, next_position.1 as isize, next_position.2 as isize)); - while result.last().unwrap() != &final_position { - let next_x = if movement.0 > 0.0 { next_position.0.floor()+1.0 } else { next_position.0.floor()-1.0 }; - let next_y = if movement.1 > 0.0 { next_position.1.floor()+1.0 } else { next_position.1.floor()-1.0 }; - let next_z = if movement.2 > 0.0 { next_position.2.floor()+1.0 } else { next_position.2.floor()-1.0 }; - let x_dist = (next_x - next_position.0).abs(); - let y_dist = (next_y - next_position.1).abs(); - let z_dist = (next_z - next_position.2).abs(); - let x_time = x_dist / movement.0.abs(); - let y_time = y_dist / movement.1.abs(); - let z_time = z_dist / movement.2.abs(); + let mut next_position = position.clone(); + //result.extend(position.containing_blocks().into_iter()); + while next_position != final_position { + let x_dist = if movement.x > 0.0 { + let next_x = next_position.x1.floor()+1.0; + (next_x - next_position.x1).abs() + } else { + let next_x = next_position.x2.floor()-1.0; + (next_x - next_position.x2).abs() + }; + let y_dist = if movement.y > 0.0 { + let next_y = next_position.y1.floor()+1.0; + (next_y - next_position.y1).abs() + } else { + let next_y = next_position.y2.floor()-1.0; + (next_y - next_position.y2).abs() + }; + let z_dist = if movement.z > 0.0 { + let next_z = next_position.z1.floor()+1.0; + (next_z - next_position.z1).abs() + } else { + let next_z = next_position.z2.floor()-1.0; + (next_z - next_position.z2).abs() + }; + let x_time = x_dist / movement.x.abs(); + let y_time = y_dist / movement.y.abs(); + let z_time = z_dist / movement.z.abs(); let time = min(x_time, y_time, z_time); println!("pos{next_position:?} dist({x_dist}, {y_dist}, {z_dist}) time({x_time}, {y_time}, {z_time}) time({time})"); - next_position = (next_position.0 + movement.0 * time, next_position.1 + movement.1 * time, next_position.2 + movement.2 * time); - result.push((next_position.0 as isize, next_position.1 as isize, next_position.2 as isize)); + let mini_translation = movement.clone() * time; + next_position += &mini_translation; + result.push(mini_translation); } result } +#[test] +fn test_ray_cast() { + let shape = CollisionShape { + x1: 0.0, + y1: 0.0, + z1: 0.0, + x2: 1.0, + y2: 1.0, + z2: 1.0, + }; + + let movement = Translation { x: 5.0, y: 0.0, z: 0.0 }; + let mini_movements = ray_cast(shape.clone(), movement); + println!("{mini_movements:#?}"); + + let movement = Translation { x: 4.0, y: 2.0, z: 0.0 }; + let mini_movements = ray_cast(shape.clone(), movement); + println!("{mini_movements:#?}"); + + let movement = Translation { x: 2.38, y: 1.82, z: 1.0 }; + let mini_movements = ray_cast(shape.clone(), movement); + println!("{mini_movements:#?}"); +} + struct ServerFuture { server: ServerBehavior, } From 2cf243863a9e99c2711ab74b01758c5472f7fd26 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Mon, 13 Nov 2023 21:57:11 +0100 Subject: [PATCH 70/89] Move code to collisions.rs --- minecraft-server/src/main.rs | 370 ---------------------- minecraft-server/src/world/collisions.rs | 372 +++++++++++++++++++++++ minecraft-server/src/world/mod.rs | 2 + 3 files changed, 374 insertions(+), 370 deletions(-) create mode 100644 minecraft-server/src/world/collisions.rs diff --git a/minecraft-server/src/main.rs b/minecraft-server/src/main.rs index df122e23..9667ad48 100644 --- a/minecraft-server/src/main.rs +++ b/minecraft-server/src/main.rs @@ -8,376 +8,6 @@ mod entities; use crate::prelude::*; -fn min2(a: f32, b: f32) -> f32 { - if a < b { - a - } else { - b - } -} - -fn min(a: f32, b: f32, c: f32) -> f32 { - min2(min2(a, b), c) -} - -fn min_options2(a: Option, b: Option) -> Option { - match (a, b) { - (Some(a), Some(b)) => Some(min(a, b, 1.0)), - (Some(a), None) => Some(a), - (None, Some(b)) => Some(b), - (None, None) => None, - } -} - -#[derive(Debug, Clone, PartialEq)] -struct CollisionShape { - x1: f32, - y1: f32, - z1: f32, - x2: f32, - y2: f32, - z2: f32, -} - -struct Point { - x: f32, - y: f32, - z: f32, -} - -struct PointIter<'a> { - shape: &'a CollisionShape, - index: usize, -} - -impl<'a> Iterator for PointIter<'a> { - type Item = Point; - - fn next(&mut self) -> Option { - if self.index < 8 { - let result = Point { - x: if self.index & 1 == 0 { self.shape.x1 } else { self.shape.x2 }, - y: if self.index & 2 == 0 { self.shape.y1 } else { self.shape.y2 }, - z: if self.index & 4 == 0 { self.shape.z1 } else { self.shape.z2 }, - }; - self.index += 1; - Some(result) - } else { - None - } - } -} - -impl CollisionShape { - const fn points(&self) -> PointIter { - PointIter { - shape: self, - index: 0, - } - } - - // TODO(perf): Return an iterator yielding blocks instead of a vec of blocks - fn containing_blocks(&self) -> Vec { - let mut result = Vec::new(); - for x in self.x1.floor() as i32..=self.x2.floor() as i32 { - for y in self.y1.floor() as i32..=self.y2.floor() as i32 { - for z in self.z1.floor() as i32..=self.z2.floor() as i32 { - let block = BlockPosition { x, y, z }; - result.push(block); - } - } - } - result - } -} - -#[derive(Debug, Clone, PartialEq)] -struct Translation { - x: f32, - y: f32, - z: f32, -} - -impl std::ops::Add for Translation { - type Output = Translation; - - fn add(self, rhs: Translation) -> Self::Output { - Translation { - x: self.x + rhs.x, - y: self.y + rhs.y, - z: self.z + rhs.z, - } - } -} - -impl std::ops::Add for CollisionShape { - type Output = CollisionShape; - - fn add(self, rhs: Translation) -> Self::Output { - CollisionShape { - x1: self.x1 + rhs.x, - y1: self.y1 + rhs.y, - z1: self.z1 + rhs.z, - x2: self.x2 + rhs.x, - y2: self.y2 + rhs.y, - z2: self.z2 + rhs.z, - } - } -} - -impl std::ops::Add<&Translation> for CollisionShape { - type Output = CollisionShape; - - fn add(self, rhs: &Translation) -> Self::Output { - CollisionShape { - x1: self.x1 + rhs.x, - y1: self.y1 + rhs.y, - z1: self.z1 + rhs.z, - x2: self.x2 + rhs.x, - y2: self.y2 + rhs.y, - z2: self.z2 + rhs.z, - } - } -} - -impl std::ops::AddAssign<&Translation> for CollisionShape { - fn add_assign(&mut self, rhs: &Translation) { - self.x1 += rhs.x; - self.y1 += rhs.y; - self.z1 += rhs.z; - self.x2 += rhs.x; - self.y2 += rhs.y; - self.z2 += rhs.z; - } -} - -impl std::ops::Mul for Translation { - type Output = Translation; - - fn mul(self, rhs: f32) -> Self::Output { - Translation { - x: self.x * rhs, - y: self.y * rhs, - z: self.z * rhs, - } - } -} - -fn is_inside(shape: &CollisionShape, point: Point) -> bool { - (shape.x1..=shape.x2).contains(&point.x) && (shape.y1..=shape.y2).contains(&point.y) && (shape.z1..=shape.z2).contains(&point.z) -} - -fn translation_limit_y(shape: &CollisionShape, translation: &Translation, point: &Point) -> f32 { - if translation.y == 0.0 { - return 1.0; - } - let y = if translation.y < 0.0 { shape.y1 } else { shape.y2 }; - let translated_ratio = (point.y - y) / translation.y; - if translated_ratio >= 1.0 { - return 1.0; - } else if translated_ratio <= 0.0 { - return 0.0; - } - let translated_x1 = shape.x1 + translation.x * translated_ratio; - let translated_x2 = shape.x2 + translation.x * translated_ratio; - let translated_z1 = shape.z1 + translation.z * translated_ratio; - let translated_z2 = shape.z2 + translation.z * translated_ratio; - if (translated_x1..=translated_x2).contains(&point.x) && (translated_z1..=translated_z2).contains(&point.z) { - translated_ratio - } else { - 1.0 - } -} - -fn translation_limit_x(shape: &CollisionShape, translation: &Translation, point: &Point) -> f32 { - if translation.x == 0.0 { - return 1.0; - } - let x = if translation.x < 0.0 { shape.x1 } else { shape.x2 }; - let translated_ratio = (point.x - x) / translation.x; - if translated_ratio >= 1.0 { - return 1.0; - } else if translated_ratio <= 0.0 { - return 0.0; - } - let translated_y1 = shape.y1 + translation.y * translated_ratio; - let translated_y2 = shape.y2 + translation.y * translated_ratio; - let translated_z1 = shape.z1 + translation.z * translated_ratio; - let translated_z2 = shape.z2 + translation.z * translated_ratio; - if (translated_y1..=translated_y2).contains(&point.y) && (translated_z1..=translated_z2).contains(&point.z) { - translated_ratio - } else { - 1.0 - } -} - -fn translation_limit_z(shape: &CollisionShape, translation: &Translation, point: &Point) -> f32 { - if translation.z == 0.0 { - return 1.0; - } - let z = if translation.z < 0.0 { shape.z1 } else { shape.z2 }; - let translated_ratio = (point.z - z) / translation.z; - if translated_ratio >= 1.0 { - return 1.0; - } else if translated_ratio <= 0.0 { - return 0.0; - } - let translated_x1 = shape.x1 + translation.x * translated_ratio; - let translated_x2 = shape.x2 + translation.x * translated_ratio; - let translated_y1 = shape.y1 + translation.y * translated_ratio; - let translated_y2 = shape.y2 + translation.y * translated_ratio; - if (translated_x1..=translated_x2).contains(&point.x) && (translated_y1..=translated_y2).contains(&point.y) { - translated_ratio - } else { - 1.0 - } -} - -fn translation_limit(shape: &CollisionShape, translation: &Translation, point: &Point) -> f32 { - min( - translation_limit_x(shape, translation, point), - translation_limit_y(shape, translation, point), - translation_limit_z(shape, translation, point) - ) -} - -fn restrict(translating: &CollisionShape, translation: &mut Translation, obstacle: &CollisionShape) { - let mut limit = 1.0; - - for point in obstacle.points() { - limit = min2(limit, translation_limit(translating, translation, &point)); - if limit == 0.0 { - break; - } - } - - translation.x *= limit; - translation.y *= limit; - translation.z *= limit; -} - -#[test] -fn test() { - let shape1 = CollisionShape { - x1: 0.0, - y1: 0.0, - z1: 0.0, - x2: 1.0, - y2: 1.0, - z2: 1.0, - }; - - // Boxes are just next to each other and pushing against each other - let shape2 = shape1.clone() + Translation { x: 1.0, y: 0.0, z: 0.0 }; - let mut translation = Translation { x: -1.0, y: 0.0, z: 0.0 }; - restrict(&shape2, &mut translation, &shape1); - assert_eq!(translation, Translation { x: 0.0, y: 0.0, z: 0.0 }); - - // Boxes are one block away but one comes and pushes the other - let shape2 = shape1.clone() + Translation { x: 2.0, y: 0.0, z: 0.0 }; - let mut translation = Translation { x: -2.0, y: 0.0, z: 0.0 }; - restrict(&shape2, &mut translation, &shape1); - assert_eq!(translation, Translation { x: -1.0, y: 0.0, z: 0.0 }); - - // The other way around - let shape2 = shape1.clone() + Translation { x: -2.0, y: 0.0, z: 0.0 }; - let mut translation = Translation { x: 2.0, y: 0.0, z: 0.0 }; - restrict(&shape2, &mut translation, &shape1); - assert_eq!(translation, Translation { x: 1.0, y: 0.0, z: 0.0 }); - - // From top - let shape2 = shape1.clone() + Translation { x: 0.0, y: 2.0, z: 0.0 }; - let mut translation = Translation { x: 0.0, y: -2.0, z: 0.0 }; - restrict(&shape2, &mut translation, &shape1); - assert_eq!(translation, Translation { x: 0.0, y: -1.0, z: 0.0 }); - - // On last axis - let shape2 = shape1.clone() + Translation { x: 0.0, y: 0.0, z: 2.0 }; - let mut translation = Translation { x: 0.0, y: 0.0, z: -2.0 }; - restrict(&shape2, &mut translation, &shape1); - assert_eq!(translation, Translation { x: 0.0, y: 0.0, z: -1.0 }); - - // Colliding on corner - let shape2 = shape1.clone() + Translation { x: 2.0, y: 2.0, z: 2.0 }; - let mut translation = Translation { x: -2.0, y: -2.0, z: -2.0 }; - restrict(&shape2, &mut translation, &shape1); - assert_eq!(translation, Translation { x: -1.0, y: -1.0, z: -1.0 }); - - // Colliding with offset on other axis - let shape2 = shape1.clone() + Translation { x: 2.0, y: 0.5, z: 0.0 }; - let mut translation = Translation { x: -2.0, y: 0.0, z: 0.0 }; - restrict(&shape2, &mut translation, &shape1); - assert_eq!(translation, Translation { x: -1.0, y: 0.0, z: 0.0 }); - - // Colliding when already inside - let shape2 = shape1.clone() + Translation { x: 0.5, y: 0.5, z: 0.5 }; - let mut translation = Translation { x: -0.5, y: -0.5, z: -0.5 }; - restrict(&shape2, &mut translation, &shape1); - assert_eq!(translation, Translation { x: 0.0, y: 0.0, z: 0.0 }); -} - -fn ray_cast(position: CollisionShape, movement: Translation) -> Vec { - let final_position = position.clone() + &movement; - let mut result = Vec::new(); - let mut next_position = position.clone(); - //result.extend(position.containing_blocks().into_iter()); - while next_position != final_position { - let x_dist = if movement.x > 0.0 { - let next_x = next_position.x1.floor()+1.0; - (next_x - next_position.x1).abs() - } else { - let next_x = next_position.x2.floor()-1.0; - (next_x - next_position.x2).abs() - }; - let y_dist = if movement.y > 0.0 { - let next_y = next_position.y1.floor()+1.0; - (next_y - next_position.y1).abs() - } else { - let next_y = next_position.y2.floor()-1.0; - (next_y - next_position.y2).abs() - }; - let z_dist = if movement.z > 0.0 { - let next_z = next_position.z1.floor()+1.0; - (next_z - next_position.z1).abs() - } else { - let next_z = next_position.z2.floor()-1.0; - (next_z - next_position.z2).abs() - }; - let x_time = x_dist / movement.x.abs(); - let y_time = y_dist / movement.y.abs(); - let z_time = z_dist / movement.z.abs(); - let time = min(x_time, y_time, z_time); - println!("pos{next_position:?} dist({x_dist}, {y_dist}, {z_dist}) time({x_time}, {y_time}, {z_time}) time({time})"); - let mini_translation = movement.clone() * time; - next_position += &mini_translation; - result.push(mini_translation); - } - result -} - -#[test] -fn test_ray_cast() { - let shape = CollisionShape { - x1: 0.0, - y1: 0.0, - z1: 0.0, - x2: 1.0, - y2: 1.0, - z2: 1.0, - }; - - let movement = Translation { x: 5.0, y: 0.0, z: 0.0 }; - let mini_movements = ray_cast(shape.clone(), movement); - println!("{mini_movements:#?}"); - - let movement = Translation { x: 4.0, y: 2.0, z: 0.0 }; - let mini_movements = ray_cast(shape.clone(), movement); - println!("{mini_movements:#?}"); - - let movement = Translation { x: 2.38, y: 1.82, z: 1.0 }; - let mini_movements = ray_cast(shape.clone(), movement); - println!("{mini_movements:#?}"); -} struct ServerFuture { server: ServerBehavior, diff --git a/minecraft-server/src/world/collisions.rs b/minecraft-server/src/world/collisions.rs new file mode 100644 index 00000000..56f16533 --- /dev/null +++ b/minecraft-server/src/world/collisions.rs @@ -0,0 +1,372 @@ +fn min2(a: f32, b: f32) -> f32 { + if a < b { + a + } else { + b + } +} + +fn min(a: f32, b: f32, c: f32) -> f32 { + min2(min2(a, b), c) +} + +fn min_options2(a: Option, b: Option) -> Option { + match (a, b) { + (Some(a), Some(b)) => Some(min(a, b, 1.0)), + (Some(a), None) => Some(a), + (None, Some(b)) => Some(b), + (None, None) => None, + } +} + +#[derive(Debug, Clone, PartialEq)] +struct CollisionShape { + x1: f32, + y1: f32, + z1: f32, + x2: f32, + y2: f32, + z2: f32, +} + +struct Point { + x: f32, + y: f32, + z: f32, +} + +struct PointIter<'a> { + shape: &'a CollisionShape, + index: usize, +} + +impl<'a> Iterator for PointIter<'a> { + type Item = Point; + + fn next(&mut self) -> Option { + if self.index < 8 { + let result = Point { + x: if self.index & 1 == 0 { self.shape.x1 } else { self.shape.x2 }, + y: if self.index & 2 == 0 { self.shape.y1 } else { self.shape.y2 }, + z: if self.index & 4 == 0 { self.shape.z1 } else { self.shape.z2 }, + }; + self.index += 1; + Some(result) + } else { + None + } + } +} + +impl CollisionShape { + const fn points(&self) -> PointIter { + PointIter { + shape: self, + index: 0, + } + } + + // TODO(perf): Return an iterator yielding blocks instead of a vec of blocks + fn containing_blocks(&self) -> Vec { + let mut result = Vec::new(); + for x in self.x1.floor() as i32..=self.x2.floor() as i32 { + for y in self.y1.floor() as i32..=self.y2.floor() as i32 { + for z in self.z1.floor() as i32..=self.z2.floor() as i32 { + let block = BlockPosition { x, y, z }; + result.push(block); + } + } + } + result + } +} + +#[derive(Debug, Clone, PartialEq)] +struct Translation { + x: f32, + y: f32, + z: f32, +} + +impl std::ops::Add for Translation { + type Output = Translation; + + fn add(self, rhs: Translation) -> Self::Output { + Translation { + x: self.x + rhs.x, + y: self.y + rhs.y, + z: self.z + rhs.z, + } + } +} + +impl std::ops::Add for CollisionShape { + type Output = CollisionShape; + + fn add(self, rhs: Translation) -> Self::Output { + CollisionShape { + x1: self.x1 + rhs.x, + y1: self.y1 + rhs.y, + z1: self.z1 + rhs.z, + x2: self.x2 + rhs.x, + y2: self.y2 + rhs.y, + z2: self.z2 + rhs.z, + } + } +} + +impl std::ops::Add<&Translation> for CollisionShape { + type Output = CollisionShape; + + fn add(self, rhs: &Translation) -> Self::Output { + CollisionShape { + x1: self.x1 + rhs.x, + y1: self.y1 + rhs.y, + z1: self.z1 + rhs.z, + x2: self.x2 + rhs.x, + y2: self.y2 + rhs.y, + z2: self.z2 + rhs.z, + } + } +} + +impl std::ops::AddAssign<&Translation> for CollisionShape { + fn add_assign(&mut self, rhs: &Translation) { + self.x1 += rhs.x; + self.y1 += rhs.y; + self.z1 += rhs.z; + self.x2 += rhs.x; + self.y2 += rhs.y; + self.z2 += rhs.z; + } +} + +impl std::ops::Mul for Translation { + type Output = Translation; + + fn mul(self, rhs: f32) -> Self::Output { + Translation { + x: self.x * rhs, + y: self.y * rhs, + z: self.z * rhs, + } + } +} + +fn is_inside(shape: &CollisionShape, point: Point) -> bool { + (shape.x1..=shape.x2).contains(&point.x) && (shape.y1..=shape.y2).contains(&point.y) && (shape.z1..=shape.z2).contains(&point.z) +} + +fn translation_limit_y(shape: &CollisionShape, translation: &Translation, point: &Point) -> f32 { + if translation.y == 0.0 { + return 1.0; + } + let y = if translation.y < 0.0 { shape.y1 } else { shape.y2 }; + let translated_ratio = (point.y - y) / translation.y; + if translated_ratio >= 1.0 { + return 1.0; + } else if translated_ratio <= 0.0 { + return 0.0; + } + let translated_x1 = shape.x1 + translation.x * translated_ratio; + let translated_x2 = shape.x2 + translation.x * translated_ratio; + let translated_z1 = shape.z1 + translation.z * translated_ratio; + let translated_z2 = shape.z2 + translation.z * translated_ratio; + if (translated_x1..=translated_x2).contains(&point.x) && (translated_z1..=translated_z2).contains(&point.z) { + translated_ratio + } else { + 1.0 + } +} + +fn translation_limit_x(shape: &CollisionShape, translation: &Translation, point: &Point) -> f32 { + if translation.x == 0.0 { + return 1.0; + } + let x = if translation.x < 0.0 { shape.x1 } else { shape.x2 }; + let translated_ratio = (point.x - x) / translation.x; + if translated_ratio >= 1.0 { + return 1.0; + } else if translated_ratio <= 0.0 { + return 0.0; + } + let translated_y1 = shape.y1 + translation.y * translated_ratio; + let translated_y2 = shape.y2 + translation.y * translated_ratio; + let translated_z1 = shape.z1 + translation.z * translated_ratio; + let translated_z2 = shape.z2 + translation.z * translated_ratio; + if (translated_y1..=translated_y2).contains(&point.y) && (translated_z1..=translated_z2).contains(&point.z) { + translated_ratio + } else { + 1.0 + } +} + +fn translation_limit_z(shape: &CollisionShape, translation: &Translation, point: &Point) -> f32 { + if translation.z == 0.0 { + return 1.0; + } + let z = if translation.z < 0.0 { shape.z1 } else { shape.z2 }; + let translated_ratio = (point.z - z) / translation.z; + if translated_ratio >= 1.0 { + return 1.0; + } else if translated_ratio <= 0.0 { + return 0.0; + } + let translated_x1 = shape.x1 + translation.x * translated_ratio; + let translated_x2 = shape.x2 + translation.x * translated_ratio; + let translated_y1 = shape.y1 + translation.y * translated_ratio; + let translated_y2 = shape.y2 + translation.y * translated_ratio; + if (translated_x1..=translated_x2).contains(&point.x) && (translated_y1..=translated_y2).contains(&point.y) { + translated_ratio + } else { + 1.0 + } +} + +fn translation_limit(shape: &CollisionShape, translation: &Translation, point: &Point) -> f32 { + min( + translation_limit_x(shape, translation, point), + translation_limit_y(shape, translation, point), + translation_limit_z(shape, translation, point) + ) +} + +fn restrict(translating: &CollisionShape, translation: &mut Translation, obstacle: &CollisionShape) { + let mut limit = 1.0; + + for point in obstacle.points() { + limit = min2(limit, translation_limit(translating, translation, &point)); + if limit == 0.0 { + break; + } + } + + translation.x *= limit; + translation.y *= limit; + translation.z *= limit; +} + +fn ray_cast(position: CollisionShape, movement: Translation) -> Vec { + let final_position = position.clone() + &movement; + let mut result = Vec::new(); + let mut next_position = position.clone(); + //result.extend(position.containing_blocks().into_iter()); + while next_position != final_position { + let x_dist = if movement.x > 0.0 { + let next_x = next_position.x1.floor()+1.0; + (next_x - next_position.x1).abs() + } else { + let next_x = next_position.x2.floor()-1.0; + (next_x - next_position.x2).abs() + }; + let y_dist = if movement.y > 0.0 { + let next_y = next_position.y1.floor()+1.0; + (next_y - next_position.y1).abs() + } else { + let next_y = next_position.y2.floor()-1.0; + (next_y - next_position.y2).abs() + }; + let z_dist = if movement.z > 0.0 { + let next_z = next_position.z1.floor()+1.0; + (next_z - next_position.z1).abs() + } else { + let next_z = next_position.z2.floor()-1.0; + (next_z - next_position.z2).abs() + }; + let x_time = x_dist / movement.x.abs(); + let y_time = y_dist / movement.y.abs(); + let z_time = z_dist / movement.z.abs(); + let time = min(x_time, y_time, z_time); + println!("pos{next_position:?} dist({x_dist}, {y_dist}, {z_dist}) time({x_time}, {y_time}, {z_time}) time({time})"); + let mini_translation = movement.clone() * time; + next_position += &mini_translation; + result.push(mini_translation); + } + result +} + + + +#[test] +fn test() { + let shape1 = CollisionShape { + x1: 0.0, + y1: 0.0, + z1: 0.0, + x2: 1.0, + y2: 1.0, + z2: 1.0, + }; + + // Boxes are just next to each other and pushing against each other + let shape2 = shape1.clone() + Translation { x: 1.0, y: 0.0, z: 0.0 }; + let mut translation = Translation { x: -1.0, y: 0.0, z: 0.0 }; + restrict(&shape2, &mut translation, &shape1); + assert_eq!(translation, Translation { x: 0.0, y: 0.0, z: 0.0 }); + + // Boxes are one block away but one comes and pushes the other + let shape2 = shape1.clone() + Translation { x: 2.0, y: 0.0, z: 0.0 }; + let mut translation = Translation { x: -2.0, y: 0.0, z: 0.0 }; + restrict(&shape2, &mut translation, &shape1); + assert_eq!(translation, Translation { x: -1.0, y: 0.0, z: 0.0 }); + + // The other way around + let shape2 = shape1.clone() + Translation { x: -2.0, y: 0.0, z: 0.0 }; + let mut translation = Translation { x: 2.0, y: 0.0, z: 0.0 }; + restrict(&shape2, &mut translation, &shape1); + assert_eq!(translation, Translation { x: 1.0, y: 0.0, z: 0.0 }); + + // From top + let shape2 = shape1.clone() + Translation { x: 0.0, y: 2.0, z: 0.0 }; + let mut translation = Translation { x: 0.0, y: -2.0, z: 0.0 }; + restrict(&shape2, &mut translation, &shape1); + assert_eq!(translation, Translation { x: 0.0, y: -1.0, z: 0.0 }); + + // On last axis + let shape2 = shape1.clone() + Translation { x: 0.0, y: 0.0, z: 2.0 }; + let mut translation = Translation { x: 0.0, y: 0.0, z: -2.0 }; + restrict(&shape2, &mut translation, &shape1); + assert_eq!(translation, Translation { x: 0.0, y: 0.0, z: -1.0 }); + + // Colliding on corner + let shape2 = shape1.clone() + Translation { x: 2.0, y: 2.0, z: 2.0 }; + let mut translation = Translation { x: -2.0, y: -2.0, z: -2.0 }; + restrict(&shape2, &mut translation, &shape1); + assert_eq!(translation, Translation { x: -1.0, y: -1.0, z: -1.0 }); + + // Colliding with offset on other axis + let shape2 = shape1.clone() + Translation { x: 2.0, y: 0.5, z: 0.0 }; + let mut translation = Translation { x: -2.0, y: 0.0, z: 0.0 }; + restrict(&shape2, &mut translation, &shape1); + assert_eq!(translation, Translation { x: -1.0, y: 0.0, z: 0.0 }); + + // Colliding when already inside + let shape2 = shape1.clone() + Translation { x: 0.5, y: 0.5, z: 0.5 }; + let mut translation = Translation { x: -0.5, y: -0.5, z: -0.5 }; + restrict(&shape2, &mut translation, &shape1); + assert_eq!(translation, Translation { x: 0.0, y: 0.0, z: 0.0 }); +} + +#[test] +fn test_ray_cast() { + let shape = CollisionShape { + x1: 0.0, + y1: 0.0, + z1: 0.0, + x2: 1.0, + y2: 1.0, + z2: 1.0, + }; + + let movement = Translation { x: 5.0, y: 0.0, z: 0.0 }; + let mini_movements = ray_cast(shape.clone(), movement); + println!("{mini_movements:#?}"); + + let movement = Translation { x: 4.0, y: 2.0, z: 0.0 }; + let mini_movements = ray_cast(shape.clone(), movement); + println!("{mini_movements:#?}"); + + let movement = Translation { x: 2.38, y: 1.82, z: 1.0 }; + let mini_movements = ray_cast(shape.clone(), movement); + println!("{mini_movements:#?}"); +} diff --git a/minecraft-server/src/world/mod.rs b/minecraft-server/src/world/mod.rs index de90410f..07eef017 100644 --- a/minecraft-server/src/world/mod.rs +++ b/minecraft-server/src/world/mod.rs @@ -8,6 +8,8 @@ mod map; use map::*; mod ecs; use ecs::*; +mod collisions; +use collisions::*; /// World is the union of the map and entities. /// World handles loaded chunks and entities. From a057b3b8716c76e7a0c1ab59d0d258519fd50447 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Mon, 13 Nov 2023 21:59:04 +0100 Subject: [PATCH 71/89] Add test module --- minecraft-server/src/world/collisions.rs | 165 ++++++++++++----------- 1 file changed, 84 insertions(+), 81 deletions(-) diff --git a/minecraft-server/src/world/collisions.rs b/minecraft-server/src/world/collisions.rs index 56f16533..469b9259 100644 --- a/minecraft-server/src/world/collisions.rs +++ b/minecraft-server/src/world/collisions.rs @@ -285,88 +285,91 @@ fn ray_cast(position: CollisionShape, movement: Translation) -> Vec result } +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test() { + let shape1 = CollisionShape { + x1: 0.0, + y1: 0.0, + z1: 0.0, + x2: 1.0, + y2: 1.0, + z2: 1.0, + }; + // Boxes are just next to each other and pushing against each other + let shape2 = shape1.clone() + Translation { x: 1.0, y: 0.0, z: 0.0 }; + let mut translation = Translation { x: -1.0, y: 0.0, z: 0.0 }; + restrict(&shape2, &mut translation, &shape1); + assert_eq!(translation, Translation { x: 0.0, y: 0.0, z: 0.0 }); + + // Boxes are one block away but one comes and pushes the other + let shape2 = shape1.clone() + Translation { x: 2.0, y: 0.0, z: 0.0 }; + let mut translation = Translation { x: -2.0, y: 0.0, z: 0.0 }; + restrict(&shape2, &mut translation, &shape1); + assert_eq!(translation, Translation { x: -1.0, y: 0.0, z: 0.0 }); + + // The other way around + let shape2 = shape1.clone() + Translation { x: -2.0, y: 0.0, z: 0.0 }; + let mut translation = Translation { x: 2.0, y: 0.0, z: 0.0 }; + restrict(&shape2, &mut translation, &shape1); + assert_eq!(translation, Translation { x: 1.0, y: 0.0, z: 0.0 }); + + // From top + let shape2 = shape1.clone() + Translation { x: 0.0, y: 2.0, z: 0.0 }; + let mut translation = Translation { x: 0.0, y: -2.0, z: 0.0 }; + restrict(&shape2, &mut translation, &shape1); + assert_eq!(translation, Translation { x: 0.0, y: -1.0, z: 0.0 }); + + // On last axis + let shape2 = shape1.clone() + Translation { x: 0.0, y: 0.0, z: 2.0 }; + let mut translation = Translation { x: 0.0, y: 0.0, z: -2.0 }; + restrict(&shape2, &mut translation, &shape1); + assert_eq!(translation, Translation { x: 0.0, y: 0.0, z: -1.0 }); + + // Colliding on corner + let shape2 = shape1.clone() + Translation { x: 2.0, y: 2.0, z: 2.0 }; + let mut translation = Translation { x: -2.0, y: -2.0, z: -2.0 }; + restrict(&shape2, &mut translation, &shape1); + assert_eq!(translation, Translation { x: -1.0, y: -1.0, z: -1.0 }); + + // Colliding with offset on other axis + let shape2 = shape1.clone() + Translation { x: 2.0, y: 0.5, z: 0.0 }; + let mut translation = Translation { x: -2.0, y: 0.0, z: 0.0 }; + restrict(&shape2, &mut translation, &shape1); + assert_eq!(translation, Translation { x: -1.0, y: 0.0, z: 0.0 }); + + // Colliding when already inside + let shape2 = shape1.clone() + Translation { x: 0.5, y: 0.5, z: 0.5 }; + let mut translation = Translation { x: -0.5, y: -0.5, z: -0.5 }; + restrict(&shape2, &mut translation, &shape1); + assert_eq!(translation, Translation { x: 0.0, y: 0.0, z: 0.0 }); + } -#[test] -fn test() { - let shape1 = CollisionShape { - x1: 0.0, - y1: 0.0, - z1: 0.0, - x2: 1.0, - y2: 1.0, - z2: 1.0, - }; - - // Boxes are just next to each other and pushing against each other - let shape2 = shape1.clone() + Translation { x: 1.0, y: 0.0, z: 0.0 }; - let mut translation = Translation { x: -1.0, y: 0.0, z: 0.0 }; - restrict(&shape2, &mut translation, &shape1); - assert_eq!(translation, Translation { x: 0.0, y: 0.0, z: 0.0 }); - - // Boxes are one block away but one comes and pushes the other - let shape2 = shape1.clone() + Translation { x: 2.0, y: 0.0, z: 0.0 }; - let mut translation = Translation { x: -2.0, y: 0.0, z: 0.0 }; - restrict(&shape2, &mut translation, &shape1); - assert_eq!(translation, Translation { x: -1.0, y: 0.0, z: 0.0 }); - - // The other way around - let shape2 = shape1.clone() + Translation { x: -2.0, y: 0.0, z: 0.0 }; - let mut translation = Translation { x: 2.0, y: 0.0, z: 0.0 }; - restrict(&shape2, &mut translation, &shape1); - assert_eq!(translation, Translation { x: 1.0, y: 0.0, z: 0.0 }); - - // From top - let shape2 = shape1.clone() + Translation { x: 0.0, y: 2.0, z: 0.0 }; - let mut translation = Translation { x: 0.0, y: -2.0, z: 0.0 }; - restrict(&shape2, &mut translation, &shape1); - assert_eq!(translation, Translation { x: 0.0, y: -1.0, z: 0.0 }); - - // On last axis - let shape2 = shape1.clone() + Translation { x: 0.0, y: 0.0, z: 2.0 }; - let mut translation = Translation { x: 0.0, y: 0.0, z: -2.0 }; - restrict(&shape2, &mut translation, &shape1); - assert_eq!(translation, Translation { x: 0.0, y: 0.0, z: -1.0 }); - - // Colliding on corner - let shape2 = shape1.clone() + Translation { x: 2.0, y: 2.0, z: 2.0 }; - let mut translation = Translation { x: -2.0, y: -2.0, z: -2.0 }; - restrict(&shape2, &mut translation, &shape1); - assert_eq!(translation, Translation { x: -1.0, y: -1.0, z: -1.0 }); - - // Colliding with offset on other axis - let shape2 = shape1.clone() + Translation { x: 2.0, y: 0.5, z: 0.0 }; - let mut translation = Translation { x: -2.0, y: 0.0, z: 0.0 }; - restrict(&shape2, &mut translation, &shape1); - assert_eq!(translation, Translation { x: -1.0, y: 0.0, z: 0.0 }); - - // Colliding when already inside - let shape2 = shape1.clone() + Translation { x: 0.5, y: 0.5, z: 0.5 }; - let mut translation = Translation { x: -0.5, y: -0.5, z: -0.5 }; - restrict(&shape2, &mut translation, &shape1); - assert_eq!(translation, Translation { x: 0.0, y: 0.0, z: 0.0 }); -} + #[test] + fn test_ray_cast() { + let shape = CollisionShape { + x1: 0.0, + y1: 0.0, + z1: 0.0, + x2: 1.0, + y2: 1.0, + z2: 1.0, + }; -#[test] -fn test_ray_cast() { - let shape = CollisionShape { - x1: 0.0, - y1: 0.0, - z1: 0.0, - x2: 1.0, - y2: 1.0, - z2: 1.0, - }; - - let movement = Translation { x: 5.0, y: 0.0, z: 0.0 }; - let mini_movements = ray_cast(shape.clone(), movement); - println!("{mini_movements:#?}"); - - let movement = Translation { x: 4.0, y: 2.0, z: 0.0 }; - let mini_movements = ray_cast(shape.clone(), movement); - println!("{mini_movements:#?}"); - - let movement = Translation { x: 2.38, y: 1.82, z: 1.0 }; - let mini_movements = ray_cast(shape.clone(), movement); - println!("{mini_movements:#?}"); + let movement = Translation { x: 5.0, y: 0.0, z: 0.0 }; + let mini_movements = ray_cast(shape.clone(), movement); + println!("{mini_movements:#?}"); + + let movement = Translation { x: 4.0, y: 2.0, z: 0.0 }; + let mini_movements = ray_cast(shape.clone(), movement); + println!("{mini_movements:#?}"); + + let movement = Translation { x: 2.38, y: 1.82, z: 1.0 }; + let mini_movements = ray_cast(shape.clone(), movement); + println!("{mini_movements:#?}"); + } } From c9ecf2c6184ae902af78baebb3b822683982c9c6 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Mon, 13 Nov 2023 21:59:45 +0100 Subject: [PATCH 72/89] Fix compilation --- minecraft-server/src/world/collisions.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/minecraft-server/src/world/collisions.rs b/minecraft-server/src/world/collisions.rs index 469b9259..58e3318f 100644 --- a/minecraft-server/src/world/collisions.rs +++ b/minecraft-server/src/world/collisions.rs @@ -1,3 +1,5 @@ +use super::*; + fn min2(a: f32, b: f32) -> f32 { if a < b { a From b20596ca5e4f4b1e8b474b3b99ef9ed7b885244a Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Mon, 13 Nov 2023 22:18:01 +0100 Subject: [PATCH 73/89] Clean positions.rs --- minecraft-server/src/world/collisions.rs | 282 ++++++++++++----------- minecraft-server/src/world/map.rs | 4 + 2 files changed, 148 insertions(+), 138 deletions(-) diff --git a/minecraft-server/src/world/collisions.rs b/minecraft-server/src/world/collisions.rs index 58e3318f..3df436f3 100644 --- a/minecraft-server/src/world/collisions.rs +++ b/minecraft-server/src/world/collisions.rs @@ -1,5 +1,6 @@ use super::*; +/// Returns minimum of two floats fn min2(a: f32, b: f32) -> f32 { if a < b { a @@ -8,21 +9,14 @@ fn min2(a: f32, b: f32) -> f32 { } } +/// Returns minimum of three floats fn min(a: f32, b: f32, c: f32) -> f32 { min2(min2(a, b), c) } -fn min_options2(a: Option, b: Option) -> Option { - match (a, b) { - (Some(a), Some(b)) => Some(min(a, b, 1.0)), - (Some(a), None) => Some(a), - (None, Some(b)) => Some(b), - (None, None) => None, - } -} - +/// An object in space #[derive(Debug, Clone, PartialEq)] -struct CollisionShape { +pub struct CollisionShape { x1: f32, y1: f32, z1: f32, @@ -31,13 +25,123 @@ struct CollisionShape { z2: f32, } -struct Point { +impl CollisionShape { + const fn points(&self) -> PointIter { + PointIter { + shape: self, + index: 0, + } + } + + // TODO(perf): Return an iterator yielding blocks instead of a vec of blocks + fn containing_blocks(&self) -> Vec { + let mut result = Vec::new(); + for x in self.x1.floor() as i32..=self.x2.floor() as i32 { + for y in self.y1.floor() as i32..=self.y2.floor() as i32 { + for z in self.z1.floor() as i32..=self.z2.floor() as i32 { + let block = BlockPosition { x, y, z }; + result.push(block); + } + } + } + result + } +} + +/// A point in space +pub struct Point { x: f32, y: f32, z: f32, } -struct PointIter<'a> { +impl Point { + /// Returns true if the point is inside the shape + fn is_inside(&self, shape: &CollisionShape) -> bool { + (shape.x1..=shape.x2).contains(&self.x) && (shape.y1..=shape.y2).contains(&self.y) && (shape.z1..=shape.z2).contains(&self.z) + } + + /// Returns the proportion of the translation that can be applied without absorbing `point` inside `shape` on the x axis + fn collide_x(&self, shape: &CollisionShape, translation: &Translation) -> f32 { + if translation.x == 0.0 { + return 1.0; + } + let x = if translation.x < 0.0 { shape.x1 } else { shape.x2 }; + let translated_ratio = (self.x - x) / translation.x; + if translated_ratio >= 1.0 { + return 1.0; + } else if translated_ratio <= 0.0 { + return 0.0; + } + let translated_y1 = shape.y1 + translation.y * translated_ratio; + let translated_y2 = shape.y2 + translation.y * translated_ratio; + let translated_z1 = shape.z1 + translation.z * translated_ratio; + let translated_z2 = shape.z2 + translation.z * translated_ratio; + if (translated_y1..=translated_y2).contains(&self.y) && (translated_z1..=translated_z2).contains(&self.z) { + translated_ratio + } else { + 1.0 + } + } + + /// Returns the proportion of the translation that can be applied without absorbing `point` inside `shape` on the y axis + fn collide_y(&self, shape: &CollisionShape, translation: &Translation) -> f32 { + if translation.y == 0.0 { + return 1.0; + } + let y = if translation.y < 0.0 { shape.y1 } else { shape.y2 }; + let translated_ratio = (self.y - y) / translation.y; + if translated_ratio >= 1.0 { + return 1.0; + } else if translated_ratio <= 0.0 { + return 0.0; + } + let translated_x1 = shape.x1 + translation.x * translated_ratio; + let translated_x2 = shape.x2 + translation.x * translated_ratio; + let translated_z1 = shape.z1 + translation.z * translated_ratio; + let translated_z2 = shape.z2 + translation.z * translated_ratio; + if (translated_x1..=translated_x2).contains(&self.x) && (translated_z1..=translated_z2).contains(&self.z) { + translated_ratio + } else { + 1.0 + } + } + + /// Returns the proportion of the translation that can be applied without absorbing `point` inside `shape` on the z axis + fn collide_z(&self, shape: &CollisionShape, translation: &Translation) -> f32 { + if translation.z == 0.0 { + return 1.0; + } + let z = if translation.z < 0.0 { shape.z1 } else { shape.z2 }; + let translated_ratio = (self.z - z) / translation.z; + if translated_ratio >= 1.0 { + return 1.0; + } else if translated_ratio <= 0.0 { + return 0.0; + } + let translated_x1 = shape.x1 + translation.x * translated_ratio; + let translated_x2 = shape.x2 + translation.x * translated_ratio; + let translated_y1 = shape.y1 + translation.y * translated_ratio; + let translated_y2 = shape.y2 + translation.y * translated_ratio; + if (translated_x1..=translated_x2).contains(&self.x) && (translated_y1..=translated_y2).contains(&self.y) { + translated_ratio + } else { + 1.0 + } + } + + /// Returns the proportion of the translation that can be applied without absorbing `point` inside `shape` + fn collide(&self, shape: &CollisionShape, translation: &Translation) -> f32 { + min( + self.collide_x(shape, translation), + self.collide_y(shape, translation), + self.collide_z(shape, translation) + ) + } +} + +/// An iterator over the 8 corners of a [CollisionShape] +pub struct PointIter<'a> { shape: &'a CollisionShape, index: usize, } @@ -60,36 +164,32 @@ impl<'a> Iterator for PointIter<'a> { } } -impl CollisionShape { - const fn points(&self) -> PointIter { - PointIter { - shape: self, - index: 0, - } - } - - // TODO(perf): Return an iterator yielding blocks instead of a vec of blocks - fn containing_blocks(&self) -> Vec { - let mut result = Vec::new(); - for x in self.x1.floor() as i32..=self.x2.floor() as i32 { - for y in self.y1.floor() as i32..=self.y2.floor() as i32 { - for z in self.z1.floor() as i32..=self.z2.floor() as i32 { - let block = BlockPosition { x, y, z }; - result.push(block); - } - } - } - result - } -} - +/// Vector describing a movement #[derive(Debug, Clone, PartialEq)] -struct Translation { +pub struct Translation { x: f32, y: f32, z: f32, } +impl Translation { + /// Cuts the translation just enough so that the shape doesn't collide with the obstacle + fn prevent_collision(&mut self, object: &CollisionShape, obstacle: &CollisionShape) { + let mut limit = 1.0; + + for point in obstacle.points() { + limit = min2(limit, point.collide(object, self)); + if limit == 0.0 { + break; + } + } + + self.x *= limit; + self.y *= limit; + self.z *= limit; + } +} + impl std::ops::Add for Translation { type Output = Translation; @@ -154,100 +254,6 @@ impl std::ops::Mul for Translation { } } } - -fn is_inside(shape: &CollisionShape, point: Point) -> bool { - (shape.x1..=shape.x2).contains(&point.x) && (shape.y1..=shape.y2).contains(&point.y) && (shape.z1..=shape.z2).contains(&point.z) -} - -fn translation_limit_y(shape: &CollisionShape, translation: &Translation, point: &Point) -> f32 { - if translation.y == 0.0 { - return 1.0; - } - let y = if translation.y < 0.0 { shape.y1 } else { shape.y2 }; - let translated_ratio = (point.y - y) / translation.y; - if translated_ratio >= 1.0 { - return 1.0; - } else if translated_ratio <= 0.0 { - return 0.0; - } - let translated_x1 = shape.x1 + translation.x * translated_ratio; - let translated_x2 = shape.x2 + translation.x * translated_ratio; - let translated_z1 = shape.z1 + translation.z * translated_ratio; - let translated_z2 = shape.z2 + translation.z * translated_ratio; - if (translated_x1..=translated_x2).contains(&point.x) && (translated_z1..=translated_z2).contains(&point.z) { - translated_ratio - } else { - 1.0 - } -} - -fn translation_limit_x(shape: &CollisionShape, translation: &Translation, point: &Point) -> f32 { - if translation.x == 0.0 { - return 1.0; - } - let x = if translation.x < 0.0 { shape.x1 } else { shape.x2 }; - let translated_ratio = (point.x - x) / translation.x; - if translated_ratio >= 1.0 { - return 1.0; - } else if translated_ratio <= 0.0 { - return 0.0; - } - let translated_y1 = shape.y1 + translation.y * translated_ratio; - let translated_y2 = shape.y2 + translation.y * translated_ratio; - let translated_z1 = shape.z1 + translation.z * translated_ratio; - let translated_z2 = shape.z2 + translation.z * translated_ratio; - if (translated_y1..=translated_y2).contains(&point.y) && (translated_z1..=translated_z2).contains(&point.z) { - translated_ratio - } else { - 1.0 - } -} - -fn translation_limit_z(shape: &CollisionShape, translation: &Translation, point: &Point) -> f32 { - if translation.z == 0.0 { - return 1.0; - } - let z = if translation.z < 0.0 { shape.z1 } else { shape.z2 }; - let translated_ratio = (point.z - z) / translation.z; - if translated_ratio >= 1.0 { - return 1.0; - } else if translated_ratio <= 0.0 { - return 0.0; - } - let translated_x1 = shape.x1 + translation.x * translated_ratio; - let translated_x2 = shape.x2 + translation.x * translated_ratio; - let translated_y1 = shape.y1 + translation.y * translated_ratio; - let translated_y2 = shape.y2 + translation.y * translated_ratio; - if (translated_x1..=translated_x2).contains(&point.x) && (translated_y1..=translated_y2).contains(&point.y) { - translated_ratio - } else { - 1.0 - } -} - -fn translation_limit(shape: &CollisionShape, translation: &Translation, point: &Point) -> f32 { - min( - translation_limit_x(shape, translation, point), - translation_limit_y(shape, translation, point), - translation_limit_z(shape, translation, point) - ) -} - -fn restrict(translating: &CollisionShape, translation: &mut Translation, obstacle: &CollisionShape) { - let mut limit = 1.0; - - for point in obstacle.points() { - limit = min2(limit, translation_limit(translating, translation, &point)); - if limit == 0.0 { - break; - } - } - - translation.x *= limit; - translation.y *= limit; - translation.z *= limit; -} - fn ray_cast(position: CollisionShape, movement: Translation) -> Vec { let final_position = position.clone() + &movement; let mut result = Vec::new(); @@ -305,49 +311,49 @@ mod tests { // Boxes are just next to each other and pushing against each other let shape2 = shape1.clone() + Translation { x: 1.0, y: 0.0, z: 0.0 }; let mut translation = Translation { x: -1.0, y: 0.0, z: 0.0 }; - restrict(&shape2, &mut translation, &shape1); + translation.prevent_collision(&shape2, &shape1); assert_eq!(translation, Translation { x: 0.0, y: 0.0, z: 0.0 }); // Boxes are one block away but one comes and pushes the other let shape2 = shape1.clone() + Translation { x: 2.0, y: 0.0, z: 0.0 }; let mut translation = Translation { x: -2.0, y: 0.0, z: 0.0 }; - restrict(&shape2, &mut translation, &shape1); + translation.prevent_collision(&shape2, &shape1); assert_eq!(translation, Translation { x: -1.0, y: 0.0, z: 0.0 }); // The other way around let shape2 = shape1.clone() + Translation { x: -2.0, y: 0.0, z: 0.0 }; let mut translation = Translation { x: 2.0, y: 0.0, z: 0.0 }; - restrict(&shape2, &mut translation, &shape1); + translation.prevent_collision(&shape2, &shape1); assert_eq!(translation, Translation { x: 1.0, y: 0.0, z: 0.0 }); // From top let shape2 = shape1.clone() + Translation { x: 0.0, y: 2.0, z: 0.0 }; let mut translation = Translation { x: 0.0, y: -2.0, z: 0.0 }; - restrict(&shape2, &mut translation, &shape1); + translation.prevent_collision(&shape2, &shape1); assert_eq!(translation, Translation { x: 0.0, y: -1.0, z: 0.0 }); // On last axis let shape2 = shape1.clone() + Translation { x: 0.0, y: 0.0, z: 2.0 }; let mut translation = Translation { x: 0.0, y: 0.0, z: -2.0 }; - restrict(&shape2, &mut translation, &shape1); + translation.prevent_collision(&shape2, &shape1); assert_eq!(translation, Translation { x: 0.0, y: 0.0, z: -1.0 }); // Colliding on corner let shape2 = shape1.clone() + Translation { x: 2.0, y: 2.0, z: 2.0 }; let mut translation = Translation { x: -2.0, y: -2.0, z: -2.0 }; - restrict(&shape2, &mut translation, &shape1); + translation.prevent_collision(&shape2, &shape1); assert_eq!(translation, Translation { x: -1.0, y: -1.0, z: -1.0 }); // Colliding with offset on other axis let shape2 = shape1.clone() + Translation { x: 2.0, y: 0.5, z: 0.0 }; let mut translation = Translation { x: -2.0, y: 0.0, z: 0.0 }; - restrict(&shape2, &mut translation, &shape1); + translation.prevent_collision(&shape2, &shape1); assert_eq!(translation, Translation { x: -1.0, y: 0.0, z: 0.0 }); // Colliding when already inside let shape2 = shape1.clone() + Translation { x: 0.5, y: 0.5, z: 0.5 }; let mut translation = Translation { x: -0.5, y: -0.5, z: -0.5 }; - restrict(&shape2, &mut translation, &shape1); + translation.prevent_collision(&shape2, &shape1); assert_eq!(translation, Translation { x: 0.0, y: 0.0, z: 0.0 }); } diff --git a/minecraft-server/src/world/map.rs b/minecraft-server/src/world/map.rs index e3e8f8d9..4ee84858 100644 --- a/minecraft-server/src/world/map.rs +++ b/minecraft-server/src/world/map.rs @@ -271,6 +271,10 @@ impl WorldMap { inner_get_block(self, position, block).await; } + pub async fn test_move(&self, object: CollisionShape, movement: Translation) -> Translation { + todo!() + } + pub async fn load(&self, position: ChunkColumnPosition) { let chunk = ChunkColumn::flat(); // TODO: load from disk let shard = position.shard(self.shard_count); From 51ecd33e5288341b535b52e1caed64c8ac25e626 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Mon, 13 Nov 2023 22:18:24 +0100 Subject: [PATCH 74/89] Make collisions pub --- minecraft-server/src/world/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/minecraft-server/src/world/mod.rs b/minecraft-server/src/world/mod.rs index 07eef017..802749bf 100644 --- a/minecraft-server/src/world/mod.rs +++ b/minecraft-server/src/world/mod.rs @@ -9,7 +9,7 @@ use map::*; mod ecs; use ecs::*; mod collisions; -use collisions::*; +pub use collisions::*; /// World is the union of the map and entities. /// World handles loaded chunks and entities. From f10ffe20e4bf8c6097d7e3bd2bced90e8128311f Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Mon, 13 Nov 2023 22:41:32 +0100 Subject: [PATCH 75/89] Add try_move --- minecraft-server/src/world/map.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/minecraft-server/src/world/map.rs b/minecraft-server/src/world/map.rs index 4ee84858..e5a798b2 100644 --- a/minecraft-server/src/world/map.rs +++ b/minecraft-server/src/world/map.rs @@ -271,8 +271,23 @@ impl WorldMap { inner_get_block(self, position, block).await; } - pub async fn test_move(&self, object: CollisionShape, movement: Translation) -> Translation { - todo!() + pub async fn try_move(&self, object: CollisionShape, movement: Translation) -> Translation { + // TODO(perf): Optimize Map.try_move by preventing block double-checking + // Also lock the map only once + let movement_fragments = movement.clone().fragment(&object); + let mut validated = Translation{ x: 0.0, y: 0.0, z: 0.0 }; + for fragment in movement_fragments { + let validating = validated.clone() + fragment; + let translated_object = object.clone() + &validating; + for block in translated_object.containing_blocks() { + let block = self.get_block(block).await; + if block.block_id() != 0 { + return validated; + } + } + validated = validating; + } + movement } pub async fn load(&self, position: ChunkColumnPosition) { From 3263ef9924dca485d3c08f483a9d84b945a88235 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Mon, 13 Nov 2023 23:48:00 +0100 Subject: [PATCH 76/89] Fix collision fragment --- minecraft-server/src/world/collisions.rs | 116 ++++++++++++----------- minecraft-server/src/world/map.rs | 26 +++++ 2 files changed, 86 insertions(+), 56 deletions(-) diff --git a/minecraft-server/src/world/collisions.rs b/minecraft-server/src/world/collisions.rs index 3df436f3..5e26fcc1 100644 --- a/minecraft-server/src/world/collisions.rs +++ b/minecraft-server/src/world/collisions.rs @@ -1,8 +1,8 @@ use super::*; -/// Returns minimum of two floats +/// Returns minimum of two floats, but not NaN fn min2(a: f32, b: f32) -> f32 { - if a < b { + if a < b || b.is_nan() { a } else { b @@ -17,12 +17,12 @@ fn min(a: f32, b: f32, c: f32) -> f32 { /// An object in space #[derive(Debug, Clone, PartialEq)] pub struct CollisionShape { - x1: f32, - y1: f32, - z1: f32, - x2: f32, - y2: f32, - z2: f32, + pub x1: f32, + pub y1: f32, + pub z1: f32, + pub x2: f32, + pub y2: f32, + pub z2: f32, } impl CollisionShape { @@ -34,7 +34,7 @@ impl CollisionShape { } // TODO(perf): Return an iterator yielding blocks instead of a vec of blocks - fn containing_blocks(&self) -> Vec { + pub fn containing_blocks(&self) -> Vec { let mut result = Vec::new(); for x in self.x1.floor() as i32..=self.x2.floor() as i32 { for y in self.y1.floor() as i32..=self.y2.floor() as i32 { @@ -167,9 +167,9 @@ impl<'a> Iterator for PointIter<'a> { /// Vector describing a movement #[derive(Debug, Clone, PartialEq)] pub struct Translation { - x: f32, - y: f32, - z: f32, + pub x: f32, + pub y: f32, + pub z: f32, } impl Translation { @@ -188,6 +188,46 @@ impl Translation { self.y *= limit; self.z *= limit; } + + // TODO: turn CollisionShape.fragment into an iterator + pub fn fragment(self, position: &CollisionShape) -> Vec { + let final_position = position.clone() + &self; + let mut result = Vec::new(); + let mut current_position = position.clone(); + //result.extend(position.containing_blocks().into_iter()); + while current_position != final_position { + let x_dist = if self.x > 0.0 { + let next_x = current_position.x2.floor()+1.0; + (next_x - current_position.x2).abs() + } else { + let next_x = current_position.x1.ceil()-1.0; + (next_x - current_position.x1).abs() + }; + let y_dist = if self.y > 0.0 { + let next_y = current_position.y2.floor()+1.0; + (next_y - current_position.y2).abs() + } else { + let next_y = current_position.y1.ceil()-1.0; + (next_y - current_position.y1).abs() + }; + let z_dist = if self.z > 0.0 { + let next_z = current_position.z2.floor()+1.0; + (next_z - current_position.z2).abs() + } else { + let next_z = current_position.z1.ceil()-1.0; + (next_z - current_position.z1).abs() + }; + let x_time = x_dist / self.x.abs(); + let y_time = y_dist / self.y.abs(); + let z_time = z_dist / self.z.abs(); + let time = min(x_time, y_time, z_time); + println!("pos{current_position:?} dist({x_dist}, {y_dist}, {z_dist}) time({x_time}, {y_time}, {z_time}) time({time})"); + let mini_translation = self.clone() * time; + current_position += &mini_translation; + result.push(mini_translation); + } + result + } } impl std::ops::Add for Translation { @@ -254,44 +294,6 @@ impl std::ops::Mul for Translation { } } } -fn ray_cast(position: CollisionShape, movement: Translation) -> Vec { - let final_position = position.clone() + &movement; - let mut result = Vec::new(); - let mut next_position = position.clone(); - //result.extend(position.containing_blocks().into_iter()); - while next_position != final_position { - let x_dist = if movement.x > 0.0 { - let next_x = next_position.x1.floor()+1.0; - (next_x - next_position.x1).abs() - } else { - let next_x = next_position.x2.floor()-1.0; - (next_x - next_position.x2).abs() - }; - let y_dist = if movement.y > 0.0 { - let next_y = next_position.y1.floor()+1.0; - (next_y - next_position.y1).abs() - } else { - let next_y = next_position.y2.floor()-1.0; - (next_y - next_position.y2).abs() - }; - let z_dist = if movement.z > 0.0 { - let next_z = next_position.z1.floor()+1.0; - (next_z - next_position.z1).abs() - } else { - let next_z = next_position.z2.floor()-1.0; - (next_z - next_position.z2).abs() - }; - let x_time = x_dist / movement.x.abs(); - let y_time = y_dist / movement.y.abs(); - let z_time = z_dist / movement.z.abs(); - let time = min(x_time, y_time, z_time); - println!("pos{next_position:?} dist({x_dist}, {y_dist}, {z_dist}) time({x_time}, {y_time}, {z_time}) time({time})"); - let mini_translation = movement.clone() * time; - next_position += &mini_translation; - result.push(mini_translation); - } - result -} #[cfg(test)] mod tests { @@ -368,16 +370,18 @@ mod tests { z2: 1.0, }; + // TODO: add real test value comparisons + let movement = Translation { x: 5.0, y: 0.0, z: 0.0 }; - let mini_movements = ray_cast(shape.clone(), movement); - println!("{mini_movements:#?}"); + let fragments = movement.fragment(&shape); + println!("{fragments:#?}"); let movement = Translation { x: 4.0, y: 2.0, z: 0.0 }; - let mini_movements = ray_cast(shape.clone(), movement); - println!("{mini_movements:#?}"); + let mini_movements = movement.fragment(&shape); + println!("{fragments:#?}"); let movement = Translation { x: 2.38, y: 1.82, z: 1.0 }; - let mini_movements = ray_cast(shape.clone(), movement); - println!("{mini_movements:#?}"); + let mini_movements = movement.fragment(&shape); + println!("{fragments:#?}"); } } diff --git a/minecraft-server/src/world/map.rs b/minecraft-server/src/world/map.rs index e5a798b2..181794e8 100644 --- a/minecraft-server/src/world/map.rs +++ b/minecraft-server/src/world/map.rs @@ -450,4 +450,30 @@ mod tests { } } } + + #[tokio::test] + async fn test_try_move() { + let map = WorldMap::new(1); + map.load(ChunkColumnPosition { cx: 0, cz: 0 }).await; + let bounding_box = CollisionShape { + x1: 0.0, + y1: 0.0, + z1: 0.0, + x2: 1.0, + y2: 1.0, + z2: 1.0, + }; + + // Position on ground and try to go through it + //let positionned_box = bounding_box.clone() + &Translation { x: 0.0, y: -3.0*16.0, z: 0.0 }; + //let movement = Translation { x: 0.0, y: -10.0, z: 0.0 }; + //let movement = map.try_move(positionned_box, movement).await; + //assert_eq!(movement, Translation { x: 0.0, y: 0.0, z: 0.0 }); // It doesn't get through + + // Place it a little above ground + let positionned_box = bounding_box.clone() + &Translation { x: 0.0, y: -3.0*16.0 + 1.0, z: 0.0 }; + let movement = Translation { x: 0.0, y: -10.0, z: 0.0 }; + let movement = map.try_move(positionned_box, movement).await; + assert_eq!(movement, Translation { x: 0.0, y: -1.0, z: 0.0 }); // It falls down but doesn't get through + } } From 8c1aa2a1c89638f823c803af5106e68147d06a11 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Mon, 13 Nov 2023 23:58:10 +0100 Subject: [PATCH 77/89] Improve algorithm to reduce imprecisions --- minecraft-server/src/world/collisions.rs | 46 +++++++++++++++--------- minecraft-server/src/world/map.rs | 8 ++--- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/minecraft-server/src/world/collisions.rs b/minecraft-server/src/world/collisions.rs index 5e26fcc1..4fbc4d05 100644 --- a/minecraft-server/src/world/collisions.rs +++ b/minecraft-server/src/world/collisions.rs @@ -189,41 +189,45 @@ impl Translation { self.z *= limit; } + fn norm(&self) -> f32 { + (self.x * self.x + self.y * self.y + self.z * self.z).sqrt() + } + // TODO: turn CollisionShape.fragment into an iterator pub fn fragment(self, position: &CollisionShape) -> Vec { - let final_position = position.clone() + &self; let mut result = Vec::new(); - let mut current_position = position.clone(); + let mut fragmented = Translation { x: 0.0, y: 0.0, z: 0.0 }; + //let mut current_position = position.clone(); //result.extend(position.containing_blocks().into_iter()); - while current_position != final_position { + while fragmented.norm() < self.norm() { let x_dist = if self.x > 0.0 { - let next_x = current_position.x2.floor()+1.0; - (next_x - current_position.x2).abs() + let next_x = (position.x2 + fragmented.x).floor()+1.0; + (next_x - (position.x2 + fragmented.x)).abs() } else { - let next_x = current_position.x1.ceil()-1.0; - (next_x - current_position.x1).abs() + let next_x = (position.x1 + fragmented.x).ceil()-1.0; + (next_x - (position.x1 + fragmented.x)).abs() }; let y_dist = if self.y > 0.0 { - let next_y = current_position.y2.floor()+1.0; - (next_y - current_position.y2).abs() + let next_y = (position.y2 + fragmented.y).floor()+1.0; + (next_y - (position.y2 + fragmented.y)).abs() } else { - let next_y = current_position.y1.ceil()-1.0; - (next_y - current_position.y1).abs() + let next_y = (position.y1 + fragmented.y).ceil()-1.0; + (next_y - (position.y1 + fragmented.y)).abs() }; let z_dist = if self.z > 0.0 { - let next_z = current_position.z2.floor()+1.0; - (next_z - current_position.z2).abs() + let next_z = (position.z2 + fragmented.z).floor()+1.0; + (next_z - (position.z2 + fragmented.z)).abs() } else { - let next_z = current_position.z1.ceil()-1.0; - (next_z - current_position.z1).abs() + let next_z = (position.z1 + fragmented.z).ceil()-1.0; + (next_z - (position.z1 + fragmented.z)).abs() }; let x_time = x_dist / self.x.abs(); let y_time = y_dist / self.y.abs(); let z_time = z_dist / self.z.abs(); let time = min(x_time, y_time, z_time); - println!("pos{current_position:?} dist({x_dist}, {y_dist}, {z_dist}) time({x_time}, {y_time}, {z_time}) time({time})"); + println!("pos{fragmented:?} dist({x_dist}, {y_dist}, {z_dist}) time({x_time}, {y_time}, {z_time}) time({time})"); let mini_translation = self.clone() * time; - current_position += &mini_translation; + fragmented += &mini_translation; result.push(mini_translation); } result @@ -242,6 +246,14 @@ impl std::ops::Add for Translation { } } +impl std::ops::AddAssign<&Translation> for Translation { + fn add_assign(&mut self, rhs: &Translation) { + self.x += rhs.x; + self.y += rhs.y; + self.z += rhs.z; + } +} + impl std::ops::Add for CollisionShape { type Output = CollisionShape; diff --git a/minecraft-server/src/world/map.rs b/minecraft-server/src/world/map.rs index 181794e8..6244edbd 100644 --- a/minecraft-server/src/world/map.rs +++ b/minecraft-server/src/world/map.rs @@ -465,10 +465,10 @@ mod tests { }; // Position on ground and try to go through it - //let positionned_box = bounding_box.clone() + &Translation { x: 0.0, y: -3.0*16.0, z: 0.0 }; - //let movement = Translation { x: 0.0, y: -10.0, z: 0.0 }; - //let movement = map.try_move(positionned_box, movement).await; - //assert_eq!(movement, Translation { x: 0.0, y: 0.0, z: 0.0 }); // It doesn't get through + let positionned_box = bounding_box.clone() + &Translation { x: 0.0, y: -3.0*16.0, z: 0.0 }; + let movement = Translation { x: 0.0, y: -10.0, z: 0.0 }; + let movement = map.try_move(positionned_box, movement).await; + assert_eq!(movement, Translation { x: 0.0, y: 0.0, z: 0.0 }); // It doesn't get through // Place it a little above ground let positionned_box = bounding_box.clone() + &Translation { x: 0.0, y: -3.0*16.0 + 1.0, z: 0.0 }; From 02a97c7d08347c4a8f128e5e73e074871753d500 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Tue, 14 Nov 2023 00:05:11 +0100 Subject: [PATCH 78/89] Improve precision --- minecraft-server/src/world/collisions.rs | 44 ++++++++++++------------ minecraft-server/src/world/map.rs | 6 ++++ 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/minecraft-server/src/world/collisions.rs b/minecraft-server/src/world/collisions.rs index 4fbc4d05..70912a19 100644 --- a/minecraft-server/src/world/collisions.rs +++ b/minecraft-server/src/world/collisions.rs @@ -1,7 +1,7 @@ use super::*; /// Returns minimum of two floats, but not NaN -fn min2(a: f32, b: f32) -> f32 { +fn min2(a: f64, b: f64) -> f64 { if a < b || b.is_nan() { a } else { @@ -10,19 +10,19 @@ fn min2(a: f32, b: f32) -> f32 { } /// Returns minimum of three floats -fn min(a: f32, b: f32, c: f32) -> f32 { +fn min(a: f64, b: f64, c: f64) -> f64 { min2(min2(a, b), c) } /// An object in space #[derive(Debug, Clone, PartialEq)] pub struct CollisionShape { - pub x1: f32, - pub y1: f32, - pub z1: f32, - pub x2: f32, - pub y2: f32, - pub z2: f32, + pub x1: f64, + pub y1: f64, + pub z1: f64, + pub x2: f64, + pub y2: f64, + pub z2: f64, } impl CollisionShape { @@ -50,9 +50,9 @@ impl CollisionShape { /// A point in space pub struct Point { - x: f32, - y: f32, - z: f32, + x: f64, + y: f64, + z: f64, } impl Point { @@ -62,7 +62,7 @@ impl Point { } /// Returns the proportion of the translation that can be applied without absorbing `point` inside `shape` on the x axis - fn collide_x(&self, shape: &CollisionShape, translation: &Translation) -> f32 { + fn collide_x(&self, shape: &CollisionShape, translation: &Translation) -> f64 { if translation.x == 0.0 { return 1.0; } @@ -85,7 +85,7 @@ impl Point { } /// Returns the proportion of the translation that can be applied without absorbing `point` inside `shape` on the y axis - fn collide_y(&self, shape: &CollisionShape, translation: &Translation) -> f32 { + fn collide_y(&self, shape: &CollisionShape, translation: &Translation) -> f64 { if translation.y == 0.0 { return 1.0; } @@ -108,7 +108,7 @@ impl Point { } /// Returns the proportion of the translation that can be applied without absorbing `point` inside `shape` on the z axis - fn collide_z(&self, shape: &CollisionShape, translation: &Translation) -> f32 { + fn collide_z(&self, shape: &CollisionShape, translation: &Translation) -> f64 { if translation.z == 0.0 { return 1.0; } @@ -131,7 +131,7 @@ impl Point { } /// Returns the proportion of the translation that can be applied without absorbing `point` inside `shape` - fn collide(&self, shape: &CollisionShape, translation: &Translation) -> f32 { + fn collide(&self, shape: &CollisionShape, translation: &Translation) -> f64 { min( self.collide_x(shape, translation), self.collide_y(shape, translation), @@ -167,9 +167,9 @@ impl<'a> Iterator for PointIter<'a> { /// Vector describing a movement #[derive(Debug, Clone, PartialEq)] pub struct Translation { - pub x: f32, - pub y: f32, - pub z: f32, + pub x: f64, + pub y: f64, + pub z: f64, } impl Translation { @@ -189,7 +189,7 @@ impl Translation { self.z *= limit; } - fn norm(&self) -> f32 { + fn norm(&self) -> f64 { (self.x * self.x + self.y * self.y + self.z * self.z).sqrt() } @@ -225,7 +225,7 @@ impl Translation { let y_time = y_dist / self.y.abs(); let z_time = z_dist / self.z.abs(); let time = min(x_time, y_time, z_time); - println!("pos{fragmented:?} dist({x_dist}, {y_dist}, {z_dist}) time({x_time}, {y_time}, {z_time}) time({time})"); + //println!("pos{fragmented:?} dist({x_dist}, {y_dist}, {z_dist}) time({x_time}, {y_time}, {z_time}) time({time})"); let mini_translation = self.clone() * time; fragmented += &mini_translation; result.push(mini_translation); @@ -295,10 +295,10 @@ impl std::ops::AddAssign<&Translation> for CollisionShape { } } -impl std::ops::Mul for Translation { +impl std::ops::Mul for Translation { type Output = Translation; - fn mul(self, rhs: f32) -> Self::Output { + fn mul(self, rhs: f64) -> Self::Output { Translation { x: self.x * rhs, y: self.y * rhs, diff --git a/minecraft-server/src/world/map.rs b/minecraft-server/src/world/map.rs index 6244edbd..f89a6d1e 100644 --- a/minecraft-server/src/world/map.rs +++ b/minecraft-server/src/world/map.rs @@ -475,5 +475,11 @@ mod tests { let movement = Translation { x: 0.0, y: -10.0, z: 0.0 }; let movement = map.try_move(positionned_box, movement).await; assert_eq!(movement, Translation { x: 0.0, y: -1.0, z: 0.0 }); // It falls down but doesn't get through + + // Place it above but not on round coordinates + let positionned_box = bounding_box.clone() + &Translation { x: 0.0, y: -3.0*16.0 + 1.1, z: 0.2 }; + let movement = Translation { x: 2.0, y: -10.0, z: 0.0 }; + let movement = map.try_move(positionned_box, movement).await; + assert_eq!(movement, Translation { x: 0.2200000000000003, y: -1.1000000000000014, z: 0.0 }); // It falls down but doesn't get through } } From 22f9f0e299db64779514614a636a01f23ad4ff55 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Tue, 14 Nov 2023 00:21:51 +0100 Subject: [PATCH 79/89] Fix last fragment --- minecraft-server/src/world/collisions.rs | 49 +++++++++++++++++++----- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/minecraft-server/src/world/collisions.rs b/minecraft-server/src/world/collisions.rs index 70912a19..bcf38277 100644 --- a/minecraft-server/src/world/collisions.rs +++ b/minecraft-server/src/world/collisions.rs @@ -230,6 +230,18 @@ impl Translation { fragmented += &mini_translation; result.push(mini_translation); } + // Last one might be too long + if let Some(last) = result.pop() { + let final_position = position.clone() + self; + let previous_fragmented = fragmented.clone() - last; + let previous_position = position.clone() + previous_fragmented; + let difference = Translation { + x: final_position.x1 - previous_position.x1, + y: final_position.y1 - previous_position.y1, + z: final_position.z1 - previous_position.z1, + }; + result.push(difference); + } result } } @@ -254,6 +266,18 @@ impl std::ops::AddAssign<&Translation> for Translation { } } +impl std::ops::Sub for Translation { + type Output = Translation; + + fn sub(self, rhs: Translation) -> Self::Output { + Translation { + x: self.x - rhs.x, + y: self.y - rhs.y, + z: self.z - rhs.z, + } + } +} + impl std::ops::Add for CollisionShape { type Output = CollisionShape; @@ -382,18 +406,23 @@ mod tests { z2: 1.0, }; - // TODO: add real test value comparisons - - let movement = Translation { x: 5.0, y: 0.0, z: 0.0 }; + let movement = Translation { x: 3.0, y: 0.0, z: 0.0 }; let fragments = movement.fragment(&shape); - println!("{fragments:#?}"); + assert_eq!(fragments, vec![Translation { x: 1.0, y: 0.0, z: 0.0 }; 3]); - let movement = Translation { x: 4.0, y: 2.0, z: 0.0 }; - let mini_movements = movement.fragment(&shape); - println!("{fragments:#?}"); + let movement = Translation { x: 2.3, y: 0.0, z: 0.0 }; + let fragments = movement.fragment(&shape); + assert_eq!(fragments, vec![Translation { x: 1.0, y: 0.0, z: 0.0 }, Translation { x: 1.0, y: 0.0, z: 0.0 }, Translation { x: 0.2999999999999998, y: 0.0, z: 0.0 }]); - let movement = Translation { x: 2.38, y: 1.82, z: 1.0 }; - let mini_movements = movement.fragment(&shape); - println!("{fragments:#?}"); + let movement = Translation { x: 1.0, y: 0.75, z: 0.0 } * 4.0; + let fragments = movement.fragment(&shape); + assert_eq!(fragments, vec![ + Translation { x: 1.0, y: 0.75, z: 0.0 }, + Translation { x: 0.3333333333333333, y: 0.25, z: 0.0 }, + Translation { x: 0.666666666666667, y: 0.5000000000000002, z: 0.0 }, + Translation { x: 0.6666666666666666, y: 0.5, z: 0.0 }, + Translation { x: 0.3333333333333335, y: 0.2500000000000001, z: 0.0 }, + Translation { x: 1.0, y: 0.75, z: 0.0 }] + ); } } From e6fe0b2b7471fdcd50523cce0aeddd2ab84f06b3 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Tue, 14 Nov 2023 08:34:19 +0100 Subject: [PATCH 80/89] Finish implementing gravity --- minecraft-server/src/entities/entity.rs | 4 +-- .../src/entities/tasks/gravity.rs | 32 +++++++++++++++++-- minecraft-server/src/player_handler/play.rs | 4 +-- minecraft-server/src/world/change.rs | 4 +-- minecraft-server/src/world/collisions.rs | 8 +++++ minecraft-server/src/world/map.rs | 10 +++--- minecraft-server/src/world/mod.rs | 4 +++ 7 files changed, 53 insertions(+), 13 deletions(-) diff --git a/minecraft-server/src/entities/entity.rs b/minecraft-server/src/entities/entity.rs index 73684d2a..2546c976 100644 --- a/minecraft-server/src/entities/entity.rs +++ b/minecraft-server/src/entities/entity.rs @@ -9,7 +9,7 @@ use super::*; )] pub struct Entity { pub position: Position, - pub velocity: Position, + pub velocity: Translation, pub pitch: f32, pub yaw: f32, pub is_on_fire: bool, @@ -38,7 +38,7 @@ impl Default for Entity { fn default() -> Self { Entity { position: Position { x: 0.0, y: 0.0, z: 0.0 }, - velocity: Position { x: 0.0, y: 0.0, z: 0.0 }, + velocity: Translation { x: 0.0, y: 0.0, z: 0.0 }, pitch: 0.0, yaw: 0.0, is_on_fire: false, diff --git a/minecraft-server/src/entities/tasks/gravity.rs b/minecraft-server/src/entities/tasks/gravity.rs index d3df0e79..153b39a4 100644 --- a/minecraft-server/src/entities/tasks/gravity.rs +++ b/minecraft-server/src/entities/tasks/gravity.rs @@ -1,3 +1,5 @@ +use crate::CollisionShape; + use super::*; pub async fn gravity_task(h: Handler, mut server_msg_rcvr: BroadcastReceiver) where AnyEntity: TryAsEntityRef { @@ -8,10 +10,36 @@ pub async fn gravity_task(h: Handler, mut server_msg_rcv continue; } + let Some((mut position, mut velocity, width, height)) = h.observe(|entity| { + let entity = entity.get_entity(); + (entity.position.clone(), entity.velocity.clone(), 0.6, 1.95) + }).await else { return; }; + + velocity.y -= 9.81/20.0; + let bounding_box = CollisionShape { + x1: position.x - width/2.0, + y1: position.y, + z1: position.z - width/2.0, + x2: position.x + width/2.0, + y2: position.y + height, + z2: position.z + width/2.0, + }; + let allowed_velocity = h.world.try_move(&bounding_box, &velocity).await; + if velocity.x != allowed_velocity.x { + velocity.x = 0.0; + } + if velocity.y != allowed_velocity.y { + velocity.y = 0.0; + } + if velocity.z != allowed_velocity.z { + velocity.z = 0.0; + } + position += allowed_velocity; + h.mutate(|entity| { let entity = entity.get_entity_mut(); - entity.velocity.y -= 9.81/20.0; - entity.position += entity.velocity.clone(); + entity.velocity = velocity; + entity.position = position; ((), EntityChanges::position()+EntityChanges::velocity()) }).await; } diff --git a/minecraft-server/src/player_handler/play.rs b/minecraft-server/src/player_handler/play.rs index d8d98403..cd3ce91e 100644 --- a/minecraft-server/src/player_handler/play.rs +++ b/minecraft-server/src/player_handler/play.rs @@ -40,7 +40,7 @@ impl PlayerHandler { }).await; } - async fn on_entity_spawned(&mut self, eid: Eid, uuid: UUID, ty: NetworkEntity, position: Position, pitch: f32, yaw: f32, head_yaw: f32, data: u32, velocity: Position, metadata: ()) { + async fn on_entity_spawned(&mut self, eid: Eid, uuid: UUID, ty: NetworkEntity, position: Position, pitch: f32, yaw: f32, head_yaw: f32, data: u32, velocity: Translation, metadata: ()) { self.entity_prev_positions.insert(eid, position.clone()); self.send_packet(PlayClientbound::SpawnEntity { id: VarInt(eid as i32), @@ -70,7 +70,7 @@ impl PlayerHandler { }).await; } - async fn on_entity_velocity_changes(&mut self, eid: Eid, velocity: Position) { + async fn on_entity_velocity_changes(&mut self, eid: Eid, velocity: Translation) { self.send_packet(PlayClientbound::SetEntityVelocity { entity_id: VarInt(eid as i32), velocity_x: (velocity.x * 8000.0) as i16, diff --git a/minecraft-server/src/world/change.rs b/minecraft-server/src/world/change.rs index 49ba04ba..d63974f3 100644 --- a/minecraft-server/src/world/change.rs +++ b/minecraft-server/src/world/change.rs @@ -12,7 +12,7 @@ pub enum WorldChange { yaw: f32, head_yaw: f32, data: u32, - velocity: Position, + velocity: Translation, metadata: (), }, EntityDispawned { @@ -28,7 +28,7 @@ pub enum WorldChange { }, EntityVelocity { eid: Eid, - velocity: Position, + velocity: Translation, }, EntityPitch { eid: Eid, diff --git a/minecraft-server/src/world/collisions.rs b/minecraft-server/src/world/collisions.rs index bcf38277..0fafcf22 100644 --- a/minecraft-server/src/world/collisions.rs +++ b/minecraft-server/src/world/collisions.rs @@ -319,6 +319,14 @@ impl std::ops::AddAssign<&Translation> for CollisionShape { } } +impl std::ops::AddAssign for Position { + fn add_assign(&mut self, rhs: Translation) { + self.x += rhs.x; + self.y += rhs.y; + self.z += rhs.z; + } +} + impl std::ops::Mul for Translation { type Output = Translation; diff --git a/minecraft-server/src/world/map.rs b/minecraft-server/src/world/map.rs index f89a6d1e..1f39dc4c 100644 --- a/minecraft-server/src/world/map.rs +++ b/minecraft-server/src/world/map.rs @@ -271,7 +271,7 @@ impl WorldMap { inner_get_block(self, position, block).await; } - pub async fn try_move(&self, object: CollisionShape, movement: Translation) -> Translation { + pub async fn try_move(&self, object: &CollisionShape, movement: &Translation) -> Translation { // TODO(perf): Optimize Map.try_move by preventing block double-checking // Also lock the map only once let movement_fragments = movement.clone().fragment(&object); @@ -287,7 +287,7 @@ impl WorldMap { } validated = validating; } - movement + movement.clone() // Would be more logic if it returned validated, but this way we avoid precision errors } pub async fn load(&self, position: ChunkColumnPosition) { @@ -467,19 +467,19 @@ mod tests { // Position on ground and try to go through it let positionned_box = bounding_box.clone() + &Translation { x: 0.0, y: -3.0*16.0, z: 0.0 }; let movement = Translation { x: 0.0, y: -10.0, z: 0.0 }; - let movement = map.try_move(positionned_box, movement).await; + let movement = map.try_move(&positionned_box, &movement).await; assert_eq!(movement, Translation { x: 0.0, y: 0.0, z: 0.0 }); // It doesn't get through // Place it a little above ground let positionned_box = bounding_box.clone() + &Translation { x: 0.0, y: -3.0*16.0 + 1.0, z: 0.0 }; let movement = Translation { x: 0.0, y: -10.0, z: 0.0 }; - let movement = map.try_move(positionned_box, movement).await; + let movement = map.try_move(&positionned_box, &movement).await; assert_eq!(movement, Translation { x: 0.0, y: -1.0, z: 0.0 }); // It falls down but doesn't get through // Place it above but not on round coordinates let positionned_box = bounding_box.clone() + &Translation { x: 0.0, y: -3.0*16.0 + 1.1, z: 0.2 }; let movement = Translation { x: 2.0, y: -10.0, z: 0.0 }; - let movement = map.try_move(positionned_box, movement).await; + let movement = map.try_move(&positionned_box, &movement).await; assert_eq!(movement, Translation { x: 0.2200000000000003, y: -1.1000000000000014, z: 0.0 }); // It falls down but doesn't get through } } diff --git a/minecraft-server/src/world/mod.rs b/minecraft-server/src/world/mod.rs index dd95200a..23d74471 100644 --- a/minecraft-server/src/world/mod.rs +++ b/minecraft-server/src/world/mod.rs @@ -47,6 +47,10 @@ impl World { self.notify(&position.chunk_column(), WorldChange::Block(position, block)).await; } + pub async fn try_move(&self, object: &CollisionShape, movement: &Translation) -> Translation { + self.map.try_move(object, movement).await + } + pub async fn add_loader(&self, uuid: UUID) -> MpscReceiver { let (sender, receiver) = mpsc_channel(100); self.change_senders.write().await.insert(uuid, sender); From 4018403191507a4ce773ed11d5cbfa2a00d3fca3 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Tue, 14 Nov 2023 08:58:50 +0100 Subject: [PATCH 81/89] Generalize on AnyEntity --- minecraft-server/src/entities/mod.rs | 8 ++++++++ .../src/entities/tasks/gravity.rs | 19 ++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/minecraft-server/src/entities/mod.rs b/minecraft-server/src/entities/mod.rs index be07a9a8..5746a767 100644 --- a/minecraft-server/src/entities/mod.rs +++ b/minecraft-server/src/entities/mod.rs @@ -107,11 +107,19 @@ impl Handler where AnyEntity: TryAsEntityRef { }).await } + pub async fn observe_any(&self, observer: impl FnOnce(&AnyEntity) -> R) -> Option { + self.world.observe_entity(self.eid, observer).await + } + pub async fn mutate(&self, mutator: impl FnOnce(&mut T) -> (R, EntityChanges)) -> Option { self.world.mutate_entity(self.eid, move |entity| { mutator(entity.try_as_entity_mut().unwrap()) }).await } + + pub async fn mutate_any(&self, mutator: impl FnOnce(&mut AnyEntity) -> (R, EntityChanges)) -> Option { + self.world.mutate_entity(self.eid, mutator).await + } } pub enum AnyEntity { diff --git a/minecraft-server/src/entities/tasks/gravity.rs b/minecraft-server/src/entities/tasks/gravity.rs index 153b39a4..48954566 100644 --- a/minecraft-server/src/entities/tasks/gravity.rs +++ b/minecraft-server/src/entities/tasks/gravity.rs @@ -10,11 +10,22 @@ pub async fn gravity_task(h: Handler, mut server_msg_rcv continue; } - let Some((mut position, mut velocity, width, height)) = h.observe(|entity| { - let entity = entity.get_entity(); - (entity.position.clone(), entity.velocity.clone(), 0.6, 1.95) + // Get data from entity + let Some((mut position, mut velocity, network_entity)) = h.observe_any(|any_entity| { + let entity = any_entity.as_entity(); + let network_entity = any_entity.to_network(); + (entity.position.clone(), entity.velocity.clone(), network_entity) }).await else { return; }; + let (width, height) = match network_entity { + Some(network_entity) => (network_entity.width() as f64, network_entity.height() as f64), + None => { + warn!("Entity {} has no network entity", h.eid); // TODO(perf): Make gravity verify that the entity has bounding boxes at the start + return; + } + }; + + // Apply velocity and collisions velocity.y -= 9.81/20.0; let bounding_box = CollisionShape { x1: position.x - width/2.0, @@ -36,6 +47,8 @@ pub async fn gravity_task(h: Handler, mut server_msg_rcv } position += allowed_velocity; + // Mutate entity + // TODO(correctness): Before modifying entity values, we should ensure the original values we based the changes on are still the same h.mutate(|entity| { let entity = entity.get_entity_mut(); entity.velocity = velocity; From 0c0bf92d389c89726015a283f46213697c97e7e7 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Tue, 14 Nov 2023 08:59:49 +0100 Subject: [PATCH 82/89] Rename task gravity into newton --- minecraft-server/src/entities/entity.rs | 2 +- minecraft-server/src/entities/tasks/mod.rs | 4 ++-- minecraft-server/src/entities/tasks/{gravity.rs => newton.rs} | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) rename minecraft-server/src/entities/tasks/{gravity.rs => newton.rs} (93%) diff --git a/minecraft-server/src/entities/entity.rs b/minecraft-server/src/entities/entity.rs index 2546c976..44634410 100644 --- a/minecraft-server/src/entities/entity.rs +++ b/minecraft-server/src/entities/entity.rs @@ -30,7 +30,7 @@ pub struct Entity { impl Handler { async fn init(self, server_msg_rcvr: BroadcastReceiver) { - self.insert_task("gravity", tokio::spawn(gravity_task(self.clone(), server_msg_rcvr))).await; + self.insert_task("newton", tokio::spawn(newton_task(self.clone(), server_msg_rcvr))).await; } } diff --git a/minecraft-server/src/entities/tasks/mod.rs b/minecraft-server/src/entities/tasks/mod.rs index 064cd8f6..bc48155f 100644 --- a/minecraft-server/src/entities/tasks/mod.rs +++ b/minecraft-server/src/entities/tasks/mod.rs @@ -1,4 +1,4 @@ pub use super::*; -mod gravity; -pub use gravity::*; +mod newton; +pub use newton::*; diff --git a/minecraft-server/src/entities/tasks/gravity.rs b/minecraft-server/src/entities/tasks/newton.rs similarity index 93% rename from minecraft-server/src/entities/tasks/gravity.rs rename to minecraft-server/src/entities/tasks/newton.rs index 48954566..f319836f 100644 --- a/minecraft-server/src/entities/tasks/gravity.rs +++ b/minecraft-server/src/entities/tasks/newton.rs @@ -2,7 +2,7 @@ use crate::CollisionShape; use super::*; -pub async fn gravity_task(h: Handler, mut server_msg_rcvr: BroadcastReceiver) where AnyEntity: TryAsEntityRef { +pub async fn newton_task(h: Handler, mut server_msg_rcvr: BroadcastReceiver) where AnyEntity: TryAsEntityRef { loop { let msg = server_msg_rcvr.recv().await.unwrap(); From bd469f1507dd30e445527bda5134723ddf26dc02 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Tue, 14 Nov 2023 09:07:02 +0100 Subject: [PATCH 83/89] Optimize newton task using EntityChanges --- minecraft-server/src/entities/tasks/newton.rs | 14 ++++++++++-- minecraft-server/src/world/change.rs | 22 +++++++++++++++---- minecraft-server/src/world/collisions.rs | 4 ++++ minecraft-server/src/world/mod.rs | 8 +++---- 4 files changed, 38 insertions(+), 10 deletions(-) diff --git a/minecraft-server/src/entities/tasks/newton.rs b/minecraft-server/src/entities/tasks/newton.rs index f319836f..ecb5af92 100644 --- a/minecraft-server/src/entities/tasks/newton.rs +++ b/minecraft-server/src/entities/tasks/newton.rs @@ -26,6 +26,7 @@ pub async fn newton_task(h: Handler, mut server_msg_rcvr }; // Apply velocity and collisions + let mut changes = EntityChanges::nothing(); velocity.y -= 9.81/20.0; let bounding_box = CollisionShape { x1: position.x - width/2.0, @@ -38,22 +39,31 @@ pub async fn newton_task(h: Handler, mut server_msg_rcvr let allowed_velocity = h.world.try_move(&bounding_box, &velocity).await; if velocity.x != allowed_velocity.x { velocity.x = 0.0; + changes += EntityChanges::velocity(); } if velocity.y != allowed_velocity.y { velocity.y = 0.0; + changes += EntityChanges::velocity(); } if velocity.z != allowed_velocity.z { velocity.z = 0.0; + changes += EntityChanges::velocity(); + } + if !allowed_velocity.is_zero() { + changes += EntityChanges::position(); + position += allowed_velocity; } - position += allowed_velocity; // Mutate entity // TODO(correctness): Before modifying entity values, we should ensure the original values we based the changes on are still the same + if changes.nothing_changed() { + continue; + } h.mutate(|entity| { let entity = entity.get_entity_mut(); entity.velocity = velocity; entity.position = position; - ((), EntityChanges::position()+EntityChanges::velocity()) + ((), changes) }).await; } } diff --git a/minecraft-server/src/world/change.rs b/minecraft-server/src/world/change.rs index d63974f3..a14f736d 100644 --- a/minecraft-server/src/world/change.rs +++ b/minecraft-server/src/world/change.rs @@ -45,6 +45,10 @@ impl EntityChanges { EntityChanges(0) } + pub const fn nothing() -> EntityChanges { + EntityChanges(0) + } + pub const fn position() -> EntityChanges { EntityChanges(1) } @@ -61,19 +65,23 @@ impl EntityChanges { EntityChanges(1 << 3) } - pub fn has_position_changed(&self) -> bool { + pub const fn nothing_changed(&self) -> bool { + self.0 == 0 + } + + pub const fn position_changed(&self) -> bool { self.0 & 1 != 0 } - pub fn has_velocity_changed(&self) -> bool { + pub const fn velocity_changed(&self) -> bool { self.0 & (1 << 1) != 0 } - pub fn has_pitch_changed(&self) -> bool { + pub const fn pitch_changed(&self) -> bool { self.0 & (1 << 2) != 0 } - pub fn has_metadata_changed(&self) -> bool { + pub const fn metadata_changed(&self) -> bool { self.0 & (1 << 3) != 0 } } @@ -85,3 +93,9 @@ impl std::ops::Add for EntityChanges { EntityChanges(self.0 | rhs.0) } } + +impl std::ops::AddAssign for EntityChanges { + fn add_assign(&mut self, rhs: EntityChanges) { + self.0 |= rhs.0; + } +} diff --git a/minecraft-server/src/world/collisions.rs b/minecraft-server/src/world/collisions.rs index 0fafcf22..7f972628 100644 --- a/minecraft-server/src/world/collisions.rs +++ b/minecraft-server/src/world/collisions.rs @@ -193,6 +193,10 @@ impl Translation { (self.x * self.x + self.y * self.y + self.z * self.z).sqrt() } + pub fn is_zero(&self) -> bool { + self.x == 0.0 && self.y == 0.0 && self.z == 0.0 + } + // TODO: turn CollisionShape.fragment into an iterator pub fn fragment(self, position: &CollisionShape) -> Vec { let mut result = Vec::new(); diff --git a/minecraft-server/src/world/mod.rs b/minecraft-server/src/world/mod.rs index 23d74471..a113fb03 100644 --- a/minecraft-server/src/world/mod.rs +++ b/minecraft-server/src/world/mod.rs @@ -110,20 +110,20 @@ impl World { Some((r, changes)) => { // TODO: make only one lookup and group into a single message with optional fields let position = self.entities.observe_entity(eid, |e| e.as_entity().position.clone()).await?; - if changes.has_position_changed() { + if changes.position_changed() { self.notify(&position.chunk_column(), WorldChange::EntityPosition { eid, position: position.clone(), }).await; } - if changes.has_velocity_changed() { + if changes.velocity_changed() { let velocity = self.entities.observe_entity(eid, |e| e.as_entity().velocity.clone()).await?; self.notify(&position.chunk_column(), WorldChange::EntityVelocity { eid, velocity, }).await; } - if changes.has_pitch_changed() { + if changes.pitch_changed() { let (pitch, yaw, head_yaw) = self.entities.observe_entity(eid, |e| (e.as_entity().pitch, e.as_entity().yaw, e.as_other::().map(|e| e.head_yaw).unwrap_or(0.0))).await?; self.notify(&position.chunk_column(), WorldChange::EntityPitch { eid, @@ -132,7 +132,7 @@ impl World { head_yaw, }).await; } - if changes.has_metadata_changed() { + if changes.metadata_changed() { todo!() } Some(r) From c5532abf70521952de49d6590310d9ae4c59063f Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Tue, 14 Nov 2023 09:09:35 +0100 Subject: [PATCH 84/89] Fix issue with entity change detection --- minecraft-server/src/entities/tasks/newton.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/minecraft-server/src/entities/tasks/newton.rs b/minecraft-server/src/entities/tasks/newton.rs index ecb5af92..f9755baf 100644 --- a/minecraft-server/src/entities/tasks/newton.rs +++ b/minecraft-server/src/entities/tasks/newton.rs @@ -27,7 +27,8 @@ pub async fn newton_task(h: Handler, mut server_msg_rcvr // Apply velocity and collisions let mut changes = EntityChanges::nothing(); - velocity.y -= 9.81/20.0; + let mut new_velocity = velocity.clone(); + new_velocity.y -= 9.81/20.0; let bounding_box = CollisionShape { x1: position.x - width/2.0, y1: position.y, @@ -36,22 +37,22 @@ pub async fn newton_task(h: Handler, mut server_msg_rcvr y2: position.y + height, z2: position.z + width/2.0, }; - let allowed_velocity = h.world.try_move(&bounding_box, &velocity).await; - if velocity.x != allowed_velocity.x { + let new_velocity = h.world.try_move(&bounding_box, &new_velocity).await; + if velocity.x != new_velocity.x { velocity.x = 0.0; changes += EntityChanges::velocity(); } - if velocity.y != allowed_velocity.y { + if velocity.y != new_velocity.y { velocity.y = 0.0; changes += EntityChanges::velocity(); } - if velocity.z != allowed_velocity.z { + if velocity.z != new_velocity.z { velocity.z = 0.0; changes += EntityChanges::velocity(); } - if !allowed_velocity.is_zero() { + if !new_velocity.is_zero() { changes += EntityChanges::position(); - position += allowed_velocity; + position += new_velocity; } // Mutate entity From 40b36aef2d1ebf008639354e1d87a527eb85867b Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Tue, 14 Nov 2023 09:17:43 +0100 Subject: [PATCH 85/89] Add todo on air resistance --- minecraft-server/src/entities/tasks/newton.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/minecraft-server/src/entities/tasks/newton.rs b/minecraft-server/src/entities/tasks/newton.rs index f9755baf..21d981e8 100644 --- a/minecraft-server/src/entities/tasks/newton.rs +++ b/minecraft-server/src/entities/tasks/newton.rs @@ -55,6 +55,9 @@ pub async fn newton_task(h: Handler, mut server_msg_rcvr position += new_velocity; } + // TODO(feat): Apply air resistance to x and z velocity + // Keep in mind that velocity shouldn't flicker when constantly kept up by another task but slowed down in this task + // Mutate entity // TODO(correctness): Before modifying entity values, we should ensure the original values we based the changes on are still the same if changes.nothing_changed() { From 5c6aee4b1b4df082fdb156464634ffadb71ef03a Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Tue, 14 Nov 2023 21:47:08 +0100 Subject: [PATCH 86/89] Make player report its existence to ECS --- minecraft-server/src/player_handler/play.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/minecraft-server/src/player_handler/play.rs b/minecraft-server/src/player_handler/play.rs index cd3ce91e..c23e2833 100644 --- a/minecraft-server/src/player_handler/play.rs +++ b/minecraft-server/src/player_handler/play.rs @@ -1,6 +1,7 @@ use super::*; struct PlayerHandler { + eid: Eid, world: &'static World, game_mode: Gamemode, info: PlayerInfo, @@ -82,6 +83,13 @@ impl PlayerHandler { async fn on_move(&mut self) { let new_center_chunk = self.position.chunk(); + // Tell the ECS about the changes + self.world.mutate_entity(self.eid, |entity| { + let entity: &mut Entity = entity.try_as_entity_mut().unwrap(); // Cannot fail + entity.position = self.position.clone(); + ((), EntityChanges::position()) + }).await; + // Tell the client which chunk he is in if new_center_chunk == self.center_chunk { return }; self.send_packet(PlayClientbound::SetCenterChunk { chunk_x: VarInt(new_center_chunk.cx), chunk_z: VarInt(new_center_chunk.cz) }).await; @@ -208,8 +216,10 @@ impl PlayerHandler { pub async fn handle_player(stream: TcpStream, player_info: PlayerInfo, mut server_msg_rcvr: BroadcastReceiver, world: &'static World, mut change_receiver: MpscReceiver) -> Result<(), ()> { let (packet_sender, mut packet_receiver) = mpsc_channel(100); + let eid = world.spawn_entity(AnyEntity::Player(Player::default())).await; let mut handler = PlayerHandler { + eid, world, game_mode: Gamemode::Creative, position: Position { x: 0.0, y: 60.0, z: 0.0 }, @@ -227,6 +237,8 @@ pub async fn handle_player(stream: TcpStream, player_info: PlayerInfo, mut serve info: player_info, }; + // TODO: player should load existing entities + for cx in -3..=3 { for cz in -3..=3 { handler.loaded_chunks.insert(ChunkColumnPosition { cx, cz }); From da6f6bb718b7550e8acc6df4f6c3352d8dba9890 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Tue, 14 Nov 2023 23:16:55 +0100 Subject: [PATCH 87/89] Make zombie follow player --- minecraft-entities-derive/src/lib.rs | 6 ++ minecraft-server/src/entities/entity.rs | 2 +- minecraft-server/src/entities/mod.rs | 4 +- minecraft-server/src/entities/monsters/mod.rs | 2 +- .../src/entities/monsters/zombies.rs | 55 +++++++++++++++++++ minecraft-server/src/entities/player.rs | 9 +++ minecraft-server/src/player_handler/play.rs | 4 +- minecraft-server/src/world/collisions.rs | 13 ++++- minecraft-server/src/world/ecs.rs | 30 ++++++++-- minecraft-server/src/world/mod.rs | 10 +++- 10 files changed, 120 insertions(+), 15 deletions(-) diff --git a/minecraft-entities-derive/src/lib.rs b/minecraft-entities-derive/src/lib.rs index f8278b0d..73aee6aa 100644 --- a/minecraft-entities-derive/src/lib.rs +++ b/minecraft-entities-derive/src/lib.rs @@ -195,6 +195,12 @@ pub fn MinecraftEntity(attr: proc_macro::TokenStream, item: proc_macro::TokenStr codes.push(code); let code = quote! { + impl From<#this> for AnyEntity { + fn from(val: #this) -> Self { + AnyEntity::#this(val) + } + } + #[cfg(test)] #[automatically_derived] #[test] diff --git a/minecraft-server/src/entities/entity.rs b/minecraft-server/src/entities/entity.rs index 44634410..59da82ac 100644 --- a/minecraft-server/src/entities/entity.rs +++ b/minecraft-server/src/entities/entity.rs @@ -29,7 +29,7 @@ pub struct Entity { } impl Handler { - async fn init(self, server_msg_rcvr: BroadcastReceiver) { + pub async fn init(self, server_msg_rcvr: BroadcastReceiver) { self.insert_task("newton", tokio::spawn(newton_task(self.clone(), server_msg_rcvr))).await; } } diff --git a/minecraft-server/src/entities/mod.rs b/minecraft-server/src/entities/mod.rs index 5746a767..909251c0 100644 --- a/minecraft-server/src/entities/mod.rs +++ b/minecraft-server/src/entities/mod.rs @@ -103,7 +103,7 @@ impl Handler where AnyEntity: TryAsEntityRef { pub async fn observe(&self, observer: impl FnOnce(&T) -> R) -> Option { self.world.observe_entity(self.eid, move |entity| { - observer(entity.try_as_entity_ref().unwrap()) + observer(entity.try_as_entity_ref().expect("Called observe on the wrong entity")) }).await } @@ -113,7 +113,7 @@ impl Handler where AnyEntity: TryAsEntityRef { pub async fn mutate(&self, mutator: impl FnOnce(&mut T) -> (R, EntityChanges)) -> Option { self.world.mutate_entity(self.eid, move |entity| { - mutator(entity.try_as_entity_mut().unwrap()) + mutator(entity.try_as_entity_mut().expect("Called mutate on the wrong entity")) }).await } diff --git a/minecraft-server/src/entities/monsters/mod.rs b/minecraft-server/src/entities/monsters/mod.rs index 487ccff8..80ea6cdc 100644 --- a/minecraft-server/src/entities/monsters/mod.rs +++ b/minecraft-server/src/entities/monsters/mod.rs @@ -1,4 +1,4 @@ -use super::*; +pub use super::*; mod piglin; pub use piglin::*; diff --git a/minecraft-server/src/entities/monsters/zombies.rs b/minecraft-server/src/entities/monsters/zombies.rs index ff2cd43c..45306920 100644 --- a/minecraft-server/src/entities/monsters/zombies.rs +++ b/minecraft-server/src/entities/monsters/zombies.rs @@ -1,3 +1,5 @@ +use minecraft_protocol::network; + use super::*; #[derive(Default)] @@ -5,6 +7,9 @@ use super::*; inheritable, ancestors { Monster, PathfinderMob, Mob, LivingEntity, Entity }, descendants { ZombieVillager, Husk, Drowned, ZombifiedPiglin }, + defines { + Entity.init(self, server_msg_rcvr: BroadcastReceiver); + } )] pub struct Zombie { pub monster: Monster, @@ -13,6 +18,56 @@ pub struct Zombie { pub is_becoming_drowned: bool, } +impl Handler { + pub async fn init(self, server_msg_rcvr: BroadcastReceiver) { + self.insert_task("newton", tokio::spawn(newton_task(self.clone(), server_msg_rcvr.resubscribe()))).await; + self.insert_task("zombie-ai", tokio::spawn(zombie_ai_task(self.clone(), server_msg_rcvr))).await; + } +} + +pub async fn zombie_ai_task(h: Handler, mut server_msg_rcvr: BroadcastReceiver) where AnyEntity: TryAsEntityRef { + loop { + let msg = server_msg_rcvr.recv().await.unwrap(); + + if !matches!(&msg, &ServerMessage::Tick) { + continue; + } + + let self_position = h.observe(|e| e.get_entity().position.clone()).await.unwrap(); + let chunk = self_position.chunk_column(); + let player_positions = h.world.observe_entities(chunk, |entity| { + let network_entity = entity.to_network().unwrap(); + TryAsEntityRef::::try_as_entity_ref(entity).map(|player| { + (player.get_entity().position.clone(), network_entity) + }) + }).await; + + let Some((target_position, network_entity)) = player_positions.get(0) else { continue }; + let target_object = CollisionShape { + x1: target_position.x - network_entity.width() as f64 / 2.0, + y1: target_position.y, + z1: target_position.z - network_entity.width() as f64 / 2.0, + x2: target_position.x + network_entity.width() as f64 / 2.0, + y2: target_position.y + network_entity.height() as f64, + z2: target_position.z + network_entity.width() as f64 / 2.0, + }; + + let mut translation = Translation { + x: target_position.x - self_position.x, + y: target_position.y - self_position.y, + z: target_position.z - self_position.z, + }; + translation.set_norm(0.23000000417232513); + + let authorized_translation = h.world.try_move(&target_object, &translation).await; + + h.mutate(|e| { + e.get_entity_mut().position += authorized_translation; + ((), EntityChanges::position()) + }).await; + } +} + #[derive(Default)] #[MinecraftEntity( ancestors { Zombie, Monster, PathfinderMob, Mob, LivingEntity, Entity }, diff --git a/minecraft-server/src/entities/player.rs b/minecraft-server/src/entities/player.rs index 1d2a7d18..b1fe0cac 100644 --- a/minecraft-server/src/entities/player.rs +++ b/minecraft-server/src/entities/player.rs @@ -2,6 +2,9 @@ use super::*; #[MinecraftEntity( ancestors { LivingEntity, Entity }, + defines { + Entity.init(self, server_msg_rcvr: BroadcastReceiver); + } )] pub struct Player { pub living_entity: LivingEntity, @@ -19,6 +22,12 @@ pub struct Player { pub right_shoulder_entity: NbtTag, } +impl Handler { + pub async fn init(self, server_msg_rcvr: BroadcastReceiver) { + //self.insert_task("newton", tokio::spawn(newton_task(self.clone(), server_msg_rcvr))).await; + } +} + impl Default for Player { fn default() -> Self { Player { diff --git a/minecraft-server/src/player_handler/play.rs b/minecraft-server/src/player_handler/play.rs index c23e2833..0e80f42a 100644 --- a/minecraft-server/src/player_handler/play.rs +++ b/minecraft-server/src/player_handler/play.rs @@ -206,7 +206,7 @@ impl PlayerHandler { let mut position = self.position.clone(); position.y += 20.0; zombie.get_entity_mut().position = position; - self.world.spawn_entity(AnyEntity::Zombie(zombie)).await; + self.world.spawn_entity::(AnyEntity::Zombie(zombie)).await; } } packet => warn!("Unsupported packet received: {packet:?}"), @@ -216,7 +216,7 @@ impl PlayerHandler { pub async fn handle_player(stream: TcpStream, player_info: PlayerInfo, mut server_msg_rcvr: BroadcastReceiver, world: &'static World, mut change_receiver: MpscReceiver) -> Result<(), ()> { let (packet_sender, mut packet_receiver) = mpsc_channel(100); - let eid = world.spawn_entity(AnyEntity::Player(Player::default())).await; + let eid = world.spawn_entity::(AnyEntity::Player(Player::default())).await; let mut handler = PlayerHandler { eid, diff --git a/minecraft-server/src/world/collisions.rs b/minecraft-server/src/world/collisions.rs index 7f972628..407d36d0 100644 --- a/minecraft-server/src/world/collisions.rs +++ b/minecraft-server/src/world/collisions.rs @@ -189,10 +189,21 @@ impl Translation { self.z *= limit; } - fn norm(&self) -> f64 { + pub fn norm(&self) -> f64 { (self.x * self.x + self.y * self.y + self.z * self.z).sqrt() } + /// Keep direction but change norm + pub fn set_norm(&mut self, norm: f64) { + let current_norm = self.norm(); + if current_norm == 0.0 { + return; + } + self.x *= norm / current_norm; + self.y *= norm / current_norm; + self.z *= norm / current_norm; + } + pub fn is_zero(&self) -> bool { self.x == 0.0 && self.y == 0.0 && self.z == 0.0 } diff --git a/minecraft-server/src/world/ecs.rs b/minecraft-server/src/world/ecs.rs index d725bfe6..143ee0f5 100644 --- a/minecraft-server/src/world/ecs.rs +++ b/minecraft-server/src/world/ecs.rs @@ -12,7 +12,7 @@ pub struct Entities { pub entities: RwLock>, /// A hashmap of chunk positions to get a list of entities in a chunk - pub chunks: RwLock>>, + pub chunks: RwLock>>, pub uuids: RwLock>, pub entity_tasks: RwLock>>, } @@ -34,6 +34,22 @@ impl Entities { self.entities.read().await.get(&eid).map(observer) } + /// Observe entities in a chunk through a closure + /// That closure will be applied to each entity, and the results will be returned in a vector + pub(super) async fn observe_entities(&self, chunk: ChunkColumnPosition, mut observer: impl FnMut(&AnyEntity) -> Option) -> Vec { + let entities = self.chunks.read().await; + let Some(eids) = entities.get(&chunk) else {return Vec::new()}; + let mut results = Vec::with_capacity(eids.len()); + for eid in eids { + if let Some(entity) = self.entities.read().await.get(eid) { + if let Some(r) = observer(entity) { + results.push(r); + } + } + } + results + } + /// Mutate an entity through a closure pub(super) async fn mutate_entity(&self, eid: Eid, mutator: impl FnOnce(&mut AnyEntity) -> (R, EntityChanges)) -> Option<(R, EntityChanges)> { let mut entities = self.entities.write().await; @@ -42,8 +58,8 @@ impl Entities { let prev_position = entity.as_entity().position.clone(); let r = mutator(entity); if prev_position != entity.as_entity().position { - let old_chunk = prev_position.chunk(); - let new_chunk = entity.as_entity().position.chunk(); + let old_chunk = prev_position.chunk_column(); + let new_chunk = entity.as_entity().position.chunk_column(); drop(entities); let mut chunks = self.chunks.write().await; chunks.entry(old_chunk).and_modify(|set| { set.remove(&eid); }); // TODO: ensure it gets removed @@ -55,19 +71,21 @@ impl Entities { } } - pub(super) async fn spawn_entity(&self, entity: AnyEntity, world: &'static World, receiver: BroadcastReceiver) -> (Eid, UUID) { + pub(super) async fn spawn_entity(&self, entity: AnyEntity, world: &'static World, receiver: BroadcastReceiver) -> (Eid, UUID) + where AnyEntity: TryAsEntityRef, Handler: EntityExt + { let eid = self.eid_counter.fetch_add(1, std::sync::atomic::Ordering::SeqCst); let uuid = self.uuid_counter.fetch_add(1, std::sync::atomic::Ordering::SeqCst) as u128; let mut entities = self.entities.write().await; let mut chunks = self.chunks.write().await; let mut uuids = self.uuids.write().await; - chunks.entry(entity.as_entity().position.chunk()).or_insert(HashSet::new()).insert(eid); + chunks.entry(entity.as_entity().position.chunk_column()).or_insert(HashSet::new()).insert(eid); entities.insert(eid, entity); uuids.insert(uuid, eid); drop(entities); drop(chunks); drop(uuids); - let h = Handler::::assume(eid, world); // TODO other than zombie + let h = Handler::::assume(eid, world); h.init(receiver).await; (eid, uuid) } diff --git a/minecraft-server/src/world/mod.rs b/minecraft-server/src/world/mod.rs index a113fb03..b7c04ae7 100644 --- a/minecraft-server/src/world/mod.rs +++ b/minecraft-server/src/world/mod.rs @@ -77,14 +77,16 @@ impl World { } } - pub async fn spawn_entity(&'static self, entity: AnyEntity) -> Eid { + pub async fn spawn_entity(&'static self, entity: AnyEntity) -> Eid + where AnyEntity: TryAsEntityRef, Handler: EntityExt + { let position = entity.as_entity().position.clone(); let velocity = entity.as_entity().velocity.clone(); let ty = entity.to_network().unwrap(); // TODO: error handling let pitch = entity.as_entity().pitch; let yaw = entity.as_entity().yaw; let head_yaw = entity.as_other::().map(|e| e.head_yaw).unwrap_or(0.0); - let (eid, uuid) = self.entities.spawn_entity(entity, self, self.receiver.resubscribe()).await; + let (eid, uuid) = self.entities.spawn_entity::(entity, self, self.receiver.resubscribe()).await; self.notify(&position.chunk_column(), WorldChange::EntitySpawned { eid, uuid, @@ -104,6 +106,10 @@ impl World { self.entities.observe_entity(eid, observer).await } + pub async fn observe_entities(&self, chunk: ChunkColumnPosition, observer: impl FnMut(&AnyEntity) -> Option) -> Vec { + self.entities.observe_entities(chunk, observer).await + } + pub async fn mutate_entity(&self, eid: Eid, mutator: impl FnOnce(&mut AnyEntity) -> (R, EntityChanges)) -> Option { // TODO change events match self.entities.mutate_entity(eid, mutator).await { From 5258bfd6f426f62927fc6a899b2e3089b9bbd6d9 Mon Sep 17 00:00:00 2001 From: Dimitri Date: Fri, 17 Nov 2023 13:46:27 +0100 Subject: [PATCH 88/89] fix warning --- minecraft-server/src/world/map.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/minecraft-server/src/world/map.rs b/minecraft-server/src/world/map.rs index 1f39dc4c..687769bf 100644 --- a/minecraft-server/src/world/map.rs +++ b/minecraft-server/src/world/map.rs @@ -274,7 +274,7 @@ impl WorldMap { pub async fn try_move(&self, object: &CollisionShape, movement: &Translation) -> Translation { // TODO(perf): Optimize Map.try_move by preventing block double-checking // Also lock the map only once - let movement_fragments = movement.clone().fragment(&object); + let movement_fragments = movement.clone().fragment(object); let mut validated = Translation{ x: 0.0, y: 0.0, z: 0.0 }; for fragment in movement_fragments { let validating = validated.clone() + fragment; From 400d2f91708c1d4598630da2f60758fa6ad2613e Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Sun, 19 Nov 2023 00:42:37 +0100 Subject: [PATCH 89/89] Update minecraft-server/src/world/collisions.rs Co-authored-by: DimitriTimoz <45998396+DimitriTimoz@users.noreply.github.com> --- minecraft-server/src/world/collisions.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/minecraft-server/src/world/collisions.rs b/minecraft-server/src/world/collisions.rs index 407d36d0..723684a9 100644 --- a/minecraft-server/src/world/collisions.rs +++ b/minecraft-server/src/world/collisions.rs @@ -2,10 +2,10 @@ use super::*; /// Returns minimum of two floats, but not NaN fn min2(a: f64, b: f64) -> f64 { - if a < b || b.is_nan() { - a - } else { + if a > b { b + } else { + a } }