mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2025-07-04 00:36:14 +00:00
more lua api stuff
This commit is contained in:
parent
8ee6ba16f2
commit
a23b5a43c0
@ -25,4 +25,4 @@ serde_json = "*"
|
|||||||
toml = "0.5"
|
toml = "0.5"
|
||||||
flate2 = "1.0"
|
flate2 = "1.0"
|
||||||
|
|
||||||
mlua = { version = "0.9.1", features = ["lua54", "vendored"] }
|
mlua = { version = "0.9.1", features = ["lua54", "vendored", "send"] }
|
||||||
|
@ -1 +1,7 @@
|
|||||||
MP.print("test from lua")
|
print("test from lua")
|
||||||
|
|
||||||
|
function onPluginLoaded()
|
||||||
|
print("HI!")
|
||||||
|
end
|
||||||
|
|
||||||
|
MP:RegisterEventHandler("onPluginLoaded", "onPluginLoaded")
|
||||||
|
@ -38,23 +38,19 @@ fn load_plugins() -> Vec<Plugin> {
|
|||||||
if let Ok(entry) = entry {
|
if let Ok(entry) = entry {
|
||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
if path.is_file() {
|
if path.is_file() {
|
||||||
trace!("Found a file! Path: {:?}", path);
|
|
||||||
if let Some(filename) = path.file_name() {
|
if let Some(filename) = path.file_name() {
|
||||||
let filename = filename.to_string_lossy().to_string();
|
let filename = filename.to_string_lossy().to_string();
|
||||||
let filename = filename.split(".").next().unwrap();
|
let filename = filename.split(".").next().unwrap();
|
||||||
if filename == "main" {
|
if filename == "main" {
|
||||||
debug!("Found a potential plugin!");
|
|
||||||
if let Ok(src) = std::fs::read_to_string(&path) {
|
if let Ok(src) = std::fs::read_to_string(&path) {
|
||||||
let extension = path.extension().map(|s| s.to_string_lossy().to_string()).unwrap_or(String::new());
|
let extension = path.extension().map(|s| s.to_string_lossy().to_string()).unwrap_or(String::new());
|
||||||
if let Some(mut backend) = match extension.as_str() {
|
if let Some(backend) = match extension.as_str() {
|
||||||
"lua" => Some(Box::new(backend_lua::BackendLua::new())),
|
"lua" => Some(Box::new(backend_lua::BackendLua::new())),
|
||||||
_ => None,
|
_ => None,
|
||||||
} {
|
} {
|
||||||
debug!("Loading plugin: {:?}", res_path);
|
debug!("Loading plugin: {:?}", res_path);
|
||||||
if backend.load_api().is_ok() {
|
if let Ok(plugin) = Plugin::new(backend, src) {
|
||||||
if backend.load(src).is_ok() {
|
plugins.push(plugin);
|
||||||
plugins.push(Plugin::new(backend));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,31 @@
|
|||||||
use super::Backend;
|
use super::{Backend, ServerBoundPluginEvent};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use tokio::sync::mpsc::Sender;
|
||||||
use mlua::prelude::*;
|
use mlua::prelude::*;
|
||||||
|
use mlua::{UserData, UserDataMethods};
|
||||||
|
|
||||||
|
struct Context {
|
||||||
|
tx: Arc<Sender<ServerBoundPluginEvent>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Context {
|
||||||
|
fn new(tx: Arc<Sender<ServerBoundPluginEvent>>) -> Self {
|
||||||
|
Self {
|
||||||
|
tx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UserData for Context {
|
||||||
|
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
|
methods.add_method("RegisterEventHandler", |_, me, (event_name, handler_name): (String, String)| {
|
||||||
|
debug!("Event handler registered: {} (EVENT) = {} (LUA)", event_name, handler_name);
|
||||||
|
// TODO: Figure out how to handle these errors (?)
|
||||||
|
let _ = me.tx.blocking_send(ServerBoundPluginEvent::RegisterEventHandler((event_name, handler_name)));
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct BackendLua {
|
pub struct BackendLua {
|
||||||
lua: Lua,
|
lua: Lua,
|
||||||
@ -21,17 +47,24 @@ impl Backend for BackendLua {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_api(&mut self) -> anyhow::Result<()> {
|
fn load_api(&mut self, tx: Arc<Sender<ServerBoundPluginEvent>>) -> anyhow::Result<()> {
|
||||||
let print_fn = self.lua.create_function(|_lua, (msg,): (String,)| {
|
let print_fn = self.lua.create_function(|_lua, (msg,): (String,)| {
|
||||||
info!("[LUA] {}", msg);
|
info!("[LUA] {}", msg);
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let api = self.lua.create_table()?;
|
// let register_event_handler_fn = self.lua.create_function(|_lua, (name, handler_name): (String, String)| {
|
||||||
|
// tx.blocking_send(ServerBoundPluginEvent::RegisterEventHandler((name, handler_name)));
|
||||||
|
// Ok(())
|
||||||
|
// })?;
|
||||||
|
|
||||||
api.set("print", print_fn)?;
|
// let api = self.lua.create_table()?;
|
||||||
|
let api = Context::new(tx);
|
||||||
|
// api.set("", thing)?;
|
||||||
|
|
||||||
self.lua.globals().set("MP", api)?;
|
let globals = self.lua.globals();
|
||||||
|
globals.set("MP", api)?;
|
||||||
|
globals.set("print", print_fn)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,34 @@
|
|||||||
pub mod backend_lua;
|
pub mod backend_lua;
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
use tokio::runtime::Runtime;
|
use tokio::runtime::Runtime;
|
||||||
|
use tokio::sync::Mutex;
|
||||||
use tokio::sync::mpsc::{self, Sender, Receiver};
|
use tokio::sync::mpsc::{self, Sender, Receiver};
|
||||||
|
|
||||||
pub trait Backend {
|
/// NOTE: Send is required as the backend is constructed on the main thread and sent over.
|
||||||
|
/// Even if we construct it inside the runtime however, because of tokio, we would
|
||||||
|
// still have to require Send as the runtime might run on different threads (?)
|
||||||
|
pub trait Backend: Send {
|
||||||
fn load(&mut self, code: String) -> anyhow::Result<()>;
|
fn load(&mut self, code: String) -> anyhow::Result<()>;
|
||||||
fn load_api(&mut self) -> anyhow::Result<()> { Ok(()) }
|
fn load_api(&mut self, tx: Arc<Sender<ServerBoundPluginEvent>>) -> anyhow::Result<()> { Ok(()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Argument {
|
||||||
|
Number(f32),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum PluginBoundPluginEvent {
|
pub enum PluginBoundPluginEvent {
|
||||||
|
CallEventHandler((String, Vec<Argument>))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ServerBoundPluginEvent {
|
pub enum ServerBoundPluginEvent {
|
||||||
PluginLoaded,
|
PluginLoaded,
|
||||||
|
|
||||||
|
/// Arguments: (event name, handler function name)
|
||||||
|
RegisterEventHandler((String, String)),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Plugin {
|
pub struct Plugin {
|
||||||
@ -25,27 +38,33 @@ pub struct Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Plugin {
|
impl Plugin {
|
||||||
pub fn new(backend: Box<dyn Backend>) -> Self {
|
pub fn new(mut backend: Box<dyn Backend>, src: String) -> anyhow::Result<Self> {
|
||||||
let runtime = Runtime::new().expect("Failed to create a tokio Runtime!");
|
let runtime = Runtime::new().expect("Failed to create a tokio Runtime!");
|
||||||
let (pb_tx, mut pb_rx) = mpsc::channel(1_000);
|
let (pb_tx, mut pb_rx) = mpsc::channel(1_000);
|
||||||
let (sb_tx, sb_rx) = mpsc::channel(1_000);
|
let (sb_tx, sb_rx) = mpsc::channel(1_000);
|
||||||
runtime.spawn(async move {
|
let sb_tx = Arc::new(sb_tx);
|
||||||
if sb_tx.send(ServerBoundPluginEvent::PluginLoaded).await.is_err() {
|
runtime.spawn_blocking(move || {
|
||||||
error!("Plugin communication channels somehow already closed!");
|
if backend.load_api(sb_tx.clone()).is_ok() {
|
||||||
return;
|
if backend.load(src).is_ok() {
|
||||||
|
if sb_tx.blocking_send(ServerBoundPluginEvent::PluginLoaded).is_err() {
|
||||||
|
error!("Plugin communication channels somehow already closed!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if let Some(message) = pb_rx.recv().await {
|
if let Some(message) = pb_rx.blocking_recv() {
|
||||||
debug!("Received message: {:?}", message);
|
debug!("Received message: {:?}", message);
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Self {
|
Ok(Self {
|
||||||
runtime,
|
runtime,
|
||||||
tx: pb_tx,
|
tx: pb_tx,
|
||||||
rx: sb_rx,
|
rx: sb_rx,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user