From 2e1736af250d5cb0e6833f8ad39d186b8c9a9cb4 Mon Sep 17 00:00:00 2001 From: ErrorNoInternet Date: Sun, 16 Feb 2025 14:21:29 -0500 Subject: [PATCH] refactor: clean up locking and convert to async --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/commands.rs | 36 ++++++++++++++++++++++-------------- src/events.rs | 4 ++-- src/http.rs | 15 ++++++--------- src/main.rs | 10 +++++----- src/scripting/mod.rs | 11 +++++++---- 7 files changed, 44 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 23aae7b..10416a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1179,12 +1179,12 @@ dependencies = [ "anyhow", "azalea", "clap", + "futures", "http-body-util", "hyper", "hyper-util", "log", "mlua", - "parking_lot", "tokio", ] diff --git a/Cargo.toml b/Cargo.toml index b5c811c..e17c9d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,5 +24,5 @@ hyper = { version = "1", features = ["server"] } hyper-util = "0" log = { version = "0" } mlua = { version = "0", features = ["async", "luau", "send"] } -parking_lot = { version = "0" } tokio = { version = "1", features = ["macros"] } +futures = "0" diff --git a/src/commands.rs b/src/commands.rs index 4015952..d6c68c5 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -7,7 +7,7 @@ use azalea::{ prelude::*, }; use bevy_ecs::{entity::Entity, query::With}; -use parking_lot::Mutex; +use futures::lock::Mutex; pub type Ctx<'a> = CommandContext>; @@ -40,35 +40,43 @@ impl CommandSource { pub fn register(commands: &mut CommandDispatcher>) { commands.register(literal("reload").executes(|ctx: &Ctx| { - let source = ctx.source.lock(); - source.reply(&format!("{:?}", reload(&source.state.lua.lock()))); + let source = ctx.source.clone(); + tokio::spawn(async move { + let source = source.lock().await; + source.reply(&format!("{:?}", reload(&source.state.lua))); + }); 1 })); commands.register( literal("eval").then(argument("code", string()).executes(|ctx: &Ctx| { - let source = ctx.source.lock(); - source.reply(&format!( - "{:?}", - eval(&source.state.lua.lock(), &get_string(ctx, "code").unwrap()) - )); + let source = ctx.source.clone(); + let code = get_string(ctx, "code").unwrap(); + tokio::spawn(async move { + let source = source.lock().await; + source.reply(&format!("{:?}", eval(&source.state.lua, &code).await)); + }); 1 })), ); commands.register( literal("exec").then(argument("code", string()).executes(|ctx: &Ctx| { - let source = ctx.source.lock(); - source.reply(&format!( - "{:?}", - exec(&source.state.lua.lock(), &get_string(ctx, "code").unwrap()) - )); + let source = ctx.source.clone(); + let code = get_string(ctx, "code").unwrap(); + tokio::spawn(async move { + let source = source.lock().await; + source.reply(&format!("{:?}", exec(&source.state.lua, &code).await)); + }); 1 })), ); commands.register(literal("ping").executes(|ctx: &Ctx| { - ctx.source.lock().reply("pong!"); + let source = ctx.source.clone(); + tokio::spawn(async move { + source.lock().await.reply("pong!"); + }); 1 })); } diff --git a/src/events.rs b/src/events.rs index 8952ec7..a0a31d2 100644 --- a/src/events.rs +++ b/src/events.rs @@ -7,7 +7,7 @@ use mlua::{Function, IntoLuaMulti, Table}; use tokio::net::TcpListener; pub async fn handle_event(client: Client, event: Event, state: State) -> anyhow::Result<()> { - let globals = state.lua.lock().globals(); + let globals = state.lua.globals(); match event { Event::Chat(message) => { @@ -40,7 +40,7 @@ pub async fn handle_event(client: Client, event: Event, state: State) -> anyhow: call_lua_handler(&globals, "on_chat", ()); } Event::Death(Some(packet)) => { - let death_data = state.lua.lock().create_table()?; + let death_data = state.lua.create_table()?; death_data.set("message", packet.message.to_string())?; death_data.set("player_id", packet.player_id)?; diff --git a/src/http.rs b/src/http.rs index a57a5ff..67953b6 100644 --- a/src/http.rs +++ b/src/http.rs @@ -12,7 +12,7 @@ pub async fn serve( let path = request.uri().path().to_owned(); Ok(match (request.method(), path.as_str()) { - (&Method::POST, "/reload") => match reload(&state.lua.lock()) { + (&Method::POST, "/reload") => match reload(&state.lua) { Ok(()) => Response::new(empty()), Err(error) => status_code_response( StatusCode::INTERNAL_SERVER_ERROR, @@ -23,14 +23,11 @@ pub async fn serve( (&Method::POST, "/eval" | "/exec") => { let bytes = request.into_body().collect().await?.to_bytes(); match std::str::from_utf8(&bytes) { - Ok(code) => { - let lua = state.lua.lock(); - Response::new(full(match path.as_str() { - "/eval" => format!("{:?}", eval(&lua, code)), - "/exec" => format!("{:?}", exec(&lua, code)), - _ => unreachable!(), - })) - } + Ok(code) => Response::new(full(match path.as_str() { + "/eval" => format!("{:?}", eval(&state.lua, code).await), + "/exec" => format!("{:?}", exec(&state.lua, code).await), + _ => unreachable!(), + })), Err(error) => status_code_response( StatusCode::BAD_REQUEST, full(format!("invalid utf-8 data received: {error:?}")), diff --git a/src/main.rs b/src/main.rs index 28fa6b0..791c852 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,15 +10,15 @@ use azalea::{brigadier::prelude::CommandDispatcher, prelude::*}; use clap::Parser; use commands::{CommandSource, register}; use events::handle_event; +use futures::lock::Mutex; use mlua::Lua; -use parking_lot::Mutex; use std::{net::SocketAddr, path::PathBuf, sync::Arc}; #[derive(Default, Clone, Component)] pub struct State { - commands: Arc>>, - lua: Arc>, + lua: Lua, http_address: Option, + commands: Arc>>, } #[tokio::main] @@ -42,9 +42,9 @@ async fn main() -> anyhow::Result<()> { let Err(error) = ClientBuilder::new() .set_handler(handle_event) .set_state(State { - commands: Arc::new(commands), - lua: Arc::new(Mutex::new(lua)), + lua, http_address: args.http_address, + commands: Arc::new(commands), }) .start( if username.contains('@') { diff --git a/src/scripting/mod.rs b/src/scripting/mod.rs index e4b1a84..c1b67f4 100644 --- a/src/scripting/mod.rs +++ b/src/scripting/mod.rs @@ -28,10 +28,13 @@ pub fn reload(lua: &Lua) -> Result<(), Error> { .map_err(Error::LoadChunk) } -pub fn eval(lua: &Lua, code: &str) -> Result { - lua.load(code).eval::().map_err(Error::EvalChunk) +pub async fn eval(lua: &Lua, code: &str) -> Result { + lua.load(code) + .eval_async::() + .await + .map_err(Error::EvalChunk) } -pub fn exec(lua: &Lua, code: &str) -> Result<(), Error> { - lua.load(code).exec().map_err(Error::ExecChunk) +pub async fn exec(lua: &Lua, code: &str) -> Result<(), Error> { + lua.load(code).exec_async().await.map_err(Error::ExecChunk) }