diff --git a/src/lua/client/mod.rs b/src/lua/client/mod.rs index 3d971ef..a4c7849 100644 --- a/src/lua/client/mod.rs +++ b/src/lua/client/mod.rs @@ -60,6 +60,8 @@ impl UserData for Client { fn add_methods>(m: &mut M) { m.add_async_method("attack", interaction::attack); + m.add_async_method("find_all_entities", world::find_all_entities); + m.add_async_method("find_all_players", world::find_all_players); m.add_async_method("find_entities", world::find_entities); m.add_async_method("find_players", world::find_players); m.add_async_method("go_to", movement::go_to); diff --git a/src/lua/client/world.rs b/src/lua/client/world/mod.rs similarity index 50% rename from src/lua/client/world.rs rename to src/lua/client/world/mod.rs index ad500a2..3cc8806 100644 --- a/src/lua/client/world.rs +++ b/src/lua/client/world/mod.rs @@ -1,3 +1,6 @@ +#[macro_use] +mod queries; + use super::{Client, Direction, Vec3}; use azalea::{ BlockPos, @@ -48,100 +51,90 @@ pub fn find_blocks( .collect()) } +pub async fn find_all_entities(lua: Lua, client: UserDataRef, (): ()) -> Result> { + let mut matched = Vec::new(); + for (position, custom_name, kind, uuid, direction, id, owner_uuid, pose) in + get_entities!(client) + { + let table = lua.create_table()?; + table.set("position", position)?; + table.set("custom_name", custom_name)?; + table.set("kind", kind)?; + table.set("uuid", uuid)?; + table.set("direction", direction)?; + table.set("id", id)?; + table.set( + "owner_uuid", + owner_uuid.and_then(|v| *v).map(|v| v.to_string()), + )?; + table.set("pose", pose)?; + matched.push(table); + } + Ok(matched) +} + pub async fn find_entities( lua: Lua, client: UserDataRef, filter_fn: Function, ) -> Result> { - let entities = { - let mut ecs = client.ecs.lock(); - ecs.query::<( - &AzaleaPosition, - &CustomName, - &EntityKind, - &EntityUuid, - &LookDirection, - &MinecraftEntityId, - Option<&Owneruuid>, - &Pose, - )>() - .iter(&ecs) - .map( - |(position, custom_name, kind, uuid, direction, id, owner_uuid, pose)| { - ( - Vec3::from(position), - custom_name.as_ref().map(ToString::to_string), - kind.to_string(), - uuid.to_string(), - Direction::from(direction), - id.0, - owner_uuid.map(ToOwned::to_owned), - *pose as u8, - ) - }, - ) - .collect::>() - }; - let mut matched = Vec::new(); - for (position, custom_name, kind, uuid, direction, id, owner_uuid, pose) in entities { - let entity = lua.create_table()?; - entity.set("position", position)?; - entity.set("custom_name", custom_name)?; - entity.set("kind", kind)?; - entity.set("uuid", uuid)?; - entity.set("direction", direction)?; - entity.set("id", id)?; - if let Some(v) = owner_uuid - && let Some(uuid) = *v - { - entity.set("owner_uuid", uuid.to_string())?; - } - entity.set("pose", pose)?; - if filter_fn.call_async::(&entity).await? { - matched.push(entity); + for (position, custom_name, kind, uuid, direction, id, owner_uuid, pose) in + get_entities!(client) + { + let table = lua.create_table()?; + table.set("position", position)?; + table.set("custom_name", custom_name)?; + table.set("kind", kind)?; + table.set("uuid", uuid)?; + table.set("direction", direction)?; + table.set("id", id)?; + table.set( + "owner_uuid", + owner_uuid.and_then(|v| *v).map(|v| v.to_string()), + )?; + table.set("pose", pose)?; + if filter_fn.call_async::(&table).await? { + matched.push(table); } } Ok(matched) } -pub async fn find_players(lua: Lua, client: UserDataRef, (): ()) -> Result> { - let entities = { - let mut ecs = client.ecs.lock(); - ecs.query_filtered::<( - &MinecraftEntityId, - &EntityUuid, - &EntityKind, - &AzaleaPosition, - &LookDirection, - &Pose, - ), (With, Without)>() - .iter(&ecs) - .map(|(id, uuid, kind, position, direction, pose)| { - ( - id.0, - uuid.to_string(), - kind.to_string(), - Vec3::from(position), - Direction::from(direction), - *pose as u8, - ) - }) - .collect::>() - }; - - let mut players = Vec::new(); - for (id, uuid, kind, position, direction, pose) in entities { - let entity = lua.create_table()?; - entity.set("id", id)?; - entity.set("uuid", uuid)?; - entity.set("kind", kind)?; - entity.set("position", position)?; - entity.set("direction", direction)?; - entity.set("pose", pose)?; - players.push(entity); +pub async fn find_all_players(lua: Lua, client: UserDataRef, (): ()) -> Result> { + let mut matched = Vec::new(); + for (id, uuid, kind, position, direction, pose) in get_players!(client) { + let table = lua.create_table()?; + table.set("id", id)?; + table.set("uuid", uuid)?; + table.set("kind", kind)?; + table.set("position", position)?; + table.set("direction", direction)?; + table.set("pose", pose)?; + matched.push(table); } - Ok(players) + Ok(matched) +} + +pub async fn find_players( + lua: Lua, + client: UserDataRef, + filter_fn: Function, +) -> Result> { + let mut matched = Vec::new(); + for (id, uuid, kind, position, direction, pose) in get_players!(client) { + let table = lua.create_table()?; + table.set("id", id)?; + table.set("uuid", uuid)?; + table.set("kind", kind)?; + table.set("position", position)?; + table.set("direction", direction)?; + table.set("pose", pose)?; + if filter_fn.call_async::(&table).await? { + matched.push(table); + } + } + Ok(matched) } pub fn get_block_state(_lua: &Lua, client: &Client, position: Vec3) -> Result> { diff --git a/src/lua/client/world/queries.rs b/src/lua/client/world/queries.rs new file mode 100644 index 0000000..3ba0808 --- /dev/null +++ b/src/lua/client/world/queries.rs @@ -0,0 +1,59 @@ +#[macro_export] +macro_rules! get_entities { + ($client:ident) => {{ + let mut ecs = $client.ecs.lock(); + ecs.query::<( + &AzaleaPosition, + &CustomName, + &EntityKind, + &EntityUuid, + &LookDirection, + &MinecraftEntityId, + Option<&Owneruuid>, + &Pose, + )>() + .iter(&ecs) + .map( + |(position, custom_name, kind, uuid, direction, id, owner_uuid, pose)| { + ( + Vec3::from(position), + custom_name.as_ref().map(ToString::to_string), + kind.to_string(), + uuid.to_string(), + Direction::from(direction), + id.0, + owner_uuid.map(ToOwned::to_owned), + *pose as u8, + ) + }, + ) + .collect::>() + }}; +} + +#[macro_export] +macro_rules! get_players { + ($client:ident) => {{ + let mut ecs = $client.ecs.lock(); + ecs.query_filtered::<( + &MinecraftEntityId, + &EntityUuid, + &EntityKind, + &AzaleaPosition, + &LookDirection, + &Pose, + ), (With, Without)>() + .iter(&ecs) + .map(|(id, uuid, kind, position, direction, pose)| { + ( + id.0, + uuid.to_string(), + kind.to_string(), + Vec3::from(position), + Direction::from(direction), + *pose as u8, + ) + }) + .collect::>() + }}; +}