refactor: clean up locking and convert to async

This commit is contained in:
Ryan 2025-02-16 14:21:29 -05:00
parent 1c7a6fde09
commit 2e1736af25
Signed by: ErrorNoInternet
GPG Key ID: 2486BFB7B1E6A4A3
7 changed files with 44 additions and 36 deletions

2
Cargo.lock generated
View File

@ -1179,12 +1179,12 @@ dependencies = [
"anyhow", "anyhow",
"azalea", "azalea",
"clap", "clap",
"futures",
"http-body-util", "http-body-util",
"hyper", "hyper",
"hyper-util", "hyper-util",
"log", "log",
"mlua", "mlua",
"parking_lot",
"tokio", "tokio",
] ]

View File

@ -24,5 +24,5 @@ hyper = { version = "1", features = ["server"] }
hyper-util = "0" hyper-util = "0"
log = { version = "0" } log = { version = "0" }
mlua = { version = "0", features = ["async", "luau", "send"] } mlua = { version = "0", features = ["async", "luau", "send"] }
parking_lot = { version = "0" }
tokio = { version = "1", features = ["macros"] } tokio = { version = "1", features = ["macros"] }
futures = "0"

View File

@ -7,7 +7,7 @@ use azalea::{
prelude::*, prelude::*,
}; };
use bevy_ecs::{entity::Entity, query::With}; use bevy_ecs::{entity::Entity, query::With};
use parking_lot::Mutex; use futures::lock::Mutex;
pub type Ctx<'a> = CommandContext<Mutex<CommandSource>>; pub type Ctx<'a> = CommandContext<Mutex<CommandSource>>;
@ -40,35 +40,43 @@ impl CommandSource {
pub fn register(commands: &mut CommandDispatcher<Mutex<CommandSource>>) { pub fn register(commands: &mut CommandDispatcher<Mutex<CommandSource>>) {
commands.register(literal("reload").executes(|ctx: &Ctx| { commands.register(literal("reload").executes(|ctx: &Ctx| {
let source = ctx.source.lock(); let source = ctx.source.clone();
source.reply(&format!("{:?}", reload(&source.state.lua.lock()))); tokio::spawn(async move {
let source = source.lock().await;
source.reply(&format!("{:?}", reload(&source.state.lua)));
});
1 1
})); }));
commands.register( commands.register(
literal("eval").then(argument("code", string()).executes(|ctx: &Ctx| { literal("eval").then(argument("code", string()).executes(|ctx: &Ctx| {
let source = ctx.source.lock(); let source = ctx.source.clone();
source.reply(&format!( let code = get_string(ctx, "code").unwrap();
"{:?}", tokio::spawn(async move {
eval(&source.state.lua.lock(), &get_string(ctx, "code").unwrap()) let source = source.lock().await;
)); source.reply(&format!("{:?}", eval(&source.state.lua, &code).await));
});
1 1
})), })),
); );
commands.register( commands.register(
literal("exec").then(argument("code", string()).executes(|ctx: &Ctx| { literal("exec").then(argument("code", string()).executes(|ctx: &Ctx| {
let source = ctx.source.lock(); let source = ctx.source.clone();
source.reply(&format!( let code = get_string(ctx, "code").unwrap();
"{:?}", tokio::spawn(async move {
exec(&source.state.lua.lock(), &get_string(ctx, "code").unwrap()) let source = source.lock().await;
)); source.reply(&format!("{:?}", exec(&source.state.lua, &code).await));
});
1 1
})), })),
); );
commands.register(literal("ping").executes(|ctx: &Ctx| { 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 1
})); }));
} }

View File

@ -7,7 +7,7 @@ use mlua::{Function, IntoLuaMulti, Table};
use tokio::net::TcpListener; use tokio::net::TcpListener;
pub async fn handle_event(client: Client, event: Event, state: State) -> anyhow::Result<()> { 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 { match event {
Event::Chat(message) => { 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", ()); call_lua_handler(&globals, "on_chat", ());
} }
Event::Death(Some(packet)) => { 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("message", packet.message.to_string())?;
death_data.set("player_id", packet.player_id)?; death_data.set("player_id", packet.player_id)?;

View File

@ -12,7 +12,7 @@ pub async fn serve(
let path = request.uri().path().to_owned(); let path = request.uri().path().to_owned();
Ok(match (request.method(), path.as_str()) { 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()), Ok(()) => Response::new(empty()),
Err(error) => status_code_response( Err(error) => status_code_response(
StatusCode::INTERNAL_SERVER_ERROR, StatusCode::INTERNAL_SERVER_ERROR,
@ -23,14 +23,11 @@ pub async fn serve(
(&Method::POST, "/eval" | "/exec") => { (&Method::POST, "/eval" | "/exec") => {
let bytes = request.into_body().collect().await?.to_bytes(); let bytes = request.into_body().collect().await?.to_bytes();
match std::str::from_utf8(&bytes) { match std::str::from_utf8(&bytes) {
Ok(code) => { Ok(code) => Response::new(full(match path.as_str() {
let lua = state.lua.lock(); "/eval" => format!("{:?}", eval(&state.lua, code).await),
Response::new(full(match path.as_str() { "/exec" => format!("{:?}", exec(&state.lua, code).await),
"/eval" => format!("{:?}", eval(&lua, code)),
"/exec" => format!("{:?}", exec(&lua, code)),
_ => unreachable!(), _ => unreachable!(),
})) })),
}
Err(error) => status_code_response( Err(error) => status_code_response(
StatusCode::BAD_REQUEST, StatusCode::BAD_REQUEST,
full(format!("invalid utf-8 data received: {error:?}")), full(format!("invalid utf-8 data received: {error:?}")),

View File

@ -10,15 +10,15 @@ use azalea::{brigadier::prelude::CommandDispatcher, prelude::*};
use clap::Parser; use clap::Parser;
use commands::{CommandSource, register}; use commands::{CommandSource, register};
use events::handle_event; use events::handle_event;
use futures::lock::Mutex;
use mlua::Lua; use mlua::Lua;
use parking_lot::Mutex;
use std::{net::SocketAddr, path::PathBuf, sync::Arc}; use std::{net::SocketAddr, path::PathBuf, sync::Arc};
#[derive(Default, Clone, Component)] #[derive(Default, Clone, Component)]
pub struct State { pub struct State {
commands: Arc<CommandDispatcher<Mutex<CommandSource>>>, lua: Lua,
lua: Arc<Mutex<Lua>>,
http_address: Option<SocketAddr>, http_address: Option<SocketAddr>,
commands: Arc<CommandDispatcher<Mutex<CommandSource>>>,
} }
#[tokio::main] #[tokio::main]
@ -42,9 +42,9 @@ async fn main() -> anyhow::Result<()> {
let Err(error) = ClientBuilder::new() let Err(error) = ClientBuilder::new()
.set_handler(handle_event) .set_handler(handle_event)
.set_state(State { .set_state(State {
commands: Arc::new(commands), lua,
lua: Arc::new(Mutex::new(lua)),
http_address: args.http_address, http_address: args.http_address,
commands: Arc::new(commands),
}) })
.start( .start(
if username.contains('@') { if username.contains('@') {

View File

@ -28,10 +28,13 @@ pub fn reload(lua: &Lua) -> Result<(), Error> {
.map_err(Error::LoadChunk) .map_err(Error::LoadChunk)
} }
pub fn eval(lua: &Lua, code: &str) -> Result<String, Error> { pub async fn eval(lua: &Lua, code: &str) -> Result<String, Error> {
lua.load(code).eval::<String>().map_err(Error::EvalChunk) lua.load(code)
.eval_async::<String>()
.await
.map_err(Error::EvalChunk)
} }
pub fn exec(lua: &Lua, code: &str) -> Result<(), Error> { pub async fn exec(lua: &Lua, code: &str) -> Result<(), Error> {
lua.load(code).exec().map_err(Error::ExecChunk) lua.load(code).exec_async().await.map_err(Error::ExecChunk)
} }