perf: lazily evaluate listener arguments

This commit is contained in:
Ryan 2025-03-13 17:04:50 -04:00
parent 10946ea7a4
commit de5dbe600a
Signed by: ErrorNoInternet
GPG Key ID: 2486BFB7B1E6A4A3

View File

@ -23,7 +23,7 @@ use tokio::net::TcpListener;
pub async fn handle_event(client: Client, event: Event, state: State) -> Result<()> { pub async fn handle_event(client: Client, event: Event, state: State) -> Result<()> {
match event { match event {
Event::AddPlayer(player_info) => { Event::AddPlayer(player_info) => {
call_listeners(&state, "add_player", Player::from(player_info)).await; call_listeners(&state, "add_player", || Ok(Player::from(player_info))).await
} }
Event::Chat(message) => { Event::Chat(message) => {
let globals = state.lua.globals(); let globals = state.lua.globals();
@ -78,101 +78,123 @@ pub async fn handle_event(client: Client, event: Event, state: State) -> Result<
} }
} }
let table = state.lua.create_table()?; call_listeners(&state, "chat", || {
table.set("text", text.to_string())?; let table = state.lua.create_table()?;
table.set("ansi_text", ansi_text)?; table.set("text", text.to_string())?;
table.set("sender", sender)?; table.set("ansi_text", ansi_text)?;
table.set("content", content)?; table.set("sender", sender)?;
table.set("uuid", uuid)?; table.set("content", content)?;
table.set("is_whisper", is_whisper)?; table.set("uuid", uuid)?;
table.set("is_encrypted", is_encrypted)?; table.set("is_whisper", is_whisper)?;
call_listeners(&state, "chat", table).await; table.set("is_encrypted", is_encrypted)?;
Ok(table)
})
.await
} }
Event::Death(packet) => { Event::Death(packet) => {
if let Some(packet) = packet { if let Some(packet) = packet {
let message_table = state.lua.create_table()?; call_listeners(&state, "death", || {
message_table.set("text", packet.message.to_string())?; let message_table = state.lua.create_table()?;
message_table.set("ansi_text", packet.message.to_ansi())?; message_table.set("text", packet.message.to_string())?;
let table = state.lua.create_table()?; message_table.set("ansi_text", packet.message.to_ansi())?;
table.set("message", message_table)?; let table = state.lua.create_table()?;
table.set("player_id", packet.player_id.0)?; table.set("message", message_table)?;
call_listeners(&state, "death", table).await; table.set("player_id", packet.player_id.0)?;
Ok(table)
})
.await
} else { } else {
call_listeners(&state, "death", ()).await; call_listeners(&state, "death", || Ok(())).await
} }
} }
Event::Disconnect(message) => { Event::Disconnect(message) => {
if let Some(message) = message { if let Some(message) = message {
let table = state.lua.create_table()?; call_listeners(&state, "disconnect", || {
table.set("text", message.to_string())?; let table = state.lua.create_table()?;
table.set("ansi_text", message.to_ansi())?; table.set("text", message.to_string())?;
call_listeners(&state, "disconnect", table).await; table.set("ansi_text", message.to_ansi())?;
Ok(table)
})
.await
} else { } else {
call_listeners(&state, "disconnect", ()).await; call_listeners(&state, "disconnect", || Ok(())).await
} }
} }
Event::KeepAlive(id) => call_listeners(&state, "keep_alive", id).await, Event::KeepAlive(id) => call_listeners(&state, "keep_alive", || Ok(id)).await,
Event::Login => call_listeners(&state, "login", ()).await, Event::Login => call_listeners(&state, "login", || Ok(())).await,
Event::RemovePlayer(player_info) => { Event::RemovePlayer(player_info) => {
call_listeners(&state, "remove_player", Player::from(player_info)).await; call_listeners(&state, "remove_player", || Ok(Player::from(player_info))).await
} }
Event::Tick => call_listeners(&state, "tick", ()).await, Event::Tick => call_listeners(&state, "tick", || Ok(())).await,
Event::UpdatePlayer(player_info) => { Event::UpdatePlayer(player_info) => {
call_listeners(&state, "update_player", Player::from(player_info)).await; call_listeners(&state, "update_player", || Ok(Player::from(player_info))).await
} }
Event::Packet(packet) => match packet.as_ref() { Event::Packet(packet) => match packet.as_ref() {
ClientboundGamePacket::AddEntity(packet) => { ClientboundGamePacket::AddEntity(packet) => {
let table = state.lua.create_table()?; call_listeners(&state, "add_entity", || {
table.set("id", packet.id.0)?; let table = state.lua.create_table()?;
table.set("uuid", packet.uuid.to_string())?; table.set("id", packet.id.0)?;
table.set("kind", packet.entity_type.to_string())?; table.set("uuid", packet.uuid.to_string())?;
table.set("position", Vec3::from(packet.position))?; table.set("kind", packet.entity_type.to_string())?;
table.set( table.set("position", Vec3::from(packet.position))?;
"direction", table.set(
Direction { "direction",
y: f32::from(packet.y_rot) / (256.0 / 360.0), Direction {
x: f32::from(packet.x_rot) / (256.0 / 360.0), y: f32::from(packet.y_rot) / (256.0 / 360.0),
}, x: f32::from(packet.x_rot) / (256.0 / 360.0),
)?; },
table.set("data", packet.data)?; )?;
call_listeners(&state, "add_entity", table).await; table.set("data", packet.data)?;
Ok(table)
})
.await
} }
ClientboundGamePacket::LevelParticles(packet) => { ClientboundGamePacket::LevelParticles(packet) => {
let table = state.lua.create_table()?; call_listeners(&state, "level_particles", || {
table.set("position", Vec3::from(packet.pos))?; let table = state.lua.create_table()?;
table.set("count", packet.count)?; table.set("position", Vec3::from(packet.pos))?;
table.set("kind", particle::to_kind(&packet.particle) as u8)?; table.set("count", packet.count)?;
call_listeners(&state, "level_particles", table).await; table.set("kind", particle::to_kind(&packet.particle) as u8)?;
Ok(table)
})
.await
} }
ClientboundGamePacket::RemoveEntities(packet) => { ClientboundGamePacket::RemoveEntities(packet) => {
call_listeners( call_listeners(&state, "remove_entities", || {
&state, Ok(packet.entity_ids.iter().map(|id| id.0).collect::<Vec<_>>())
"remove_entities", })
packet.entity_ids.iter().map(|id| id.0).collect::<Vec<_>>(), .await
)
.await;
} }
ClientboundGamePacket::SetHealth(packet) => { ClientboundGamePacket::SetHealth(packet) => {
let table = state.lua.create_table()?; call_listeners(&state, "set_health", || {
table.set("food", packet.food)?; let table = state.lua.create_table()?;
table.set("health", packet.health)?; table.set("food", packet.food)?;
table.set("saturation", packet.saturation)?; table.set("health", packet.health)?;
call_listeners(&state, "set_health", table).await; table.set("saturation", packet.saturation)?;
Ok(table)
})
.await
} }
ClientboundGamePacket::SetPassengers(packet) => { ClientboundGamePacket::SetPassengers(packet) => {
let table = state.lua.create_table()?; call_listeners(&state, "set_passengers", || {
table.set("vehicle", packet.vehicle)?; let table = state.lua.create_table()?;
table.set("passengers", &*packet.passengers)?; table.set("vehicle", packet.vehicle)?;
call_listeners(&state, "set_passengers", table).await; table.set("passengers", &*packet.passengers)?;
Ok(table)
})
.await
} }
ClientboundGamePacket::SetTime(packet) => { ClientboundGamePacket::SetTime(packet) => {
let table = state.lua.create_table()?; call_listeners(&state, "set_time", || {
table.set("day_time", packet.day_time)?; let table = state.lua.create_table()?;
table.set("game_time", packet.game_time)?; table.set("day_time", packet.day_time)?;
table.set("tick_day_time", packet.tick_day_time)?; table.set("game_time", packet.game_time)?;
call_listeners(&state, "set_time", table).await; table.set("tick_day_time", packet.tick_day_time)?;
Ok(table)
})
.await
} }
_ => (), _ => Ok(()),
}, },
Event::Init => { Event::Init => {
debug!("received init event"); debug!("received init event");
@ -202,7 +224,13 @@ pub async fn handle_event(client: Client, event: Event, state: State) -> Result<
debug!("http server listening on {address}"); debug!("http server listening on {address}");
loop { loop {
let (stream, peer) = listener.accept().await?; let (stream, peer) = match listener.accept().await {
Ok(pair) => pair,
Err(error) => {
error!("failed to accept connection: {error:?}");
continue;
}
};
trace!("http server got connection from {peer}"); trace!("http server got connection from {peer}");
let conn_state = state.clone(); let conn_state = state.clone();
@ -222,8 +250,6 @@ pub async fn handle_event(client: Client, event: Event, state: State) -> Result<
} }
} }
} }
Ok(())
} }
async fn lua_init(client: Client, state: &State, globals: &Table) -> Result<()> { async fn lua_init(client: Client, state: &State, globals: &Table) -> Result<()> {
@ -240,16 +266,16 @@ async fn lua_init(client: Client, state: &State, globals: &Table) -> Result<()>
})?, })?,
)?; )?;
globals.set("client", client::Client(Some(client)))?; globals.set("client", client::Client(Some(client)))?;
call_listeners(state, "init", ()).await; call_listeners(state, "init", || Ok(())).await
Ok(())
} }
async fn call_listeners<T: Clone + IntoLuaMulti + Send + 'static>( async fn call_listeners<T, F>(state: &State, event_type: &'static str, getter: F) -> Result<()>
state: &State, where
event_type: &'static str, T: Clone + IntoLuaMulti + Send + 'static,
data: T, F: FnOnce() -> Result<T>,
) { {
if let Some(listeners) = state.event_listeners.read().await.get(event_type).cloned() { if let Some(listeners) = state.event_listeners.read().await.get(event_type).cloned() {
let data = getter()?;
for (id, callback) in listeners { for (id, callback) in listeners {
let data = data.clone(); let data = data.clone();
tokio::spawn(async move { tokio::spawn(async move {
@ -259,4 +285,5 @@ async fn call_listeners<T: Clone + IntoLuaMulti + Send + 'static>(
}); });
} }
} }
Ok(())
} }