diff --git a/src/macros.rs b/src/macros.rs index b895dc7..438d315 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,11 +1,13 @@ #[macro_export] macro_rules! logger { (const $i:ident $name:expr) => { + #[allow(unused)] pub const $i: $crate::once_cell::sync::Lazy<$crate::utils::logger::Logger> = $crate::once_cell::sync::Lazy::new(|| $crate::utils::logger::Logger::new($name)); }; ($i:ident $name:expr) => { + #[allow(unused)] pub const $i: $crate::once_cell::sync::Lazy<$crate::utils::logger::Logger> = $crate::once_cell::sync::Lazy::new(|| $crate::utils::logger::Logger::new($name)); }; diff --git a/src/main.rs b/src/main.rs index b5a7c3d..9134b2f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ mod macros; +mod plugin; mod requests; mod server; mod types; diff --git a/src/plugin/loader.rs b/src/plugin/loader.rs new file mode 100644 index 0000000..43c3294 --- /dev/null +++ b/src/plugin/loader.rs @@ -0,0 +1,90 @@ +use crate::{logger, plugin::Plugin}; +use serde::{Deserialize, Serialize}; +use std::{ + collections::HashMap, + fs, + io::Read, + net::{TcpListener, TcpStream}, + path::Path, + process::Command, + sync::{Arc, Mutex}, +}; + +logger!(LOGGER "Plugin Loader"); + +#[derive(Debug, Serialize, Deserialize)] +pub struct PluginJson { + pub id: String, + pub version: String, + pub supported_versions: Vec, + pub file: String, + pub args: Vec, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct PluginHandshake { + pub id: String, +} + +pub struct PluginLoader { + plugins: Vec, + plugin_clients: Arc>>, +} + +impl PluginLoader { + pub fn new() -> Self { + Self { + plugins: Vec::new(), + plugin_clients: Arc::new(Mutex::new(HashMap::new())), + } + } + + pub fn load(&self, json_path: &Path) -> Plugin { + let json_string = fs::read_to_string(json_path).unwrap(); + let plugin_json: PluginJson = serde_json::from_str(&json_string).unwrap(); + LOGGER.info(format!("Loading {}", plugin_json.id)); + + Command::new(plugin_json.file) + .args(plugin_json.args) + .current_dir("plugins") + .spawn() + .unwrap(); + + while self + .plugin_clients + .lock() + .unwrap() + .get(&plugin_json.id) + .is_none() + {} + Plugin( + self.plugin_clients + .lock() + .unwrap() + .get(&plugin_json.id) + .unwrap() + .try_clone() + .unwrap(), + ) + } + + pub fn start_server(&self) { + let plugin_clients = self.plugin_clients.clone(); + + std::thread::spawn(move || { + let listener = TcpListener::bind("0.0.0.0:7243").unwrap(); + LOGGER.info("Server listening at 0.0.0.0:7243"); + + for stream in listener.incoming() { + let mut stream = stream.unwrap(); + let mut s = String::new(); + stream.read_to_string(&mut s).unwrap(); + let plugin_handshake: PluginHandshake = serde_json::from_str(&s).unwrap(); + plugin_clients + .lock() + .unwrap() + .insert(plugin_handshake.id, stream); + } + }); + } +} diff --git a/src/plugin/mod.rs b/src/plugin/mod.rs new file mode 100644 index 0000000..98f998a --- /dev/null +++ b/src/plugin/mod.rs @@ -0,0 +1,7 @@ +use std::net::TcpStream; + +pub mod loader; + +pub struct Plugin(TcpStream); + +impl Plugin {} diff --git a/src/server.rs b/src/server.rs index 60404a7..dc20de7 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,12 +1,15 @@ use std::{ collections::HashSet, + fs, net::{TcpListener, TcpStream}, path::{Path, PathBuf}, sync::{Arc, Mutex}, }; use crate::{ - logger, types, + logger, + plugin::loader::PluginLoader, + types, utils::{self, client::Client}, }; @@ -25,6 +28,7 @@ pub struct Server { pub config: ServerConfig, pub clients: Mutex>, pub db: utils::database::Database, + pub plugin_loader: PluginLoader, } impl Default for ServerConfig { @@ -32,8 +36,8 @@ impl Default for ServerConfig { Self { port: 7080, server_name: format!("Server Name"), - server_id: format!("offline-server"), - server_key: format!(""), + server_id: format!("important"), + server_key: format!("important"), channels: Vec::new(), } } @@ -58,13 +62,25 @@ impl Server { root: root.to_path_buf(), config, clients: Mutex::new(HashSet::new()), + plugin_loader: PluginLoader::new(), }) } pub fn run(self: &Arc) -> crate::Result<()> { // Load plugins + Self::LOGGER.info("Loading plugins"); + for entry in fs::read_dir(self.root.join("plugins"))? { + let entry = entry?; + let path = entry.path(); + + if path.extension().and_then(|s| s.to_str()) == Some("json") { + self.plugin_loader.load(&path); + } + } + Self::LOGGER.info("Plugins loaded"); // Initialize plugins + Self::LOGGER.info("Initializing plugins"); // Start server let listener = TcpListener::bind(format!("0.0.0.0:{}", self.config.port))?;