mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2026-10-25 13:30:43 +00:00
very early version of plugin system
This commit is contained in:
1 parent
0b6ad43fbb
commit
8ee6ba16f2
7 files changed
+244
-2
No files matched your search
Generated
+89
@@ -99,6 +99,7 @@ dependencies = [
|
|||||||
"flate2",
|
"flate2",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
|
"mlua",
|
||||||
"nalgebra",
|
"nalgebra",
|
||||||
"num_enum",
|
"num_enum",
|
||||||
"pretty_env_logger",
|
"pretty_env_logger",
|
||||||
@@ -121,6 +122,16 @@ version = "2.4.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bstr"
|
||||||
|
version = "1.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.14.0"
|
version = "3.14.0"
|
||||||
@@ -179,6 +190,12 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encoding_rs"
|
name = "encoding_rs"
|
||||||
version = "0.8.33"
|
version = "0.8.33"
|
||||||
@@ -354,6 +371,15 @@ version = "0.3.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
|
checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "home"
|
||||||
|
version = "0.5.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "http"
|
name = "http"
|
||||||
version = "0.2.9"
|
version = "0.2.9"
|
||||||
@@ -509,6 +535,25 @@ version = "0.4.20"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lua-src"
|
||||||
|
version = "546.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7c26d4af78361e025a3d03a2b964cd1592aff7495f4d4f7947218c084c6fdca8"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "luajit-src"
|
||||||
|
version = "210.4.8+resty107baaf"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e05167e8b2a2185758d83ed23541e5bd8bce37072e4204e0ef2c9b322bc87c4e"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"which",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "matrixmultiply"
|
name = "matrixmultiply"
|
||||||
version = "0.3.8"
|
version = "0.3.8"
|
||||||
@@ -551,6 +596,32 @@ dependencies = [
|
|||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mlua"
|
||||||
|
version = "0.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c3a7a7ff4481ec91b951a733390211a8ace1caba57266ccb5f4d4966704e560"
|
||||||
|
dependencies = [
|
||||||
|
"bstr",
|
||||||
|
"mlua-sys",
|
||||||
|
"num-traits",
|
||||||
|
"once_cell",
|
||||||
|
"rustc-hash",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mlua-sys"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3ec8b54eddb76093069cce9eeffb4c7b3a1a0fe66962d7bd44c4867928149ca3"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
|
"lua-src",
|
||||||
|
"luajit-src",
|
||||||
|
"pkg-config",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nalgebra"
|
name = "nalgebra"
|
||||||
version = "0.31.4"
|
version = "0.31.4"
|
||||||
@@ -887,6 +958,12 @@ version = "0.1.23"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-hash"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.38.21"
|
version = "0.38.21"
|
||||||
@@ -1356,6 +1433,18 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "which"
|
||||||
|
version = "4.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
"home",
|
||||||
|
"once_cell",
|
||||||
|
"rustix",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wide"
|
name = "wide"
|
||||||
version = "0.7.13"
|
version = "0.7.13"
|
||||||
|
|||||||
@@ -24,3 +24,5 @@ serde_json = "*"
|
|||||||
|
|
||||||
toml = "0.5"
|
toml = "0.5"
|
||||||
flate2 = "1.0"
|
flate2 = "1.0"
|
||||||
|
|
||||||
|
mlua = { version = "0.9.1", features = ["lua54", "vendored"] }
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
MP.print("test from lua")
|
||||||
@@ -1,2 +1,4 @@
|
|||||||
# Todo List
|
# Todo List
|
||||||
- Redo the entire download process. Currently it is very very clunky, and the implementation is terrible. It essentially acts as a second client and it would be much better if this was either implemented as part of the original client (server-sided client), or if the entire download flow was redone both client and server side.
|
- Redo the entire download process. Currently it is very very clunky, and the implementation is terrible. It essentially acts as a second client and it would be much better if this was either implemented as part of the original client (server-sided client), or if the entire download flow was redone both client and server side.
|
||||||
|
- Implement the Lua API (and discuss wanted changes).
|
||||||
|
- Implement the auth-key stuff to have public servers be possible.
|
||||||
+61
-2
@@ -1,6 +1,7 @@
|
|||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::sync::{Arc, Mutex, atomic::{AtomicBool, Ordering}};
|
use std::sync::{Arc, Mutex, atomic::{AtomicBool, Ordering}};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use tokio::net::{TcpListener, UdpSocket};
|
use tokio::net::{TcpListener, UdpSocket};
|
||||||
use tokio::task::{JoinHandle, JoinSet};
|
use tokio::task::{JoinHandle, JoinSet};
|
||||||
@@ -13,14 +14,64 @@ mod backend;
|
|||||||
mod car;
|
mod car;
|
||||||
mod client;
|
mod client;
|
||||||
mod packet;
|
mod packet;
|
||||||
|
mod plugins;
|
||||||
|
|
||||||
pub use backend::*;
|
pub use backend::*;
|
||||||
pub use car::*;
|
pub use car::*;
|
||||||
pub use client::*;
|
pub use client::*;
|
||||||
pub use packet::*;
|
pub use packet::*;
|
||||||
|
pub use plugins::*;
|
||||||
|
|
||||||
pub use crate::config::Config;
|
pub use crate::config::Config;
|
||||||
|
|
||||||
|
fn load_plugins() -> Vec<Plugin> {
|
||||||
|
let mut plugins = Vec::new();
|
||||||
|
|
||||||
|
for res_entry in std::fs::read_dir("Resources/Server").expect("Failed to read Resources/Server!") {
|
||||||
|
if let Ok(res_entry) = res_entry {
|
||||||
|
let res_path = res_entry.path();
|
||||||
|
if res_path.is_dir() {
|
||||||
|
|
||||||
|
// TODO: Fix this (split into different functions)
|
||||||
|
if let Ok(read_dir) = std::fs::read_dir(&res_path) {
|
||||||
|
for entry in read_dir {
|
||||||
|
if let Ok(entry) = entry {
|
||||||
|
let path = entry.path();
|
||||||
|
if path.is_file() {
|
||||||
|
trace!("Found a file! Path: {:?}", path);
|
||||||
|
if let Some(filename) = path.file_name() {
|
||||||
|
let filename = filename.to_string_lossy().to_string();
|
||||||
|
let filename = filename.split(".").next().unwrap();
|
||||||
|
if filename == "main" {
|
||||||
|
debug!("Found a potential plugin!");
|
||||||
|
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());
|
||||||
|
if let Some(mut backend) = match extension.as_str() {
|
||||||
|
"lua" => Some(Box::new(backend_lua::BackendLua::new())),
|
||||||
|
_ => None,
|
||||||
|
} {
|
||||||
|
debug!("Loading plugin: {:?}", res_path);
|
||||||
|
if backend.load_api().is_ok() {
|
||||||
|
if backend.load(src).is_ok() {
|
||||||
|
plugins.push(Plugin::new(backend));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, IntoPrimitive, Copy, Clone, Debug)]
|
#[derive(PartialEq, IntoPrimitive, Copy, Clone, Debug)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
enum ServerState {
|
enum ServerState {
|
||||||
@@ -49,6 +100,8 @@ pub struct Server {
|
|||||||
config: Arc<Config>,
|
config: Arc<Config>,
|
||||||
|
|
||||||
last_plist_update: Instant,
|
last_plist_update: Instant,
|
||||||
|
|
||||||
|
plugins: Vec<Plugin>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Server {
|
impl Server {
|
||||||
@@ -68,6 +121,10 @@ impl Server {
|
|||||||
Arc::new(UdpSocket::bind(bind_addr).await?)
|
Arc::new(UdpSocket::bind(bind_addr).await?)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Load existing plugins
|
||||||
|
let plugins = load_plugins();
|
||||||
|
|
||||||
|
// Start client runtime
|
||||||
let clients_incoming = Arc::new(Mutex::new(Vec::new()));
|
let clients_incoming = Arc::new(Mutex::new(Vec::new()));
|
||||||
let clients_incoming_ref = Arc::clone(&clients_incoming);
|
let clients_incoming_ref = Arc::clone(&clients_incoming);
|
||||||
debug!("Client acception runtime starting...");
|
debug!("Client acception runtime starting...");
|
||||||
@@ -86,7 +143,7 @@ impl Server {
|
|||||||
|
|
||||||
let mut client = Client::new(socket);
|
let mut client = Client::new(socket);
|
||||||
match client.authenticate(&cfg_ref).await {
|
match client.authenticate(&cfg_ref).await {
|
||||||
Ok(isClient) if isClient => {
|
Ok(is_client) if is_client => {
|
||||||
let mut lock = ci_ref
|
let mut lock = ci_ref
|
||||||
.lock()
|
.lock()
|
||||||
.map_err(|e| error!("{:?}", e))
|
.map_err(|e| error!("{:?}", e))
|
||||||
@@ -94,7 +151,7 @@ impl Server {
|
|||||||
lock.push(client);
|
lock.push(client);
|
||||||
drop(lock);
|
drop(lock);
|
||||||
},
|
},
|
||||||
Ok(isClient) => {
|
Ok(_is_client) => {
|
||||||
debug!("Downloader?");
|
debug!("Downloader?");
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@@ -134,6 +191,8 @@ impl Server {
|
|||||||
config: config,
|
config: config,
|
||||||
|
|
||||||
last_plist_update: Instant::now(),
|
last_plist_update: Instant::now(),
|
||||||
|
|
||||||
|
plugins,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
use super::Backend;
|
||||||
|
use mlua::prelude::*;
|
||||||
|
|
||||||
|
pub struct BackendLua {
|
||||||
|
lua: Lua,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BackendLua {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let lua = Lua::new();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
lua,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Backend for BackendLua {
|
||||||
|
fn load(&mut self, code: String) -> anyhow::Result<()> {
|
||||||
|
self.lua.load(code).exec().map_err(|e| { error!("[LUA] {:?}", e); e })?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_api(&mut self) -> anyhow::Result<()> {
|
||||||
|
let print_fn = self.lua.create_function(|_lua, (msg,): (String,)| {
|
||||||
|
info!("[LUA] {}", msg);
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let api = self.lua.create_table()?;
|
||||||
|
|
||||||
|
api.set("print", print_fn)?;
|
||||||
|
|
||||||
|
self.lua.globals().set("MP", api)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
pub mod backend_lua;
|
||||||
|
|
||||||
|
use tokio::runtime::Runtime;
|
||||||
|
use tokio::sync::mpsc::{self, Sender, Receiver};
|
||||||
|
|
||||||
|
pub trait Backend {
|
||||||
|
fn load(&mut self, code: String) -> anyhow::Result<()>;
|
||||||
|
fn load_api(&mut self) -> anyhow::Result<()> { Ok(()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum PluginBoundPluginEvent {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ServerBoundPluginEvent {
|
||||||
|
PluginLoaded,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Plugin {
|
||||||
|
runtime: Runtime,
|
||||||
|
tx: Sender<PluginBoundPluginEvent>,
|
||||||
|
rx: Receiver<ServerBoundPluginEvent>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Plugin {
|
||||||
|
pub fn new(backend: Box<dyn Backend>) -> Self {
|
||||||
|
let runtime = Runtime::new().expect("Failed to create a tokio Runtime!");
|
||||||
|
let (pb_tx, mut pb_rx) = mpsc::channel(1_000);
|
||||||
|
let (sb_tx, sb_rx) = mpsc::channel(1_000);
|
||||||
|
runtime.spawn(async move {
|
||||||
|
if sb_tx.send(ServerBoundPluginEvent::PluginLoaded).await.is_err() {
|
||||||
|
error!("Plugin communication channels somehow already closed!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
loop {
|
||||||
|
if let Some(message) = pb_rx.recv().await {
|
||||||
|
debug!("Received message: {:?}", message);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Self {
|
||||||
|
runtime,
|
||||||
|
tx: pb_tx,
|
||||||
|
rx: sb_rx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user