diff --git a/src/lua/mod.rs b/src/lua/mod.rs index a5f620a..c667425 100644 --- a/src/lua/mod.rs +++ b/src/lua/mod.rs @@ -1,6 +1,7 @@ pub mod events; pub mod manifest; pub mod runtime; +pub mod structs; pub mod worker; use std::path::PathBuf; diff --git a/src/lua/runtime.rs b/src/lua/runtime.rs index b035ddf..78b2d0c 100644 --- a/src/lua/runtime.rs +++ b/src/lua/runtime.rs @@ -1,16 +1,12 @@ use anyhow::{Context as AnyhowContext, Result}; -use mlua::{Function, Lua, Table}; -use pumpkin_util::text::TextComponent; -use rand::{Rng, rng}; +use mlua::Lua; use std::collections::HashMap; use std::fs; use std::path::{Path, PathBuf}; -use std::time::{SystemTime, UNIX_EPOCH}; -use crate::SERVER; use crate::config::ConfigManager; -use crate::lua::events; use crate::lua::manifest::LuaPluginManifest; +use crate::lua::{events, structs}; pub struct LuaPlugin { pub manifest: LuaPluginManifest, @@ -83,183 +79,21 @@ impl LuaRuntime { let lua = &self.lua; let pumpkin_table = lua.create_table()?; - lua.globals().set("pumpkin", pumpkin_table.clone())?; - - { - let log_table = lua.create_table()?; - - log_table.set( - "info", - lua.create_function(|_, message: String| { - log::info!("[Lua] {}", message); - Ok(()) - })?, - )?; - - log_table.set( - "warn", - lua.create_function(|_, message: String| { - log::warn!("[Lua] {}", message); - Ok(()) - })?, - )?; - - log_table.set( - "error", - lua.create_function(|_, message: String| { - log::error!("[Lua] {}", message); - Ok(()) - })?, - )?; - - log_table.set( - "debug", - lua.create_function(|_, message: String| { - log::debug!("[Lua] {}", message); - Ok(()) - })?, - )?; - - pumpkin_table.set("log", log_table)?; - } - - { - let server_table = lua.create_table()?; - - server_table.set( - "broadcast_message", - lua.create_async_function(move |_, message: String| async move { - if let Some(server) = SERVER.get() { - for p in server.get_all_players().await { - p.send_system_message(&TextComponent::text(message.clone())) - .await; - } - } - Ok(()) - })?, - )?; - - pumpkin_table.set("server", server_table)?; - } + pumpkin_table.set("log", structs::Log)?; + pumpkin_table.set("server", structs::Server)?; { let events_table = lua.create_table()?; - - events_table.set( - "register_listener", - lua.create_function(|lua_ctx, (event_type, callback): (String, Function)| { - let globals = lua_ctx.globals(); - let pumpkin: Table = globals.get("pumpkin")?; - let events: Table = pumpkin.get("events")?; - - let timestamp = SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap_or_default() - .as_millis(); - - let random = rng().random::(); - - let plugin_name = lua_ctx - .globals() - .get::("PLUGIN_INFO") - .and_then(|t| t.get::("name")) - .unwrap_or_else(|_| "unknown".to_string()); - - let callback_name = callback - .info() - .name - .unwrap_or_else(|| event_type.clone()) - .replace(|c: char| !c.is_alphanumeric(), ""); - - let listener_id = format!( - "listener_{}_{}_{}_{}", - plugin_name, callback_name, timestamp, random - ); - - match event_type.as_str() { - "player_join" => { - let listeners: Table = events.get("player_join")?; - listeners.set(listener_id.clone(), callback)?; - Ok(listener_id) - } - "player_leave" => { - let listeners: Table = events.get("player_leave")?; - listeners.set(listener_id.clone(), callback)?; - Ok(listener_id) - } - "player_chat" => { - let listeners: Table = events.get("player_chat")?; - listeners.set(listener_id.clone(), callback)?; - Ok(listener_id) - } - "block_place" => { - let listeners: Table = events.get("block_place")?; - listeners.set(listener_id.clone(), callback)?; - Ok(listener_id) - } - "block_break" => { - let listeners: Table = events.get("block_break")?; - listeners.set(listener_id.clone(), callback)?; - Ok(listener_id) - } - _ => Err(mlua::Error::RuntimeError(format!( - "Unknown event type: {}", - event_type - ))), - } - })?, - )?; - - events_table.set( - "unregister_listener", - lua.create_function(|lua_ctx, (event_type, listener_id): (String, String)| { - let globals = lua_ctx.globals(); - let pumpkin: Table = globals.get("pumpkin")?; - let events: Table = pumpkin.get("events")?; - - match event_type.as_str() { - "player_join" => { - let listeners: Table = events.get("player_join")?; - listeners.set(listener_id, mlua::Value::Nil)?; - Ok(true) - } - "player_leave" => { - let listeners: Table = events.get("player_leave")?; - listeners.set(listener_id, mlua::Value::Nil)?; - Ok(true) - } - "player_chat" => { - let listeners: Table = events.get("player_chat")?; - listeners.set(listener_id, mlua::Value::Nil)?; - Ok(true) - } - "block_place" => { - let listeners: Table = events.get("block_place")?; - listeners.set(listener_id, mlua::Value::Nil)?; - Ok(true) - } - "block_break" => { - let listeners: Table = events.get("block_break")?; - listeners.set(listener_id, mlua::Value::Nil)?; - Ok(true) - } - _ => Err(mlua::Error::RuntimeError(format!( - "Unknown event type: {}", - event_type - ))), - } - })?, - )?; - + events_table.set("", structs::Events)?; events::player_join::setup_lua_event(lua, &events_table)?; events::player_leave::setup_lua_event(lua, &events_table)?; events::player_chat::setup_lua_event(lua, &events_table)?; events::block_place::setup_lua_event(lua, &events_table)?; events::block_break::setup_lua_event(lua, &events_table)?; - pumpkin_table.set("events", events_table)?; } + lua.globals().set("pumpkin", pumpkin_table.clone())?; Ok(()) } diff --git a/src/lua/structs/events.rs b/src/lua/structs/events.rs new file mode 100644 index 0000000..cd2446f --- /dev/null +++ b/src/lua/structs/events.rs @@ -0,0 +1,112 @@ +use std::time::UNIX_EPOCH; + +use mlua::prelude::*; +use rand::{Rng, rng}; + +pub struct Events; + +impl LuaUserData for Events { + fn add_methods>(methods: &mut M) { + methods.add_function( + "register_listener", + |lua, (event_type, callback): (String, LuaFunction)| { + let globals = lua.globals(); + let pumpkin: LuaTable = globals.get("pumpkin")?; + let events: LuaTable = pumpkin.get("events")?; + + let timestamp = UNIX_EPOCH.elapsed().unwrap_or_default().as_millis(); + + let random = rng().random::(); + + let plugin_name = lua + .globals() + .get::("PLUGIN_INFO") + .and_then(|t| t.get::("name")) + .unwrap_or_else(|_| "unknown".to_string()); + + let callback_name = callback + .info() + .name + .unwrap_or_else(|| event_type.clone()) + .replace(|c: char| !c.is_alphanumeric(), ""); + + let listener_id = format!( + "listener_{}_{}_{}_{}", + plugin_name, callback_name, timestamp, random + ); + + match event_type.as_str() { + "player_join" => { + let listeners: LuaTable = events.get("player_join")?; + listeners.set(listener_id.clone(), callback)?; + Ok(listener_id) + } + "player_leave" => { + let listeners: LuaTable = events.get("player_leave")?; + listeners.set(listener_id.clone(), callback)?; + Ok(listener_id) + } + "player_chat" => { + let listeners: LuaTable = events.get("player_chat")?; + listeners.set(listener_id.clone(), callback)?; + Ok(listener_id) + } + "block_place" => { + let listeners: LuaTable = events.get("block_place")?; + listeners.set(listener_id.clone(), callback)?; + Ok(listener_id) + } + "block_break" => { + let listeners: LuaTable = events.get("block_break")?; + listeners.set(listener_id.clone(), callback)?; + Ok(listener_id) + } + _ => Err(mlua::Error::RuntimeError(format!( + "Unknown event type: {}", + event_type + ))), + } + }, + ); + methods.add_function( + "unregister_listener", + |lua, (event_type, listener_id): (String, String)| { + let globals = lua.globals(); + let pumpkin: LuaTable = globals.get("pumpkin")?; + let events: LuaTable = pumpkin.get("events")?; + + match event_type.as_str() { + "player_join" => { + let listeners: LuaTable = events.get("player_join")?; + listeners.set(listener_id, mlua::Value::Nil)?; + Ok(true) + } + "player_leave" => { + let listeners: LuaTable = events.get("player_leave")?; + listeners.set(listener_id, mlua::Value::Nil)?; + Ok(true) + } + "player_chat" => { + let listeners: LuaTable = events.get("player_chat")?; + listeners.set(listener_id, mlua::Value::Nil)?; + Ok(true) + } + "block_place" => { + let listeners: LuaTable = events.get("block_place")?; + listeners.set(listener_id, mlua::Value::Nil)?; + Ok(true) + } + "block_break" => { + let listeners: LuaTable = events.get("block_break")?; + listeners.set(listener_id, mlua::Value::Nil)?; + Ok(true) + } + _ => Err(mlua::Error::RuntimeError(format!( + "Unknown event type: {}", + event_type + ))), + } + }, + ); + } +} diff --git a/src/lua/structs/log.rs b/src/lua/structs/log.rs new file mode 100644 index 0000000..67e11de --- /dev/null +++ b/src/lua/structs/log.rs @@ -0,0 +1,24 @@ +use mlua::prelude::*; + +pub struct Log; + +impl LuaUserData for Log { + fn add_methods>(methods: &mut M) { + methods.add_function("info", |_, message: String| { + log::info!("[Lua] {}", message); + Ok(()) + }); + methods.add_function("warn", |_, message: String| { + log::warn!("[Lua] {}", message); + Ok(()) + }); + methods.add_function("error", |_, message: String| { + log::error!("[Lua] {}", message); + Ok(()) + }); + methods.add_function("debug", |_, message: String| { + log::debug!("[Lua] {}", message); + Ok(()) + }); + } +} diff --git a/src/lua/structs/mod.rs b/src/lua/structs/mod.rs new file mode 100644 index 0000000..6069d04 --- /dev/null +++ b/src/lua/structs/mod.rs @@ -0,0 +1,8 @@ +mod log; +pub use log::Log; + +mod server; +pub use server::Server; + +mod events; +pub use events::Events; diff --git a/src/lua/structs/server.rs b/src/lua/structs/server.rs new file mode 100644 index 0000000..0df4970 --- /dev/null +++ b/src/lua/structs/server.rs @@ -0,0 +1,20 @@ +pub use mlua::prelude::*; +use pumpkin_util::text::TextComponent; + +use crate::SERVER; + +pub struct Server; + +impl LuaUserData for Server { + fn add_methods>(methods: &mut M) { + methods.add_async_function("broadcast_message", async |_, message: String| { + if let Some(server) = SERVER.get() { + for p in server.get_all_players().await { + p.send_system_message(&TextComponent::text(message.clone())) + .await; + } + } + Ok(()) + }); + } +}