From 29a8c9fcf2eb4836f9d92c1d55471be8a15701fb Mon Sep 17 00:00:00 2001
From: ErrorNoInternet <errornointernet@envs.net>
Date: Sat, 1 Mar 2025 00:21:03 -0500
Subject: [PATCH] feat(client): add specialized find_players method as an
 optimization

---
 src/lua/client/mod.rs   |  1 +
 src/lua/client/world.rs | 43 +++++++++++++++++++++++++++++++++++++++--
 2 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/src/lua/client/mod.rs b/src/lua/client/mod.rs
index f5bf063..0905b6a 100644
--- a/src/lua/client/mod.rs
+++ b/src/lua/client/mod.rs
@@ -60,6 +60,7 @@ impl UserData for Client {
     fn add_methods<M: UserDataMethods<Self>>(m: &mut M) {
         m.add_async_method("attack", interaction::attack);
         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);
         m.add_async_method("look_at", movement::look_at);
         m.add_async_method("mine", interaction::mine);
diff --git a/src/lua/client/world.rs b/src/lua/client/world.rs
index 929f8ea..c707b26 100644
--- a/src/lua/client/world.rs
+++ b/src/lua/client/world.rs
@@ -3,10 +3,10 @@ use azalea::{
     BlockPos,
     auto_tool::AutoToolClientExt,
     blocks::{BlockState, BlockStates},
-    ecs::query::Without,
+    ecs::query::{With, Without},
     entity::{
         Dead, EntityKind, EntityUuid, LookDirection, Pose, Position as AzaleaPosition,
-        metadata::CustomName,
+        metadata::{CustomName, Player},
     },
     world::{InstanceName, MinecraftEntityId},
 };
@@ -96,6 +96,45 @@ pub async fn find_entities(
     Ok(matched)
 }
 
+pub async fn find_players(lua: Lua, client: UserDataRef<Client>, (): ()) -> Result<Vec<Table>> {
+    let entities = {
+        let mut ecs = client.ecs.lock();
+        ecs.query_filtered::<(
+            &MinecraftEntityId,
+            &EntityUuid,
+            &EntityKind,
+            &AzaleaPosition,
+            &LookDirection,
+            &Pose,
+        ), (With<Player>, Without<Dead>)>()
+            .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::<Vec<_>>()
+    };
+
+    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);
+    }
+    Ok(players)
+}
+
 pub fn get_block_state(_lua: &Lua, client: &Client, position: Vec3) -> Result<Option<u16>> {
     #[allow(clippy::cast_possible_truncation)]
     Ok(client