From ff067f8e4b03cffa5f7bec9a968f57ecc5127ef0 Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Thu, 30 Jun 2022 08:08:48 +0100 Subject: [PATCH 1/3] way too much happened here + added scriptable version of the server, networkManager and clientManager + added lua engine creation +also added unfinished rhai support + also did some restructuring --- server/Cargo.toml | 3 +- server/src/lua/builder.rs | 33 +++++++ server/src/lua/client_lua.rs | 41 --------- server/src/lua/client_manager_lua.rs | 63 ------------- server/src/lua/lua_manager.rs | 89 +++++++++++++++++++ server/src/lua/mod.rs | 9 +- server/src/lua/server_lua.rs | 38 -------- server/src/main.rs | 3 + server/src/rhai/builder.rs | 58 ++++++++++++ server/src/rhai/mod.rs | 4 + server/src/rhai/rhai_manager.rs | 37 ++++++++ server/src/scripting/mod.rs | 3 + .../scripting/scriptable_client_manager.rs | 19 ++++ .../scripting/scriptable_network_manager.rs | 19 ++++ server/src/scripting/scriptable_server.rs | 70 +++++++++++++++ server/src/server/builder.rs | 2 +- server/src/server/messages.rs | 23 +++++ server/src/server/mod.rs | 4 +- server/src/server/server.rs | 56 ++++++++---- 19 files changed, 408 insertions(+), 166 deletions(-) create mode 100644 server/src/lua/builder.rs delete mode 100644 server/src/lua/client_lua.rs delete mode 100644 server/src/lua/client_manager_lua.rs create mode 100644 server/src/lua/lua_manager.rs delete mode 100644 server/src/lua/server_lua.rs create mode 100644 server/src/rhai/builder.rs create mode 100644 server/src/rhai/mod.rs create mode 100644 server/src/rhai/rhai_manager.rs create mode 100644 server/src/scripting/mod.rs create mode 100644 server/src/scripting/scriptable_client_manager.rs create mode 100644 server/src/scripting/scriptable_network_manager.rs create mode 100644 server/src/scripting/scriptable_server.rs create mode 100644 server/src/server/messages.rs diff --git a/server/Cargo.toml b/server/Cargo.toml index 66bc9fb..c45357a 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -31,7 +31,8 @@ tokio = { version = "1.9.0", features = ["full"] } futures = "0.3.16" async-trait = "0.1.52" actix = "0.13" -mlua = { version = "0.7.3", features=["lua54", "async", "serde", "macros"] } +rhai = {version = "1.7.0"} +mlua = { version = "0.8.0", features=["lua54", "async", "serde", "macros", "vendored"] } libloading = "0.7" toml = "0.4.2" aquamarine = "0.1.11" diff --git a/server/src/lua/builder.rs b/server/src/lua/builder.rs new file mode 100644 index 0000000..f696f37 --- /dev/null +++ b/server/src/lua/builder.rs @@ -0,0 +1,33 @@ +use actix::{Actor, Addr}; +use mlua::Lua; +use rhai::{Engine, RegisterNativeFunction, Scope}; +use crate::client_management::ClientManager; +use crate::lua::lua_manager::LuaManager; +use crate::network::NetworkManager; +use crate::Server; + +pub struct Builder { + pub(crate) engine: Lua, + pub(super) server: Addr, + pub(super) network_manager: Addr, + pub(super) client_manager: Addr, +} + +impl Builder { + pub(super) fn new( + server: Addr, + network_manager: Addr, + client_manager: Addr, + ) -> Self { + Builder { + engine: Lua::new(), + server, + network_manager, + client_manager, + } + } + + pub(crate) fn build(self) -> Addr { + Addr::from(self) + } +} \ No newline at end of file diff --git a/server/src/lua/client_lua.rs b/server/src/lua/client_lua.rs deleted file mode 100644 index bb8523e..0000000 --- a/server/src/lua/client_lua.rs +++ /dev/null @@ -1,41 +0,0 @@ -use std::sync::Arc; -use mlua::prelude::LuaUserData; -use mlua::{UserDataFields, UserDataMethods}; -use crate::client::Client; -use crate::messages::ClientMessage; - -pub struct ClientLua(pub Arc>) - where - Out: From + Send; - -impl ClientLua - where - Out: From + Send -{ - pub fn new(client: Arc>) -> Self { - ClientLua(client) - } -} - -impl LuaUserData for ClientLua - where - Out: From + Send -{ - fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) { - fields.add_field_method_get("uuid", |_lua, this| { - Ok(this.0.details.uuid.to_string()) - }); - - fields.add_field_method_get("username", |_lua, this| { - Ok(this.0.details.username.to_string()) - }); - - fields.add_field_method_get("address", |_lua, this| { - Ok(this.0.details.address.to_string()) - }); - } - - fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(_methods: &mut M) { - - } -} \ No newline at end of file diff --git a/server/src/lua/client_manager_lua.rs b/server/src/lua/client_manager_lua.rs deleted file mode 100644 index bb2fa35..0000000 --- a/server/src/lua/client_manager_lua.rs +++ /dev/null @@ -1,63 +0,0 @@ -use std::str::FromStr; -use std::sync::Arc; -use mlua::{Function, MetaMethod, Nil, ToLua, UserDataFields, UserDataMethods}; -use mlua::prelude::LuaUserData; -use uuid::Uuid; -use crate::client_manager::{ClientManager, ClientMgrMessage}; -use crate::lua::ClientLua; - -#[derive(Clone)] -pub struct ClientManagerLua<'lua, Out: 'static>(pub Arc>, pub Vec>) - where - Out: From + Send; - -impl ClientManagerLua<'_, Out> - where - Out: From + Send -{ - pub fn new(manager: Arc>) -> Self { - ClientManagerLua(manager, Vec::new()) - } -} - -impl LuaUserData for ClientManagerLua<'_, Out> - where - Out: From + Clone + Send -{ - fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) { - - } - - fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { - methods.add_async_method("getCount", |_lua,this,()| { - let this = this.0.clone(); - async move { - Ok(this.clients.lock().await.len()) - } - }); - - methods.add_async_method("getClientList", |_lua,this,()| { - let this = this.0.clone(); - async move { - let clients = this.clients.lock().await; - let clients: Vec> = clients.iter() - .map(|(_id,c)| ClientLua::new(c.clone())) - .collect(); - Ok(clients) - } - }); - - methods.add_async_meta_method(MetaMethod::Index, |lua, this, (index): (String)| { - let manager = this.0.clone(); - async move { - if let Ok(id) = Uuid::from_str(&index) { - let map = manager.clients.lock().await; - if let Some(found) = map.get(&id) { - return Ok(ClientLua::new(found.clone()).to_lua(lua)?); - } - } - return Ok(Nil); - } - }); - } -} \ No newline at end of file diff --git a/server/src/lua/lua_manager.rs b/server/src/lua/lua_manager.rs new file mode 100644 index 0000000..d699728 --- /dev/null +++ b/server/src/lua/lua_manager.rs @@ -0,0 +1,89 @@ +use actix::{Actor, Addr, ArbiterHandle, AsyncContext, Context, Running}; +use actix::fut::wrap_future; +use mlua::{Lua, Thread, ThreadStatus}; +use rhai::{Engine, Func, Scope}; +use crate::client_management::ClientManager; +use crate::lua::builder::Builder; +use crate::network::NetworkManager; +use crate::scripting::scriptable_server::ScriptableServer; +use crate::Server; + +pub struct LuaManager { + pub(super) engine: Lua, + pub(super) server: Addr, + pub(super) network_manager: Addr, + pub(super) client_manager: Addr, +} + +impl LuaManager { + pub fn create( + server: Addr, + network_manager: Addr, + client_manager: Addr + ) -> Builder { + Builder::new( + server.clone(), + network_manager.clone(), + client_manager.clone() + ) + } + + fn create_lua(&self) -> Lua { + let engine = Lua::new(); + let server = ScriptableServer::from(self.server.clone()); + + let api = engine.create_table().unwrap(); + api.set::<&str, ScriptableServer>("server", server).unwrap(); + api.set::<&str, i32>("a", 12).unwrap(); + + engine.globals().set("chat", api).unwrap(); + engine + } +} + +impl Actor for LuaManager { + type Context = Context; + + fn started(&mut self, ctx: &mut Self::Context) { + let engine = self.create_lua(); + + ctx.spawn(wrap_future(async move { + let coroutine: Thread = engine.load(r#" + coroutine.create(function () + print("hello lua") + print(chat.server.Test) + print(chat.server:name()) + end) + "#).eval().unwrap(); + let coroutine = coroutine.into_async::<(),()>(()); + coroutine.await.expect("TODO: panic message"); + })); + } +} + +// by implementing it for the addr type, +// we enforce the actor model on the consumer of the api. +impl From for Addr { + fn from(b: Builder) -> Addr { + let mgr = LuaManager { + engine: b.engine, + server: b.server.clone(), + network_manager: b.network_manager.clone(), + client_manager: b.client_manager.clone() + }; + + let server = ScriptableServer::from(b.server); + + let api = mgr.engine.create_table().unwrap(); + api.set::<&str, ScriptableServer>("server", server).unwrap(); + api.set::<&str, i32>("a", 12).unwrap(); + + let a = api.get::<&str, i32>("a").unwrap(); + + println!("Lua stored: {}", a); + + mgr.engine.globals().set("chat", api).unwrap(); + + mgr.start() + } +} diff --git a/server/src/lua/mod.rs b/server/src/lua/mod.rs index 56d5028..50fc6ce 100644 --- a/server/src/lua/mod.rs +++ b/server/src/lua/mod.rs @@ -1,7 +1,4 @@ -mod client_lua; -mod client_manager_lua; -mod server_lua; +mod lua_manager; +mod builder; -pub use client_lua::ClientLua; -pub use client_manager_lua::ClientManagerLua; -pub use server_lua::ServerLua; \ No newline at end of file +pub use lua_manager::LuaManager; \ No newline at end of file diff --git a/server/src/lua/server_lua.rs b/server/src/lua/server_lua.rs deleted file mode 100644 index c1267de..0000000 --- a/server/src/lua/server_lua.rs +++ /dev/null @@ -1,38 +0,0 @@ -use std::sync::Arc; -use mlua::prelude::LuaUserData; -use mlua::{UserDataFields, UserDataMethods}; -use crate::lua::ClientManagerLua; -use crate::Server; - -/// # ServerLua -/// A wrapper struct for making the Server lua scriptable. -/// -/// # Attributes -/// - 1: A reference to the server. -#[derive(Clone)] -pub struct ServerLua(Arc); - -impl ServerLua { - pub fn new(server: Arc) -> Self { - ServerLua(server) - } -} - -impl LuaUserData for ServerLua { - fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) { - fields.add_field_method_get("ClientManager", |lua,this| { - println!("Getting count"); - Ok(ClientManagerLua(this.0.client_manager.clone(), vec![])) - }); - fields.add_field_method_get("NetworkManager", |lua,this| { - Ok("unimplemented") - }); - fields.add_field_method_get("address", |lua,this| { - Ok("unimplemented") - }); - } - - fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(_methods: &mut M) { - - } -} \ No newline at end of file diff --git a/server/src/main.rs b/server/src/main.rs index d66d87d..54aa344 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -7,6 +7,9 @@ pub(crate) mod server; pub(crate) mod client_management; pub(crate) mod network; pub(crate) mod prelude; +pub(crate) mod rhai; +pub(crate) mod lua; +pub(crate) mod scripting; use std::env::args; use server::Server; diff --git a/server/src/rhai/builder.rs b/server/src/rhai/builder.rs new file mode 100644 index 0000000..772e2dd --- /dev/null +++ b/server/src/rhai/builder.rs @@ -0,0 +1,58 @@ +use actix::{Actor, Addr}; +use mlua::Lua; +use rhai::{Engine, RegisterNativeFunction, Scope}; +use crate::client_management::ClientManager; +use crate::rhai::rhai_manager::RhaiManager; +use crate::network::NetworkManager; +use crate::Server; + +pub struct Builder { + engine: Engine, + server: Addr, + network_manager: Addr, + client_manager: Addr, + scope: Scope<'static>, +} + +impl Builder { + pub(super) fn new( + server: Addr, + network_manager: Addr, + client_manager: Addr, + ) -> Self { + Builder { + engine: Engine::new(), + server, + network_manager, + client_manager, + scope: Default::default() + } + } + + pub fn scope_object(mut self, name: &str, obj: T) -> Self + where + T: Clone { + self.engine.register_type::(); + self.scope.set_value(name, obj); + self + } + + pub fn scope_fn(mut self, name: &str, func: F ) -> Self + where + F: RegisterNativeFunction + { + self.engine.register_fn(name, func); + self + } + + + pub(crate) fn build(self) -> Addr { + RhaiManager { + engine: self.engine, + scope: self.scope, + server: self.server, + network_manager: self.network_manager, + client_manager: self.client_manager + }.start() + } +} \ No newline at end of file diff --git a/server/src/rhai/mod.rs b/server/src/rhai/mod.rs new file mode 100644 index 0000000..f9440f8 --- /dev/null +++ b/server/src/rhai/mod.rs @@ -0,0 +1,4 @@ +mod rhai_manager; +mod builder; + +pub use rhai_manager::RhaiManager; \ No newline at end of file diff --git a/server/src/rhai/rhai_manager.rs b/server/src/rhai/rhai_manager.rs new file mode 100644 index 0000000..aed917b --- /dev/null +++ b/server/src/rhai/rhai_manager.rs @@ -0,0 +1,37 @@ +use actix::{Actor, Addr, ArbiterHandle, AsyncContext, Context, Running}; +use actix::fut::wrap_future; +use rhai::{Engine, Func, Scope}; +use crate::client_management::ClientManager; +use crate::rhai::builder::Builder; +use crate::network::NetworkManager; +use crate::Server; + +pub struct RhaiManager { + pub(super) engine: Engine, + pub(super) scope: Scope<'static>, + pub(super) server: Addr, + pub(super) network_manager: Addr, + pub(super) client_manager: Addr, +} + +impl RhaiManager { + pub fn create( + server: Addr, + network_manager: Addr, + client_manager: Addr + ) -> Builder { + Builder::new(server.clone(), network_manager.clone(), client_manager.clone()) + .scope_object("server", server) + } +} + +impl Actor for RhaiManager { + type Context = Context; + + fn started(&mut self, ctx: &mut Self::Context) { + self.engine.run(r#" + print("hello rhai") + "#).unwrap(); + } +} + diff --git a/server/src/scripting/mod.rs b/server/src/scripting/mod.rs new file mode 100644 index 0000000..9664e44 --- /dev/null +++ b/server/src/scripting/mod.rs @@ -0,0 +1,3 @@ +pub(crate) mod scriptable_server; +pub(crate) mod scriptable_network_manager; +pub(crate) mod scriptable_client_manager; \ No newline at end of file diff --git a/server/src/scripting/scriptable_client_manager.rs b/server/src/scripting/scriptable_client_manager.rs new file mode 100644 index 0000000..2b81538 --- /dev/null +++ b/server/src/scripting/scriptable_client_manager.rs @@ -0,0 +1,19 @@ +use actix::Addr; +use mlua::UserData; +use crate::client_management::ClientManager; + +pub(crate) struct ScriptableClientManager { + addr: Addr +} + +impl UserData for ScriptableClientManager { + +} + +impl From> for ScriptableClientManager { + fn from(addr: Addr) -> Self { + Self { + addr + } + } +} \ No newline at end of file diff --git a/server/src/scripting/scriptable_network_manager.rs b/server/src/scripting/scriptable_network_manager.rs new file mode 100644 index 0000000..c774daf --- /dev/null +++ b/server/src/scripting/scriptable_network_manager.rs @@ -0,0 +1,19 @@ +use actix::Addr; +use mlua::UserData; +use crate::network::NetworkManager; + +pub(crate) struct ScriptableNetworkManager { + addr: Addr +} + +impl UserData for ScriptableNetworkManager { + +} + +impl From> for ScriptableNetworkManager { + fn from(addr: Addr) -> Self { + Self { + addr + } + } +} \ No newline at end of file diff --git a/server/src/scripting/scriptable_server.rs b/server/src/scripting/scriptable_server.rs new file mode 100644 index 0000000..fff7fe5 --- /dev/null +++ b/server/src/scripting/scriptable_server.rs @@ -0,0 +1,70 @@ +use actix::Addr; +use mlua::{Error, UserData, UserDataFields, UserDataMethods}; +use crate::scripting::scriptable_client_manager::ScriptableClientManager; +use crate::scripting::scriptable_network_manager::ScriptableNetworkManager; + +use crate::server::*; +use crate::server::ServerDataResponse::{ClientManager, Name, NetworkManager, Owner, Port}; + +#[derive(Clone)] +pub(crate) struct ScriptableServer { + pub(super) addr: Addr +} + +impl UserData for ScriptableServer { + + fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_async_method("name", |_lua, obj, ()| async move { + let name: Option = obj.addr.send(ServerDataMessage::Name).await.ok(); + if let Some(Name(name)) = name { + Ok(name) + } else { + Err(Error::RuntimeError("Name returned null or other value".to_string())) + } + }); + + methods.add_async_method("port", |_lua, obj, ()| async move { + let port: Option = obj.addr.send(ServerDataMessage::Port).await.ok(); + if let Some(Port(name)) = port { + Ok(name) + } else { + Err(Error::RuntimeError("Name returned null or other value".to_string())) + } + }); + + methods.add_async_method("owner", |_lua, obj, ()| async move { + let owner: Option = obj.addr.send(ServerDataMessage::Owner).await.ok(); + if let Some(Owner(name)) = owner { + Ok(name) + } else { + Err(Error::RuntimeError("Name returned null or other value".to_string())) + } + }); + + methods.add_async_method("client_manager", |_lua, obj, ()| async move { + let name: Option = obj.addr.send(ServerDataMessage::ClientManager).await.ok(); + if let Some(ClientManager(Some(cm))) = name { + Ok(ScriptableClientManager::from(cm)) + } else { + Err(Error::RuntimeError("Name returned null or other value".to_string())) + } + }); + + methods.add_async_method("network_manager", |_lua, obj, ()| async move { + let name: Option = obj.addr.send(ServerDataMessage::NetworkManager).await.ok(); + if let Some(NetworkManager(Some(nm))) = name { + Ok(ScriptableNetworkManager::from(nm)) + } else { + Err(Error::RuntimeError("Name returned null or other value".to_string())) + } + }); + } +} + +impl From> for ScriptableServer { + fn from(addr: Addr) -> Self { + Self { + addr + } + } +} diff --git a/server/src/server/builder.rs b/server/src/server/builder.rs index 6ec5756..51a2206 100644 --- a/server/src/server/builder.rs +++ b/server/src/server/builder.rs @@ -7,7 +7,7 @@ pub struct ServerBuilder { pub(super) owner: Option, } -impl ServerBuilder { +impl<'rhai> ServerBuilder { pub(super) fn new() -> Self { Self { name: None, diff --git a/server/src/server/messages.rs b/server/src/server/messages.rs new file mode 100644 index 0000000..e64bbcf --- /dev/null +++ b/server/src/server/messages.rs @@ -0,0 +1,23 @@ +use actix::{Addr, Message, MessageResponse}; +use crate::client_management::ClientManager; +use crate::network::NetworkManager; + + +#[derive(Message, Clone)] +#[rtype(result = "ServerDataResponse")] +pub enum ServerDataMessage { + Name, + Port, + Owner, + ClientManager, + NetworkManager, +} + +#[derive(MessageResponse, Clone)] +pub enum ServerDataResponse { + Name(String), + Port(u16), + Owner(String), + ClientManager(Option>), + NetworkManager(Option>), +} \ No newline at end of file diff --git a/server/src/server/mod.rs b/server/src/server/mod.rs index 6f55931..a7e9052 100644 --- a/server/src/server/mod.rs +++ b/server/src/server/mod.rs @@ -6,7 +6,9 @@ mod server; mod config; mod builder; +mod messages; use config::ServerConfig; pub use server::Server; -pub(crate) use builder::ServerBuilder; \ No newline at end of file +pub use builder::ServerBuilder; +pub use messages::*; \ No newline at end of file diff --git a/server/src/server/server.rs b/server/src/server/server.rs index 59ee247..361ebfc 100644 --- a/server/src/server/server.rs +++ b/server/src/server/server.rs @@ -1,13 +1,20 @@ +//! This crate holds the implementations and functions for the server +//! including server boot procedures + use actix::{Actor, ActorFutureExt, Addr, AsyncContext, Context, ContextFutureSpawner, Handler}; +use actix::dev::MessageResponse; use actix::fut::wrap_future; +use mlua::Lua; use foundation::ClientDetails; use foundation::messages::network::NetworkSockOut::GotInfo; use crate::client_management::{Client, ClientManager, ClientManagerOutput}; use crate::client_management::ClientManagerMessage::AddClient; +use crate::lua::LuaManager; +use crate::rhai::RhaiManager; use crate::network::{Connection, NetworkManager, NetworkMessage, NetworkOutput}; use crate::network::ConnectionMessage::{CloseConnection, SendData}; use crate::network::NetworkOutput::{InfoRequested, NewClient}; -use crate::server::{builder, ServerBuilder}; +use crate::server::{builder, ServerBuilder, ServerDataMessage, ServerDataResponse}; use crate::server::config::ServerConfig; /// This struct is the main actor of the server. @@ -16,18 +23,11 @@ pub struct Server { config: ServerConfig, network_manager: Option>, client_management: Option>, + rhai_manager: Option>, + lua_manager: Option> } impl Server { - pub(crate) fn new() -> Addr { - Server { - config: Default::default(), - network_manager: None, - client_management: None, - } - .start() - } - pub fn create() -> builder::ServerBuilder { ServerBuilder::new() } @@ -75,11 +75,20 @@ impl Actor for Server { let nm = NetworkManager::create(addr.clone().recipient()) .port(self.config.port) .build(); - self.network_manager.replace(nm); + self.network_manager.replace(nm.clone()); - self.client_management.replace(ClientManager::new( + let cm = ClientManager::new( addr.clone().recipient(), - )); + ); + self.client_management.replace(cm.clone()); + + let rm = RhaiManager::create(ctx.address(), nm.clone(), cm.clone()) + .build(); + self.rhai_manager.replace(rm); + + let lm = LuaManager::create(ctx.address(), nm, cm) + .build(); + self.lua_manager.replace(lm); if let Some(net_mgr) = self.network_manager.as_ref() { net_mgr.do_send(NetworkMessage::StartListening); @@ -87,6 +96,21 @@ impl Actor for Server { } } +impl Handler for Server { + type Result = ServerDataResponse; + + fn handle(&mut self, msg: ServerDataMessage, ctx: &mut Self::Context) -> Self::Result { + println!("data message"); + match msg { + ServerDataMessage::Name => ServerDataResponse::Name(self.config.name.clone()), + ServerDataMessage::Port => ServerDataResponse::Port(self.config.port.clone()), + ServerDataMessage::Owner => ServerDataResponse::Owner(self.config.owner.clone()), + ServerDataMessage::ClientManager => ServerDataResponse::ClientManager(self.client_management.clone()), + ServerDataMessage::NetworkManager => ServerDataResponse::NetworkManager(self.network_manager.clone()), + } + } +} + impl Handler for Server { type Result = (); fn handle( @@ -118,7 +142,7 @@ impl Handler for Server { } } -impl From for Server { +impl From for Server { fn from(builder: ServerBuilder) -> Self { Server { config: ServerConfig { @@ -127,7 +151,9 @@ impl From for Server { owner: builder.owner.unwrap_or_else(|| "Default owner".to_string()), }, network_manager: None, - client_management: None + client_management: None, + rhai_manager: None, + lua_manager: None } } } \ No newline at end of file From 51cea3523ef13e5825217e8437f24fc8235c00c6 Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Fri, 1 Jul 2022 00:43:13 +0100 Subject: [PATCH 2/3] made client manager and clients scriptable --- server/Cargo.toml | 2 +- .../src/client_management/client_manager.rs | 54 ++++++++++--------- server/src/client_management/messages.rs | 29 ++++++++++ server/src/client_management/mod.rs | 7 ++- server/src/lua/lua_manager.rs | 41 ++++++-------- server/src/scripting/mod.rs | 3 +- server/src/scripting/scriptable_client.rs | 19 +++++++ .../scripting/scriptable_client_manager.rs | 26 +++++++-- 8 files changed, 123 insertions(+), 58 deletions(-) create mode 100644 server/src/client_management/messages.rs create mode 100644 server/src/scripting/scriptable_client.rs diff --git a/server/Cargo.toml b/server/Cargo.toml index c45357a..3464914 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -32,7 +32,7 @@ futures = "0.3.16" async-trait = "0.1.52" actix = "0.13" rhai = {version = "1.7.0"} -mlua = { version = "0.8.0", features=["lua54", "async", "serde", "macros", "vendored"] } +mlua = { version = "0.8.1", features=["lua54", "async", "serde", "macros", "vendored"] } libloading = "0.7" toml = "0.4.2" aquamarine = "0.1.11" diff --git a/server/src/client_management/client_manager.rs b/server/src/client_management/client_manager.rs index 6d7cef5..f34cfe0 100644 --- a/server/src/client_management/client_manager.rs +++ b/server/src/client_management/client_manager.rs @@ -40,19 +40,8 @@ use crate::{ network::NetworkOutput, prelude::messages::ObservableMessage, }; - -#[derive(Message)] -#[rtype(result = "()")] -pub(crate) enum ClientManagerMessage { - AddClient(Uuid, Addr), - RemoveClient(Uuid), -} - -#[derive(Message)] -#[rtype(result = "()")] -pub enum ClientManagerOutput { - UpdateRequest(Addr), -} +use crate::client_management::messages::{ClientManagerDataMessage, ClientManagerDataResponse, ClientManagerMessage, ClientManagerOutput}; +use crate::client_management::messages::ClientManagerDataResponse::{ClientCount, Clients}; pub struct ClientManager { clients: HashMap>, @@ -60,6 +49,16 @@ pub struct ClientManager { } impl ClientManager { + pub(crate) fn new( + delegate: WeakRecipient, + ) -> Addr { + ClientManager { + delegate, + clients: HashMap::new(), + } + .start() + } + pub(crate) fn send_update( &mut self, ctx: &mut Context, @@ -145,18 +144,6 @@ impl ClientManager { ctx.spawn(fut); } } -} - -impl ClientManager { - pub(crate) fn new( - delegate: WeakRecipient, - ) -> Addr { - ClientManager { - delegate, - clients: HashMap::new(), - } - .start() - } fn add_client( &mut self, @@ -231,3 +218,20 @@ impl Handler for ClientManager { } } } + +impl Handler for ClientManager { + type Result = ClientManagerDataResponse; + + fn handle(&mut self, msg: ClientManagerDataMessage, ctx: &mut Self::Context) -> Self::Result { + match msg { + ClientManagerDataMessage::ClientCount => { + ClientCount(self.clients.values().count()) + } + ClientManagerDataMessage::Clients => Clients( + self.clients.values() + .map(|a| a.downgrade()) + .collect() + ) + } + } +} diff --git a/server/src/client_management/messages.rs b/server/src/client_management/messages.rs new file mode 100644 index 0000000..54f3cbe --- /dev/null +++ b/server/src/client_management/messages.rs @@ -0,0 +1,29 @@ +use actix::{Message, MessageResponse, Addr, WeakAddr}; +use uuid::Uuid; +use crate::client_management::{Client, ClientManager}; + +#[derive(Message)] +#[rtype(result = "()")] +pub(crate) enum ClientManagerMessage { + AddClient(Uuid, Addr), + RemoveClient(Uuid), +} + +#[derive(Message)] +#[rtype(result = "()")] +pub(crate) enum ClientManagerOutput { + UpdateRequest(Addr), +} + +#[derive(Message)] +#[rtype(result = "ClientManagerDataResponse")] +pub enum ClientManagerDataMessage { + ClientCount, + Clients +} + +#[derive(MessageResponse)] +pub enum ClientManagerDataResponse { + ClientCount(usize), + Clients(Vec>) +} \ No newline at end of file diff --git a/server/src/client_management/mod.rs b/server/src/client_management/mod.rs index 774448a..c97c7ef 100644 --- a/server/src/client_management/mod.rs +++ b/server/src/client_management/mod.rs @@ -1,9 +1,12 @@ mod client; mod client_manager; +mod messages; pub(crate) use client::Client; -pub(crate) use client_manager::{ - ClientManager, +pub(crate) use client_manager::ClientManager; +pub(crate) use messages::{ ClientManagerMessage, ClientManagerOutput, + ClientManagerDataMessage, + ClientManagerDataResponse, }; diff --git a/server/src/lua/lua_manager.rs b/server/src/lua/lua_manager.rs index d699728..94c0d69 100644 --- a/server/src/lua/lua_manager.rs +++ b/server/src/lua/lua_manager.rs @@ -1,3 +1,7 @@ +//! # lua_manager.rs +//! +//! Holds the LuaManger struct and implements it's methods + use actix::{Actor, Addr, ArbiterHandle, AsyncContext, Context, Running}; use actix::fut::wrap_future; use mlua::{Lua, Thread, ThreadStatus}; @@ -8,8 +12,10 @@ use crate::network::NetworkManager; use crate::scripting::scriptable_server::ScriptableServer; use crate::Server; +/// # LuaManager +/// Holds common server objects +/// todo: change to weak references pub struct LuaManager { - pub(super) engine: Lua, pub(super) server: Addr, pub(super) network_manager: Addr, pub(super) client_manager: Addr, @@ -22,9 +28,9 @@ impl LuaManager { client_manager: Addr ) -> Builder { Builder::new( - server.clone(), - network_manager.clone(), - client_manager.clone() + server, + network_manager, + client_manager ) } @@ -34,7 +40,6 @@ impl LuaManager { let api = engine.create_table().unwrap(); api.set::<&str, ScriptableServer>("server", server).unwrap(); - api.set::<&str, i32>("a", 12).unwrap(); engine.globals().set("chat", api).unwrap(); engine @@ -51,7 +56,6 @@ impl Actor for LuaManager { let coroutine: Thread = engine.load(r#" coroutine.create(function () print("hello lua") - print(chat.server.Test) print(chat.server:name()) end) "#).eval().unwrap(); @@ -65,25 +69,10 @@ impl Actor for LuaManager { // we enforce the actor model on the consumer of the api. impl From for Addr { fn from(b: Builder) -> Addr { - let mgr = LuaManager { - engine: b.engine, - server: b.server.clone(), - network_manager: b.network_manager.clone(), - client_manager: b.client_manager.clone() - }; - - let server = ScriptableServer::from(b.server); - - let api = mgr.engine.create_table().unwrap(); - api.set::<&str, ScriptableServer>("server", server).unwrap(); - api.set::<&str, i32>("a", 12).unwrap(); - - let a = api.get::<&str, i32>("a").unwrap(); - - println!("Lua stored: {}", a); - - mgr.engine.globals().set("chat", api).unwrap(); - - mgr.start() + LuaManager { + server: b.server, + network_manager: b.network_manager, + client_manager: b.client_manager + }.start() } } diff --git a/server/src/scripting/mod.rs b/server/src/scripting/mod.rs index 9664e44..7b5304f 100644 --- a/server/src/scripting/mod.rs +++ b/server/src/scripting/mod.rs @@ -1,3 +1,4 @@ pub(crate) mod scriptable_server; pub(crate) mod scriptable_network_manager; -pub(crate) mod scriptable_client_manager; \ No newline at end of file +pub(crate) mod scriptable_client_manager; +pub(crate) mod scriptable_client; \ No newline at end of file diff --git a/server/src/scripting/scriptable_client.rs b/server/src/scripting/scriptable_client.rs new file mode 100644 index 0000000..29dc013 --- /dev/null +++ b/server/src/scripting/scriptable_client.rs @@ -0,0 +1,19 @@ +use actix::Addr; +use mlua::UserData; +use crate::client_management::Client; + +pub(crate) struct ScriptableClient { + addr: Addr +} + +impl UserData for ScriptableClient { + +} + +impl From> for ScriptableClient { + fn from(addr: Addr) -> Self { + Self { + addr + } + } +} \ No newline at end of file diff --git a/server/src/scripting/scriptable_client_manager.rs b/server/src/scripting/scriptable_client_manager.rs index 2b81538..bb6a0cc 100644 --- a/server/src/scripting/scriptable_client_manager.rs +++ b/server/src/scripting/scriptable_client_manager.rs @@ -1,13 +1,33 @@ -use actix::Addr; -use mlua::UserData; -use crate::client_management::ClientManager; +use actix::{ActorStreamExt, Addr}; +use mlua::{Error, UserData, UserDataFields, UserDataMethods}; +use crate::client_management::{ClientManager, ClientManagerDataMessage}; +use crate::client_management::ClientManagerDataResponse::Clients; +use crate::scripting::scriptable_client::ScriptableClient; +#[derive(Clone)] pub(crate) struct ScriptableClientManager { addr: Addr } impl UserData for ScriptableClientManager { + fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_async_method("clients", |lua, obj, ()| async move { + let res = obj.addr.send(ClientManagerDataMessage::Clients).await; + if let Ok(Clients(clients)) = res { + let clients: Vec = clients.into_iter() + .map(|a| a.upgrade()) + .filter(|o| o.is_some()) + .map(|o| o.unwrap()) + .map(|a| ScriptableClient::from(a)) + .collect(); + + Ok(clients) + } else { + Err(Error::RuntimeError("clients returned null or other value".to_string())) + } + }) + } } impl From> for ScriptableClientManager { From 83316268b9192b8ed2c51b7b737ae0184476d391 Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Mon, 4 Jul 2022 08:29:17 +0100 Subject: [PATCH 3/3] added more scriptable objects --- foundation/src/lib.rs | 2 +- .../client_management/{ => client}/client.rs | 106 ++++++------------ .../src/client_management/client/messages.rs | 39 +++++++ server/src/client_management/client/mod.rs | 5 + .../src/client_management/client_manager.rs | 62 ++++++---- server/src/client_management/messages.rs | 5 +- server/src/client_management/mod.rs | 4 +- server/src/network/mod.rs | 4 +- .../src/network/network_manager/messages.rs | 13 ++- server/src/network/network_manager/mod.rs | 2 +- .../network_manager/network_manager.rs | 12 +- server/src/prelude/mod.rs | 7 +- server/src/scripting/scriptable_client.rs | 35 +++++- .../scripting/scriptable_network_manager.rs | 17 ++- server/src/server/server.rs | 3 +- 15 files changed, 201 insertions(+), 115 deletions(-) rename server/src/client_management/{ => client}/client.rs (70%) create mode 100644 server/src/client_management/client/messages.rs create mode 100644 server/src/client_management/client/mod.rs diff --git a/foundation/src/lib.rs b/foundation/src/lib.rs index 60010ae..228b30b 100644 --- a/foundation/src/lib.rs +++ b/foundation/src/lib.rs @@ -17,7 +17,7 @@ use uuid::Uuid; * address: the ip address of the connected user. * public_key: the public key used when sending messages to the user. */ -#[derive(Deserialize, Serialize, Debug, Clone)] +#[derive(Deserialize, Serialize, Debug, Clone, Default)] pub struct ClientDetails { pub uuid: Uuid, pub username: String, diff --git a/server/src/client_management/client.rs b/server/src/client_management/client/client.rs similarity index 70% rename from server/src/client_management/client.rs rename to server/src/client_management/client/client.rs index 0326f43..bef8e77 100644 --- a/server/src/client_management/client.rs +++ b/server/src/client_management/client/client.rs @@ -1,73 +1,18 @@ +use actix::{Actor, Addr, AsyncContext, Context, Handler, Recipient}; +use foundation::ClientDetails; +use foundation::messages::client::ClientStreamIn; use std::net::SocketAddr; - -use actix::{ - Actor, - Addr, - ArbiterHandle, - AsyncContext, - Context, - Handler, - Message, - MessageResponse, - Recipient, - Running, - WeakAddr, -}; -use foundation::{ - messages::client::{ClientStreamIn, ClientStreamOut}, - ClientDetails, -}; -use serde_json::{from_str, to_string}; use uuid::Uuid; - -use crate::{ - client_management::client::ClientObservableMessage::{ - SendGlobalMessageRequest, - SendMessageRequest, - UpdateRequest, - }, - network::{ - Connection, - ConnectionMessage, - ConnectionMessage::SendData, - ConnectionOuput, - }, - prelude::{ - messages::ObservableMessage, - messages::ObservableMessage::{Subscribe, Unsubscribe}, - }, -}; - -/// Message sent ot the clients delegate -#[derive(Message)] -#[rtype(result = "()")] -pub enum ClientMessage { - SendUpdate(Vec), - SendMessage { from: Uuid, content: String }, - SendGlobalMessage { from: Uuid, content: String }, -} - -#[derive(Message)] -#[rtype(result = "ClientDetailsResponse")] -pub struct ClientDataMessage; - -#[derive(MessageResponse)] -pub struct ClientDetailsResponse(pub ClientDetails); +use crate::client_management::client::messages::{ClientDataMessage, ClientDataResponse, ClientMessage, ClientObservableMessage}; +use crate::client_management::client::messages::ClientObservableMessage::{SendGlobalMessageRequest, SendMessageRequest, UpdateRequest}; +use crate::network::{Connection, ConnectionOuput}; +use crate::prelude::messages::ObservableMessage; /// messages the client will send to itself enum SelfMessage { ReceivedMessage(ClientStreamIn), } -/// message that is sent to all observers of the current client. -#[derive(Message, Clone)] -#[rtype(result = "()")] -pub enum ClientObservableMessage { - SendMessageRequest(WeakAddr, Uuid, String), - SendGlobalMessageRequest(WeakAddr, String), - UpdateRequest(WeakAddr), -} - /// # Client /// This represents a connected client. /// it will handle received message from a connection. @@ -97,12 +42,13 @@ impl Client { addr: SocketAddr, data: String, ) { - use ClientStreamIn::{ + use foundation::messages::client::ClientStreamIn::{ Disconnect, SendGlobalMessage, SendMessage, Update, }; + use serde_json::from_str; let msg = from_str::(data.as_str()) .expect("[Client] failed to decode incoming message"); match msg { @@ -161,8 +107,12 @@ impl Actor for Client { // tells the client that it has been connected. fn started(&mut self, ctx: &mut Self::Context) { - use ClientStreamOut::Connected; - use ConnectionMessage::SendData; + use foundation::messages::client::ClientStreamOut::Connected; + use serde_json::to_string; + use foundation::messages::client::ClientStreamOut; + use crate::network::ConnectionMessage::SendData; + use crate::network::ConnectionOuput; + use crate::prelude::messages::ObservableMessage::Subscribe; println!("[Client] started"); self.connection .do_send::>(Subscribe(ctx.address().recipient())); @@ -172,8 +122,12 @@ impl Actor for Client { } fn stopped(&mut self, ctx: &mut Self::Context) { - use ClientStreamOut::Disconnected; - use ConnectionMessage::SendData; + use foundation::messages::client::ClientStreamOut::Disconnected; + use serde_json::to_string; + use foundation::messages::client::ClientStreamOut; + use crate::network::ConnectionMessage::SendData; + use crate::network::ConnectionOuput; + use crate::prelude::messages::ObservableMessage::Unsubscribe; self.connection .do_send::>(Unsubscribe(ctx.address().recipient())); self.connection.do_send(SendData( @@ -183,13 +137,16 @@ impl Actor for Client { } impl Handler for Client { - type Result = ClientDetailsResponse; + type Result = ClientDataResponse; fn handle( &mut self, msg: ClientDataMessage, ctx: &mut Self::Context, ) -> Self::Result { - ClientDetailsResponse(self.details.clone()) + match msg { + ClientDataMessage::Details => ClientDataResponse::Details(self.details.clone()), + _ => todo!() + } } } @@ -201,8 +158,11 @@ impl Handler for Client { msg: ClientMessage, _ctx: &mut Self::Context, ) -> Self::Result { - use ClientMessage::{SendGlobalMessage, SendMessage, SendUpdate}; - use ClientStreamOut::{ConnectedClients, GlobalMessage, UserMessage}; + use crate::client_management::client::messages::ClientMessage::{SendGlobalMessage, SendMessage, SendUpdate}; + use foundation::messages::client::ClientStreamOut::{ConnectedClients, GlobalMessage, UserMessage}; + use serde_json::to_string; + use foundation::messages::client::ClientStreamOut; + use crate::network::ConnectionMessage::SendData; match msg { SendUpdate(clients) => self.connection.do_send(SendData( @@ -236,7 +196,7 @@ impl Handler for Client { msg: ConnectionOuput, ctx: &mut Self::Context, ) -> Self::Result { - use ConnectionOuput::RecvData; + use crate::network::ConnectionOuput::RecvData; match msg { RecvData(sender, addr, data) => { self.handle_request(ctx, sender, addr, data) @@ -255,7 +215,7 @@ impl Handler> for Client { msg: ObservableMessage, ctx: &mut Self::Context, ) -> Self::Result { - use ObservableMessage::{Subscribe, Unsubscribe}; + use crate::prelude::messages::ObservableMessage::{Subscribe, Unsubscribe}; match msg { Subscribe(r) => { println!("[Client] adding subscriber"); diff --git a/server/src/client_management/client/messages.rs b/server/src/client_management/client/messages.rs new file mode 100644 index 0000000..daa8ebf --- /dev/null +++ b/server/src/client_management/client/messages.rs @@ -0,0 +1,39 @@ +use actix::{WeakAddr, Message, MessageResponse}; +use uuid::Uuid; +use foundation::ClientDetails; +use crate::client_management::client::client::Client; + +/// Message sent ot the clients delegate +#[derive(Message)] +#[rtype(result = "()")] +pub enum ClientMessage { + SendUpdate(Vec), + SendMessage { from: Uuid, content: String }, + SendGlobalMessage { from: Uuid, content: String }, +} + +#[derive(Message)] +#[rtype(result = "ClientDataResponse")] +pub enum ClientDataMessage { + Details, + Uuid, + Username, + Address, +} + +#[derive(MessageResponse)] +pub enum ClientDataResponse { + Details(ClientDetails), + Uuid(Uuid), + Username(String), + Address(String), +} + +/// message that is sent to all observers of the current client. +#[derive(Message, Clone)] +#[rtype(result = "()")] +pub enum ClientObservableMessage { + SendMessageRequest(WeakAddr, Uuid, String), + SendGlobalMessageRequest(WeakAddr, String), + UpdateRequest(WeakAddr), +} diff --git a/server/src/client_management/client/mod.rs b/server/src/client_management/client/mod.rs new file mode 100644 index 0000000..3d109b9 --- /dev/null +++ b/server/src/client_management/client/mod.rs @@ -0,0 +1,5 @@ +mod messages; +mod client; + +pub use messages::*; +pub use client::{Client}; diff --git a/server/src/client_management/client_manager.rs b/server/src/client_management/client_manager.rs index f34cfe0..a83e3df 100644 --- a/server/src/client_management/client_manager.rs +++ b/server/src/client_management/client_manager.rs @@ -1,7 +1,6 @@ use std::collections::HashMap; use actix::{ - fut::{wrap_future, wrap_stream}, Actor, ActorFutureExt, ActorStreamExt, @@ -9,6 +8,7 @@ use actix::{ ArbiterHandle, AsyncContext, Context, + fut::{wrap_future, wrap_stream}, Handler, MailboxError, Message, @@ -20,26 +20,21 @@ use actix::{ WeakRecipient, }; use foundation::{ - messages::client::{ClientStreamIn, ClientStreamIn::SendGlobalMessage}, ClientDetails, + messages::client::{ClientStreamIn, ClientStreamIn::SendGlobalMessage}, }; use futures::{SinkExt, TryStreamExt}; use tokio_stream::StreamExt; use uuid::Uuid; use crate::{ - client_management::{ - client::{ - ClientDataMessage, - ClientMessage, - ClientMessage::SendMessage, - ClientObservableMessage, - }, - Client, - }, network::NetworkOutput, prelude::messages::ObservableMessage, }; +use crate::client_management::client::{Client, ClientDataResponse}; +use crate::client_management::client::{ClientDataMessage, ClientMessage, ClientObservableMessage}; +use crate::client_management::client::ClientDataResponse::Details; +use crate::client_management::client::ClientMessage::SendMessage; use crate::client_management::messages::{ClientManagerDataMessage, ClientManagerDataResponse, ClientManagerMessage, ClientManagerOutput}; use crate::client_management::messages::ClientManagerDataResponse::{ClientCount, Clients}; @@ -65,16 +60,15 @@ impl ClientManager { addr: WeakAddr, ) { println!("[ClientManager] sending update to client"); - use ClientMessage::SendUpdate; + use crate::client_management::client::ClientMessage::SendUpdate; let self_addr = ctx.address(); if let Some(to_send) = addr.upgrade() { let client_addr: Vec> = self.clients.iter().map(|(_, v)| v).cloned().collect(); let collection = tokio_stream::iter(client_addr) - .then(|addr| addr.send(ClientDataMessage)) - .map(|val| val.unwrap().0) - // .filter(|val| ) + .then(|addr| addr.send(ClientDataMessage::Details)) + .map(|val| if let Details(details) = val.unwrap() { details } else { ClientDetails::default() }) .collect(); let fut = wrap_future(async move { @@ -98,18 +92,30 @@ impl ClientManager { self.clients.iter().map(|(_, v)| v).cloned().collect(); let collection = tokio_stream::iter(client_addr) - .then(|addr| addr.send(ClientDataMessage)) - .map(|val| val.unwrap().0) + .then(|addr| addr.send(ClientDataMessage::Details)) + .map(|val| val.unwrap()) + .map(|val: ClientDataResponse| if let Details(details) = val { + details + } else { + ClientDetails::default() + }) .collect(); let fut = wrap_future(async move { if let Some(sender) = sender.upgrade() { - let from: Uuid = - sender.send(ClientDataMessage).await.unwrap().0.uuid; + let details: ClientDataResponse = + sender.send(ClientDataMessage::Details).await.unwrap(); + + let from = if let Details(details) = details { + details.uuid + } else { + ClientDetails::default().uuid + }; + let client_details: Vec = collection.await; let pos = client_details.iter().position(|i| i.uuid == from); if let Some(pos) = pos { - sender.send(SendMessage { content, from }).await; + sender.send(SendMessage { content, from }).await.expect("TODO: panic message"); } } }); @@ -123,14 +129,22 @@ impl ClientManager { sender: WeakAddr, content: String, ) { - use ClientMessage::SendGlobalMessage; + use crate::client_management::client::ClientMessage::SendGlobalMessage; let client_addr: Vec> = self.clients.iter().map(|(_, v)| v).cloned().collect(); if let Some(sender) = sender.upgrade() { let fut = wrap_future(async move { - let from: Uuid = - sender.send(ClientDataMessage).await.unwrap().0.uuid; + + let details: ClientDataResponse = + sender.send(ClientDataMessage::Details).await.unwrap(); + + let from = if let Details(details) = details { + details.uuid + } else { + ClientDetails::default().uuid + }; + let collection = tokio_stream::iter(client_addr) .then(move |addr| { addr.send(SendGlobalMessage { @@ -201,7 +215,7 @@ impl Handler for ClientManager { msg: ClientObservableMessage, ctx: &mut Self::Context, ) -> Self::Result { - use ClientObservableMessage::{ + use crate::client_management::client::ClientObservableMessage::{ SendGlobalMessageRequest, SendMessageRequest, UpdateRequest, diff --git a/server/src/client_management/messages.rs b/server/src/client_management/messages.rs index 54f3cbe..2005d89 100644 --- a/server/src/client_management/messages.rs +++ b/server/src/client_management/messages.rs @@ -1,6 +1,7 @@ -use actix::{Message, MessageResponse, Addr, WeakAddr}; +use actix::{Addr, Message, MessageResponse, WeakAddr}; use uuid::Uuid; -use crate::client_management::{Client, ClientManager}; +use crate::client_management::ClientManager; +use crate::client_management::client::Client; #[derive(Message)] #[rtype(result = "()")] diff --git a/server/src/client_management/mod.rs b/server/src/client_management/mod.rs index c97c7ef..c6a559b 100644 --- a/server/src/client_management/mod.rs +++ b/server/src/client_management/mod.rs @@ -1,8 +1,8 @@ -mod client; +pub mod client; mod client_manager; mod messages; -pub(crate) use client::Client; + pub(crate) use client_manager::ClientManager; pub(crate) use messages::{ ClientManagerMessage, diff --git a/server/src/network/mod.rs b/server/src/network/mod.rs index 48692ad..e78cd6f 100644 --- a/server/src/network/mod.rs +++ b/server/src/network/mod.rs @@ -38,5 +38,7 @@ use listener::{ListenerMessage, ListenerOutput, NetworkListener}; pub(crate) use network_manager::{ NetworkManager, NetworkOutput, - NetworkMessage + NetworkMessage, + NetworkDataMessage, + NetworkDataOutput }; diff --git a/server/src/network/network_manager/messages.rs b/server/src/network/network_manager/messages.rs index ada3d24..5f0ba4e 100644 --- a/server/src/network/network_manager/messages.rs +++ b/server/src/network/network_manager/messages.rs @@ -1,7 +1,7 @@ use actix::Addr; use foundation::ClientDetails; use crate::network::Connection; -use actix::Message; +use actix::{Message, MessageResponse}; #[derive(Message, Debug, Ord, PartialOrd, Eq, PartialEq)] #[rtype(result = "()")] @@ -15,4 +15,15 @@ pub enum NetworkMessage { pub enum NetworkOutput { NewClient(Addr, ClientDetails), InfoRequested(Addr), +} + +#[derive(Message, Debug, Ord, PartialOrd, Eq, PartialEq)] +#[rtype(result = "()")] +pub enum NetworkDataMessage { + IsListening +} + +#[derive(MessageResponse)] +pub enum NetworkDataOutput { + IsListening(bool), } \ No newline at end of file diff --git a/server/src/network/network_manager/mod.rs b/server/src/network/network_manager/mod.rs index c0f2318..8d3b4f0 100644 --- a/server/src/network/network_manager/mod.rs +++ b/server/src/network/network_manager/mod.rs @@ -10,4 +10,4 @@ mod config; use config::*; pub(crate) use network_manager::{NetworkManager}; pub(crate) use builder::*; -pub(crate) use messages::{NetworkMessage,NetworkOutput}; +pub(crate) use messages::{NetworkMessage, NetworkOutput, NetworkDataMessage, NetworkDataOutput}; diff --git a/server/src/network/network_manager/network_manager.rs b/server/src/network/network_manager/network_manager.rs index afde877..721171e 100644 --- a/server/src/network/network_manager/network_manager.rs +++ b/server/src/network/network_manager/network_manager.rs @@ -1,6 +1,6 @@ use actix::{Actor, Addr, AsyncContext, Context, Handler, WeakRecipient}; use foundation::ClientDetails; -use crate::network::{Connection, ConnectionInitiator, InitiatorOutput}; +use crate::network::{Connection, ConnectionInitiator, InitiatorOutput, NetworkDataMessage, NetworkDataOutput}; use crate::network::listener::{ListenerMessage, ListenerOutput}; use crate::network::listener::NetworkListener; use crate::network::network_manager::Builder; @@ -135,6 +135,16 @@ impl Handler for NetworkManager { } } +impl Handler for NetworkManager { + type Result = (); + + fn handle(&mut self, msg: NetworkDataMessage, ctx: &mut Self::Context) -> Self::Result { + match msg { + NetworkDataMessage::IsListening => NetworkDataOutput::IsListening(if self.) + } + } +} + impl Handler for NetworkManager { type Result = (); fn handle( diff --git a/server/src/prelude/mod.rs b/server/src/prelude/mod.rs index d9012ca..f79bf0e 100644 --- a/server/src/prelude/mod.rs +++ b/server/src/prelude/mod.rs @@ -7,12 +7,13 @@ pub mod actors { //! exports all actors used in the program. pub use crate::server::Server; pub(crate) use crate::network::{Connection, ConnectionInitiator, NetworkManager}; - pub(crate) use crate::client_management::{Client,ClientManager}; + pub(crate) use crate::client_management::ClientManager; + pub(crate) use crate::client_management::client::Client; } pub mod messages { //! exports all messages used in the program. pub(crate) use super::observer::ObservableMessage; - pub(crate) use crate::network::{NetworkMessage,NetworkOutput,ConnectionMessage,ConnectionOuput}; - pub(crate) use crate::client_management::{ClientManagerOutput,ClientManagerMessage}; + pub(crate) use crate::network::{ConnectionMessage, ConnectionOuput, NetworkMessage, NetworkOutput}; + pub(crate) use crate::client_management::{ClientManagerMessage, ClientManagerOutput}; } \ No newline at end of file diff --git a/server/src/scripting/scriptable_client.rs b/server/src/scripting/scriptable_client.rs index 29dc013..a295a85 100644 --- a/server/src/scripting/scriptable_client.rs +++ b/server/src/scripting/scriptable_client.rs @@ -1,13 +1,44 @@ use actix::Addr; -use mlua::UserData; -use crate::client_management::Client; +use mlua::{Error, UserData, UserDataFields, UserDataMethods}; +use crate::client_management::client::Client; +use crate::client_management::client::{ClientDataMessage, ClientDataResponse}; +use crate::client_management::client::ClientDataResponse::{Username, Uuid}; +use crate::server::ServerDataResponse::Name; +#[derive(Clone)] pub(crate) struct ScriptableClient { addr: Addr } impl UserData for ScriptableClient { + fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_async_method("username", |_lua, obj, ()| async move { + let name: Option = obj.addr.send(ClientDataMessage::Username).await.ok(); + if let Some(Username(name)) = name { + Ok(name) + } else { + Err(Error::RuntimeError("Name returned null or other value".to_string())) + } + }); + methods.add_async_method("uuid", |_lua, obj, ()| async move { + let uuid: Option = obj.addr.send(ClientDataMessage::Uuid).await.ok(); + if let Some(Uuid(uuid)) = uuid { + Ok(uuid.to_string()) + } else { + Err(Error::RuntimeError("Uuid returned null or other value".to_string())) + } + }); + + methods.add_async_method("address", |_lua, obj, ()| async move { + let address: Option = obj.addr.send(ClientDataMessage::Address).await.ok(); + if let Some(Username(address)) = address { + Ok(address) + } else { + Err(Error::RuntimeError("address returned null or other value".to_string())) + } + }); + } } impl From> for ScriptableClient { diff --git a/server/src/scripting/scriptable_network_manager.rs b/server/src/scripting/scriptable_network_manager.rs index c774daf..708d434 100644 --- a/server/src/scripting/scriptable_network_manager.rs +++ b/server/src/scripting/scriptable_network_manager.rs @@ -1,13 +1,24 @@ use actix::Addr; -use mlua::UserData; -use crate::network::NetworkManager; +use mlua::{Error, UserData, UserDataMethods}; +use crate::network::{NetworkDataMessage, NetworkManager}; +use crate::network::NetworkDataOutput::IsListening; +#[derive(Clone)] pub(crate) struct ScriptableNetworkManager { addr: Addr } impl UserData for ScriptableNetworkManager { - + fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_async_method("Listening", |_lua, obj, ()| async move { + let is_listening = obj.addr.send(NetworkDataMessage::IsListening).await.ok(); + if let Some(IsListening(is_listening)) = is_listening { + Ok(is_listening) + } else { + Err(Error::RuntimeError("Uuid returned null or other value".to_string())) + } + }); + } } impl From> for ScriptableNetworkManager { diff --git a/server/src/server/server.rs b/server/src/server/server.rs index 361ebfc..885b551 100644 --- a/server/src/server/server.rs +++ b/server/src/server/server.rs @@ -7,7 +7,8 @@ use actix::fut::wrap_future; use mlua::Lua; use foundation::ClientDetails; use foundation::messages::network::NetworkSockOut::GotInfo; -use crate::client_management::{Client, ClientManager, ClientManagerOutput}; +use crate::client_management::{ClientManager, ClientManagerOutput}; +use crate::client_management::client::Client; use crate::client_management::ClientManagerMessage::AddClient; use crate::lua::LuaManager; use crate::rhai::RhaiManager;