refactor: random cleanups and efficiency improvements

This commit is contained in:
Ryan 2025-02-23 17:19:26 -05:00
parent 2ea7ec9e7e
commit 36054ced03
Signed by: ErrorNoInternet
GPG Key ID: 2486BFB7B1E6A4A3
5 changed files with 69 additions and 58 deletions

View File

@ -14,17 +14,17 @@ function log_player_positions()
end end
end end
function on_init() add_listener("init", function()
info("client initialized, setting information...") info("client initialized, setting information...")
client:set_client_information({ view_distance = 16 }) client:set_client_information({ view_distance = 16 })
end)
add_listener("login", function() add_listener("login", function()
info("player successfully logged in!") info("player successfully logged in!")
end) end)
add_listener("death", function() add_listener("death", function()
warn(string.format("player died at %.1f %.1f %.1f!", client.position.x, client.position.y, client.position.z)) warn(string.format("player died at %.1f %.1f %.1f!", client.position.x, client.position.y, client.position.z))
end, "warn_player_died") end, "warn_player_died")
add_listener("tick", log_player_positions) add_listener("tick", log_player_positions)
end

View File

@ -4,19 +4,18 @@ use crate::{
State, State,
commands::CommandSource, commands::CommandSource,
http::serve, http::serve,
lua::{self, events::register_functions, player::Player}, lua::{self, player::Player},
}; };
use azalea::{prelude::*, protocol::packets::game::ClientboundGamePacket}; use azalea::{prelude::*, protocol::packets::game::ClientboundGamePacket};
use hyper::{server::conn::http1, service::service_fn}; use hyper::{server::conn::http1, service::service_fn};
use hyper_util::rt::TokioIo; use hyper_util::rt::TokioIo;
use log::{debug, error, info, trace}; use log::{debug, error, info, trace};
use mlua::{Function, IntoLuaMulti}; use mlua::IntoLuaMulti;
use tokio::net::TcpListener; use tokio::net::TcpListener;
#[allow(clippy::too_many_lines)] #[allow(clippy::too_many_lines)]
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<()> {
state.lua.gc_stop(); state.lua.gc_stop();
let globals = state.lua.globals();
match event { match event {
Event::AddPlayer(player_info) => { Event::AddPlayer(player_info) => {
@ -26,7 +25,7 @@ pub async fn handle_event(client: Client, event: Event, state: State) -> anyhow:
let formatted_message = message.message(); let formatted_message = message.message();
info!("{}", formatted_message.to_ansi()); info!("{}", formatted_message.to_ansi());
let owners = globals.get::<Vec<String>>("Owners")?; let owners = state.lua.globals().get::<Vec<String>>("Owners")?;
if message.is_whisper() if message.is_whisper()
&& let (Some(sender), content) = message.split_sender_and_content() && let (Some(sender), content) = message.split_sender_and_content()
&& owners.contains(&sender) && owners.contains(&sender)
@ -78,20 +77,16 @@ pub async fn handle_event(client: Client, event: Event, state: State) -> anyhow:
} }
} }
Event::Init => { Event::Init => {
debug!("client initialized"); debug!("received initialize event");
let globals = state.lua.globals();
globals.set( globals.set(
"client", "client",
lua::client::Client { lua::client::Client {
inner: Some(client), inner: Some(client),
}, },
)?; )?;
register_functions(&state.lua, &globals, state.clone()).await?; call_listeners(&state, "init", ()).await;
if let Ok(on_init) = globals.get::<Function>("on_init")
&& let Err(error) = on_init.call::<()>(())
{
error!("failed to call lua on_init function: {error:?}");
}
if let Some(address) = state.http_address { if let Some(address) = state.http_address {
let listener = TcpListener::bind(address).await.map_err(|error| { let listener = TcpListener::bind(address).await.map_err(|error| {

View File

@ -1,17 +1,24 @@
use crate::State; use crate::ListenerMap;
use futures::executor::block_on; use futures::{executor::block_on, lock::Mutex};
use mlua::{Function, Lua, Result, Table}; use mlua::{Function, Lua, Result, Table};
use std::time::{SystemTime, UNIX_EPOCH}; use std::{
sync::Arc,
time::{SystemTime, UNIX_EPOCH},
};
pub async fn register_functions(lua: &Lua, globals: &Table, state: State) -> Result<()> { pub fn register_functions(
let l = state.event_listeners.clone(); lua: &Lua,
globals: &Table,
event_listeners: Arc<Mutex<ListenerMap>>,
) -> Result<()> {
let m = event_listeners.clone();
globals.set( globals.set(
"add_listener", "add_listener",
lua.create_function( lua.create_function(
move |_, (event_type, callback, id): (String, Function, Option<String>)| { move |_, (event_type, callback, id): (String, Function, Option<String>)| {
let l = l.clone(); let m = m.clone();
tokio::spawn(async move { tokio::spawn(async move {
l.lock().await.entry(event_type).or_default().push(( m.lock().await.entry(event_type).or_default().push((
id.unwrap_or(callback.info().name.unwrap_or(format!( id.unwrap_or(callback.info().name.unwrap_or(format!(
"anonymous @ {}", "anonymous @ {}",
SystemTime::now() SystemTime::now()
@ -27,21 +34,21 @@ pub async fn register_functions(lua: &Lua, globals: &Table, state: State) -> Res
)?, )?,
)?; )?;
let l = state.event_listeners.clone(); let m = event_listeners.clone();
globals.set( globals.set(
"remove_listener", "remove_listener",
lua.create_function(move |_, (event_type, target_id): (String, String)| { lua.create_function(move |_, (event_type, target_id): (String, String)| {
let l = l.clone(); let m = m.clone();
tokio::spawn(async move { tokio::spawn(async move {
let mut l = l.lock().await; let mut m = m.lock().await;
let empty = if let Some(listeners) = l.get_mut(&event_type) { let empty = if let Some(listeners) = m.get_mut(&event_type) {
listeners.retain(|(id, _)| target_id != *id); listeners.retain(|(id, _)| target_id != *id);
listeners.is_empty() listeners.is_empty()
} else { } else {
false false
}; };
if empty { if empty {
l.remove(&event_type); m.remove(&event_type);
} }
}); });
Ok(()) Ok(())
@ -51,10 +58,10 @@ pub async fn register_functions(lua: &Lua, globals: &Table, state: State) -> Res
globals.set( globals.set(
"get_listeners", "get_listeners",
lua.create_function(move |lua, (): ()| { lua.create_function(move |lua, (): ()| {
let l = block_on(state.event_listeners.lock()); let m = block_on(event_listeners.lock());
let listeners = lua.create_table()?; let listeners = lua.create_table()?;
for (event_type, callbacks) in l.iter() { for (event_type, callbacks) in m.iter() {
let type_listeners = lua.create_table()?; let type_listeners = lua.create_table()?;
for (id, callback) in callbacks { for (id, callback) in callbacks {
let listener = lua.create_table()?; let listener = lua.create_table()?;

View File

@ -8,7 +8,10 @@ pub mod player;
pub mod system; pub mod system;
pub mod vec3; pub mod vec3;
use crate::ListenerMap;
use futures::lock::Mutex;
use mlua::{Lua, Table}; use mlua::{Lua, Table};
use std::{io, sync::Arc, time::Duration};
#[derive(Debug)] #[derive(Debug)]
#[allow(dead_code)] #[allow(dead_code)]
@ -18,19 +21,24 @@ pub enum Error {
ExecChunk(mlua::Error), ExecChunk(mlua::Error),
LoadChunk(mlua::Error), LoadChunk(mlua::Error),
MissingPath(mlua::Error), MissingPath(mlua::Error),
ReadFile(std::io::Error), ReadFile(io::Error),
} }
pub fn register_functions(lua: &Lua, globals: &Table) -> mlua::Result<()> { pub fn register_functions(
lua: &Lua,
globals: &Table,
event_listeners: Arc<Mutex<ListenerMap>>,
) -> mlua::Result<()> {
globals.set( globals.set(
"sleep", "sleep",
lua.create_async_function(async |_, duration: u64| { lua.create_async_function(async |_, duration: u64| {
tokio::time::sleep(std::time::Duration::from_millis(duration)).await; tokio::time::sleep(Duration::from_millis(duration)).await;
Ok(()) Ok(())
})?, })?,
)?; )?;
block::register_functions(lua, globals)?; block::register_functions(lua, globals)?;
events::register_functions(lua, globals, event_listeners)?;
logging::register_functions(lua, globals)?; logging::register_functions(lua, globals)?;
system::register_functions(lua, globals) system::register_functions(lua, globals)
} }

View File

@ -16,7 +16,6 @@ use bevy_log::{
}; };
use clap::Parser; use clap::Parser;
use commands::{CommandSource, register}; use commands::{CommandSource, register};
use events::handle_event;
use futures::lock::Mutex; use futures::lock::Mutex;
use mlua::{Function, Lua}; use mlua::{Function, Lua};
use std::{ use std::{
@ -43,13 +42,14 @@ pub struct State {
#[tokio::main] #[tokio::main]
async fn main() -> anyhow::Result<()> { async fn main() -> anyhow::Result<()> {
let args = arguments::Arguments::parse(); let args = arguments::Arguments::parse();
let script_path = args.script.unwrap_or(PathBuf::from(DEFAULT_SCRIPT_PATH)); let script_path = args.script.unwrap_or(PathBuf::from(DEFAULT_SCRIPT_PATH));
let event_listeners = Arc::new(Mutex::new(HashMap::new()));
let lua = Lua::new(); let lua = Lua::new();
let globals = lua.globals(); let globals = lua.globals();
globals.set("script_path", &*script_path)?; globals.set("script_path", &*script_path)?;
lua::register_functions(&lua, &globals)?; lua::register_functions(&lua, &globals, event_listeners.clone())?;
lua.load( lua.load(
read_to_string(script_path) read_to_string(script_path)
.expect(&(DEFAULT_SCRIPT_PATH.to_owned() + " should be in current directory")), .expect(&(DEFAULT_SCRIPT_PATH.to_owned() + " should be in current directory")),
@ -65,8 +65,7 @@ async fn main() -> anyhow::Result<()> {
let mut commands = CommandDispatcher::new(); let mut commands = CommandDispatcher::new();
register(&mut commands); register(&mut commands);
let Err(error) = ClientBuilder::new_without_plugins() let log_plugin = LogPlugin {
.add_plugins(DefaultPlugins.set(LogPlugin {
custom_layer: |_| { custom_layer: |_| {
env::var("LOG_FILE").ok().map(|log_file| { env::var("LOG_FILE").ok().map(|log_file| {
layer() layer()
@ -81,12 +80,14 @@ async fn main() -> anyhow::Result<()> {
}) })
}, },
..Default::default() ..Default::default()
})) };
let Err(error) = ClientBuilder::new_without_plugins()
.add_plugins(DefaultPlugins.set(log_plugin))
.add_plugins(DefaultBotPlugins) .add_plugins(DefaultBotPlugins)
.set_handler(handle_event) .set_handler(events::handle_event)
.set_state(State { .set_state(State {
lua, lua,
event_listeners: Arc::new(Mutex::new(HashMap::new())), event_listeners,
commands: Arc::new(commands), commands: Arc::new(commands),
http_address: args.http_address, http_address: args.http_address,
}) })