From 8547ea04ab3fd5be452d6f06faa41fcfc4b4e2dd Mon Sep 17 00:00:00 2001
From: ErrorNoInternet <errornointernet@envs.net>
Date: Sun, 16 Feb 2025 22:41:28 -0500
Subject: [PATCH] refactor(client): move fields into modules

---
 src/scripting/client/interaction.rs |  60 +++++------
 src/scripting/client/mod.rs         | 157 ++++++----------------------
 src/scripting/client/movement.rs    |  89 +++++++++++++++-
 src/scripting/client/state.rs       |  27 ++++-
 4 files changed, 172 insertions(+), 161 deletions(-)

diff --git a/src/scripting/client/interaction.rs b/src/scripting/client/interaction.rs
index 7ce34d9..a626340 100644
--- a/src/scripting/client/interaction.rs
+++ b/src/scripting/client/interaction.rs
@@ -2,36 +2,6 @@ use super::{Client, Vec3};
 use azalea::{BlockPos, BotClientExt, world::MinecraftEntityId};
 use mlua::{Lua, Result, UserDataRefMut};
 
-pub async fn mine(_lua: Lua, mut client: UserDataRefMut<Client>, position: Vec3) -> Result<()> {
-    #[allow(clippy::cast_possible_truncation)]
-    client
-        .inner
-        .as_mut()
-        .unwrap()
-        .mine(BlockPos::new(
-            position.x as i32,
-            position.y as i32,
-            position.z as i32,
-        ))
-        .await;
-    Ok(())
-}
-
-pub fn start_mining(_lua: &Lua, client: &mut Client, position: Vec3) -> Result<()> {
-    #[allow(clippy::cast_possible_truncation)]
-    client.inner.as_mut().unwrap().start_mining(BlockPos::new(
-        position.x as i32,
-        position.y as i32,
-        position.z as i32,
-    ));
-    Ok(())
-}
-
-pub fn set_mining(_lua: &Lua, client: &Client, mining: bool) -> Result<()> {
-    client.inner.as_ref().unwrap().left_click_mine(mining);
-    Ok(())
-}
-
 pub fn attack(_lua: &Lua, client: &mut Client, entity_id: u32) -> Result<()> {
     client
         .inner
@@ -50,3 +20,33 @@ pub fn block_interact(_lua: &Lua, client: &mut Client, position: Vec3) -> Result
     ));
     Ok(())
 }
+
+pub async fn mine(_lua: Lua, mut client: UserDataRefMut<Client>, position: Vec3) -> Result<()> {
+    #[allow(clippy::cast_possible_truncation)]
+    client
+        .inner
+        .as_mut()
+        .unwrap()
+        .mine(BlockPos::new(
+            position.x as i32,
+            position.y as i32,
+            position.z as i32,
+        ))
+        .await;
+    Ok(())
+}
+
+pub fn set_mining(_lua: &Lua, client: &Client, mining: bool) -> Result<()> {
+    client.inner.as_ref().unwrap().left_click_mine(mining);
+    Ok(())
+}
+
+pub fn start_mining(_lua: &Lua, client: &mut Client, position: Vec3) -> Result<()> {
+    #[allow(clippy::cast_possible_truncation)]
+    client.inner.as_mut().unwrap().start_mining(BlockPos::new(
+        position.x as i32,
+        position.y as i32,
+        position.z as i32,
+    ));
+    Ok(())
+}
diff --git a/src/scripting/client/mod.rs b/src/scripting/client/mod.rs
index 94b54d9..f52c09d 100644
--- a/src/scripting/client/mod.rs
+++ b/src/scripting/client/mod.rs
@@ -7,13 +7,8 @@ use super::{
     block::Block, direction::Direction, entity::Entity, fluid_state::FluidState, hunger::Hunger,
     vec3::Vec3,
 };
-use azalea::{
-    Client as AzaleaClient,
-    entity::metadata::{AirSupply, Score},
-    interact::HitResultComponent,
-    pathfinder::{ExecutingPath, Pathfinder},
-};
-use mlua::{Lua, Result, UserData, UserDataFields, UserDataMethods};
+use azalea::Client as AzaleaClient;
+use mlua::{Lua, Result, Table, UserData, UserDataFields, UserDataMethods};
 
 pub struct Client {
     pub inner: Option<AzaleaClient>,
@@ -21,123 +16,17 @@ pub struct Client {
 
 impl UserData for Client {
     fn add_fields<F: UserDataFields<Self>>(f: &mut F) {
-        f.add_field_method_get("air_supply", |_, this| {
-            Ok(this.inner.as_ref().unwrap().component::<AirSupply>().0)
-        });
-
-        f.add_field_method_get("direction", |_, this| {
-            let d = this.inner.as_ref().unwrap().direction();
-            Ok(Direction { x: d.0, y: d.1 })
-        });
-
-        f.add_field_method_get("eye_position", |_, this| {
-            let p = this.inner.as_ref().unwrap().eye_position();
-            Ok(Vec3 {
-                x: p.x,
-                y: p.y,
-                z: p.z,
-            })
-        });
-
-        f.add_field_method_get("health", |_, this| {
-            Ok(this.inner.as_ref().unwrap().health())
-        });
-
-        f.add_field_method_get("hunger", |_, this| {
-            let h = this.inner.as_ref().unwrap().hunger();
-            Ok(Hunger {
-                food: h.food,
-                saturation: h.saturation,
-            })
-        });
-
-        f.add_field_method_get("looking_at", |lua, this| {
-            let hr = this
-                .inner
-                .as_ref()
-                .unwrap()
-                .component::<HitResultComponent>();
-            Ok(if hr.miss {
-                None
-            } else {
-                let result = lua.create_table()?;
-                result.set(
-                    "position",
-                    Vec3 {
-                        x: f64::from(hr.block_pos.x),
-                        y: f64::from(hr.block_pos.y),
-                        z: f64::from(hr.block_pos.z),
-                    },
-                )?;
-                result.set("inside", hr.inside)?;
-                result.set("world_border", hr.world_border)?;
-                Some(result)
-            })
-        });
-
-        f.add_field_method_get("pathfinder", |lua, this| {
-            let client = this.inner.as_ref().unwrap();
-            let pathfinder = lua.create_table()?;
-            pathfinder.set(
-                "is_calculating",
-                client.component::<Pathfinder>().is_calculating,
-            )?;
-            pathfinder.set(
-                "is_executing",
-                if let Some(p) = client.get_component::<ExecutingPath>() {
-                    pathfinder.set(
-                        "last_reached_node",
-                        Vec3 {
-                            x: f64::from(p.last_reached_node.x),
-                            y: f64::from(p.last_reached_node.y),
-                            z: f64::from(p.last_reached_node.z),
-                        },
-                    )?;
-                    pathfinder.set(
-                        "last_node_reach_elapsed",
-                        p.last_node_reached_at.elapsed().as_millis(),
-                    )?;
-                    pathfinder.set("is_path_partial", p.is_path_partial)?;
-                    true
-                } else {
-                    false
-                },
-            )?;
-            Ok(pathfinder)
-        });
-
-        f.add_field_method_get("position", |_, this| {
-            let p = this.inner.as_ref().unwrap().position();
-            Ok(Vec3 {
-                x: p.x,
-                y: p.y,
-                z: p.z,
-            })
-        });
-
-        f.add_field_method_get("score", |_, this| {
-            Ok(this.inner.as_ref().unwrap().component::<Score>().0)
-        });
-
-        f.add_field_method_get("tab_list", |lua, this| {
-            let tab_list = lua.create_table()?;
-            for (uuid, player_info) in this.inner.as_ref().unwrap().tab_list() {
-                let player = lua.create_table()?;
-                player.set("gamemode", player_info.gamemode.name())?;
-                player.set("latency", player_info.latency)?;
-                player.set("name", player_info.profile.name)?;
-                player.set(
-                    "display_name",
-                    player_info.display_name.map(|n| n.to_string()),
-                )?;
-                tab_list.set(uuid.to_string(), player)?;
-            }
-            Ok(tab_list)
-        });
-
-        f.add_field_method_get("uuid", |_, this| {
-            Ok(this.inner.as_ref().unwrap().uuid().to_string())
-        });
+        f.add_field_method_get("air_supply", state::air_supply);
+        f.add_field_method_get("direction", movement::direction);
+        f.add_field_method_get("eye_position", movement::eye_position);
+        f.add_field_method_get("health", state::health);
+        f.add_field_method_get("hunger", state::hunger);
+        f.add_field_method_get("looking_at", movement::looking_at);
+        f.add_field_method_get("pathfinder", movement::pathfinder);
+        f.add_field_method_get("position", movement::position);
+        f.add_field_method_get("score", state::score);
+        f.add_field_method_get("tab_list", tab_list);
+        f.add_field_method_get("uuid", uuid);
     }
 
     fn add_methods<M: UserDataMethods<Self>>(m: &mut M) {
@@ -164,6 +53,26 @@ impl UserData for Client {
     }
 }
 
+fn tab_list(lua: &Lua, client: &Client) -> Result<Table> {
+    let tab_list = lua.create_table()?;
+    for (uuid, player_info) in client.inner.as_ref().unwrap().tab_list() {
+        let player = lua.create_table()?;
+        player.set("gamemode", player_info.gamemode.name())?;
+        player.set("latency", player_info.latency)?;
+        player.set("name", player_info.profile.name)?;
+        player.set(
+            "display_name",
+            player_info.display_name.map(|n| n.to_string()),
+        )?;
+        tab_list.set(uuid.to_string(), player)?;
+    }
+    Ok(tab_list)
+}
+
+fn uuid(_lua: &Lua, client: &Client) -> Result<String> {
+    Ok(client.inner.as_ref().unwrap().uuid().to_string())
+}
+
 fn chat(_lua: &Lua, client: &Client, message: String) -> Result<()> {
     client.inner.as_ref().unwrap().chat(&message);
     Ok(())
diff --git a/src/scripting/client/movement.rs b/src/scripting/client/movement.rs
index f1b40f1..6025add 100644
--- a/src/scripting/client/movement.rs
+++ b/src/scripting/client/movement.rs
@@ -1,16 +1,26 @@
-use super::{Client, Vec3};
+use super::{Client, Direction, Vec3};
 use azalea::{
     BlockPos, BotClientExt, Client as AzaleaClient, SprintDirection, WalkDirection,
+    interact::HitResultComponent,
     pathfinder::{
-        PathfinderClientExt,
+        ExecutingPath, Pathfinder, PathfinderClientExt,
         goals::{BlockPosGoal, Goal, RadiusGoal, ReachBlockPosGoal, XZGoal, YGoal},
     },
 };
 use mlua::{FromLua, Lua, Result, Table, Value};
 
-pub fn stop_pathfinding(_lua: &Lua, client: &Client, _: ()) -> Result<()> {
-    client.inner.as_ref().unwrap().stop_pathfinding();
-    Ok(())
+pub fn direction(_lua: &Lua, client: &Client) -> Result<Direction> {
+    let d = client.inner.as_ref().unwrap().direction();
+    Ok(Direction { x: d.0, y: d.1 })
+}
+
+pub fn eye_position(_lua: &Lua, client: &Client) -> Result<Vec3> {
+    let p = client.inner.as_ref().unwrap().eye_position();
+    Ok(Vec3 {
+        x: p.x,
+        y: p.y,
+        z: p.z,
+    })
 }
 
 pub fn goto(
@@ -102,6 +112,30 @@ pub fn jump(_lua: &Lua, client: &mut Client, _: ()) -> Result<()> {
     Ok(())
 }
 
+pub fn looking_at(lua: &Lua, client: &Client) -> Result<Option<Table>> {
+    let hr = client
+        .inner
+        .as_ref()
+        .unwrap()
+        .component::<HitResultComponent>();
+    Ok(if hr.miss {
+        None
+    } else {
+        let result = lua.create_table()?;
+        result.set(
+            "position",
+            Vec3 {
+                x: f64::from(hr.block_pos.x),
+                y: f64::from(hr.block_pos.y),
+                z: f64::from(hr.block_pos.z),
+            },
+        )?;
+        result.set("inside", hr.inside)?;
+        result.set("world_border", hr.world_border)?;
+        Some(result)
+    })
+}
+
 pub fn look_at(_lua: &Lua, client: &mut Client, position: Vec3) -> Result<()> {
     client
         .inner
@@ -111,6 +145,46 @@ pub fn look_at(_lua: &Lua, client: &mut Client, position: Vec3) -> Result<()> {
     Ok(())
 }
 
+pub fn pathfinder(lua: &Lua, client: &Client) -> Result<Table> {
+    let client = client.inner.as_ref().unwrap();
+    let pathfinder = lua.create_table()?;
+    pathfinder.set(
+        "is_calculating",
+        client.component::<Pathfinder>().is_calculating,
+    )?;
+    pathfinder.set(
+        "is_executing",
+        if let Some(p) = client.get_component::<ExecutingPath>() {
+            pathfinder.set(
+                "last_reached_node",
+                Vec3 {
+                    x: f64::from(p.last_reached_node.x),
+                    y: f64::from(p.last_reached_node.y),
+                    z: f64::from(p.last_reached_node.z),
+                },
+            )?;
+            pathfinder.set(
+                "last_node_reach_elapsed",
+                p.last_node_reached_at.elapsed().as_millis(),
+            )?;
+            pathfinder.set("is_path_partial", p.is_path_partial)?;
+            true
+        } else {
+            false
+        },
+    )?;
+    Ok(pathfinder)
+}
+
+pub fn position(_lua: &Lua, client: &Client) -> Result<Vec3> {
+    let p = client.inner.as_ref().unwrap().position();
+    Ok(Vec3 {
+        x: p.x,
+        y: p.y,
+        z: p.z,
+    })
+}
+
 pub fn set_direction(_lua: &Lua, client: &mut Client, direction: (f32, f32)) -> Result<()> {
     client
         .inner
@@ -134,6 +208,11 @@ pub fn sprint(_lua: &Lua, client: &mut Client, direction: u8) -> Result<()> {
     Ok(())
 }
 
+pub fn stop_pathfinding(_lua: &Lua, client: &Client, _: ()) -> Result<()> {
+    client.inner.as_ref().unwrap().stop_pathfinding();
+    Ok(())
+}
+
 pub fn walk(_lua: &Lua, client: &mut Client, direction: u8) -> Result<()> {
     client.inner.as_mut().unwrap().walk(match direction {
         1 => WalkDirection::Forward,
diff --git a/src/scripting/client/state.rs b/src/scripting/client/state.rs
index cf7af8a..1f7a34a 100644
--- a/src/scripting/client/state.rs
+++ b/src/scripting/client/state.rs
@@ -1,7 +1,30 @@
-use super::Client;
-use azalea::ClientInformation;
+use super::{Client, Hunger};
+use azalea::{
+    ClientInformation,
+    entity::metadata::{AirSupply, Score},
+};
 use mlua::{Lua, Result, Table, UserDataRef};
 
+pub fn air_supply(_lua: &Lua, client: &Client) -> Result<i32> {
+    Ok(client.inner.as_ref().unwrap().component::<AirSupply>().0)
+}
+
+pub fn health(_lua: &Lua, client: &Client) -> Result<f32> {
+    Ok(client.inner.as_ref().unwrap().health())
+}
+
+pub fn hunger(_lua: &Lua, client: &Client) -> Result<Hunger> {
+    let h = client.inner.as_ref().unwrap().hunger();
+    Ok(Hunger {
+        food: h.food,
+        saturation: h.saturation,
+    })
+}
+
+pub fn score(_lua: &Lua, client: &Client) -> Result<i32> {
+    Ok(client.inner.as_ref().unwrap().component::<Score>().0)
+}
+
 pub async fn set_client_information(
     _lua: Lua,
     client: UserDataRef<Client>,