added more scriptable objects

This commit is contained in:
michael-bailey 2022-07-04 08:29:17 +01:00
parent 51cea3523e
commit 83316268b9
15 changed files with 201 additions and 115 deletions

View File

@ -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,

View File

@ -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<ClientDetails>),
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<Client>, Uuid, String),
SendGlobalMessageRequest(WeakAddr<Client>, String),
UpdateRequest(WeakAddr<Client>),
}
/// # 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::<ClientStreamIn>(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::<ObservableMessage<ConnectionOuput>>(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::<ObservableMessage<ConnectionOuput>>(Unsubscribe(ctx.address().recipient()));
self.connection.do_send(SendData(
@ -183,13 +137,16 @@ impl Actor for Client {
}
impl Handler<ClientDataMessage> 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<ClientMessage> 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<ConnectionOuput> 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<ObservableMessage<ClientObservableMessage>> for Client {
msg: ObservableMessage<ClientObservableMessage>,
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");

View File

@ -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<ClientDetails>),
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<Client>, Uuid, String),
SendGlobalMessageRequest(WeakAddr<Client>, String),
UpdateRequest(WeakAddr<Client>),
}

View File

@ -0,0 +1,5 @@
mod messages;
mod client;
pub use messages::*;
pub use client::{Client};

View File

@ -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<Client>,
) {
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<Addr<Client>> =
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<ClientDetails> = 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<Client>,
content: String,
) {
use ClientMessage::SendGlobalMessage;
use crate::client_management::client::ClientMessage::SendGlobalMessage;
let client_addr: Vec<Addr<Client>> =
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<ClientObservableMessage> for ClientManager {
msg: ClientObservableMessage,
ctx: &mut Self::Context,
) -> Self::Result {
use ClientObservableMessage::{
use crate::client_management::client::ClientObservableMessage::{
SendGlobalMessageRequest,
SendMessageRequest,
UpdateRequest,

View File

@ -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 = "()")]

View File

@ -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,

View File

@ -38,5 +38,7 @@ use listener::{ListenerMessage, ListenerOutput, NetworkListener};
pub(crate) use network_manager::{
NetworkManager,
NetworkOutput,
NetworkMessage
NetworkMessage,
NetworkDataMessage,
NetworkDataOutput
};

View File

@ -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<Connection>, ClientDetails),
InfoRequested(Addr<Connection>),
}
#[derive(Message, Debug, Ord, PartialOrd, Eq, PartialEq)]
#[rtype(result = "()")]
pub enum NetworkDataMessage {
IsListening
}
#[derive(MessageResponse)]
pub enum NetworkDataOutput {
IsListening(bool),
}

View File

@ -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};

View File

@ -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<NetworkMessage> for NetworkManager {
}
}
impl Handler<NetworkDataMessage> 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<ListenerOutput> for NetworkManager {
type Result = ();
fn handle(

View File

@ -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};
}

View File

@ -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<Client>
}
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<ClientDataResponse> = 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<ClientDataResponse> = 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<ClientDataResponse> = 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<Addr<Client>> for ScriptableClient {

View File

@ -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<NetworkManager>
}
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<Addr<NetworkManager>> for ScriptableNetworkManager {

View File

@ -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;