Merge branch 'feature/lua-support' into develop
This commit is contained in:
commit
fe960a2018
|
|
@ -17,7 +17,7 @@ use uuid::Uuid;
|
||||||
* address: the ip address of the connected user.
|
* address: the ip address of the connected user.
|
||||||
* public_key: the public key used when sending messages to the 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 struct ClientDetails {
|
||||||
pub uuid: Uuid,
|
pub uuid: Uuid,
|
||||||
pub username: String,
|
pub username: String,
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,8 @@ tokio = { version = "1.9.0", features = ["full"] }
|
||||||
futures = "0.3.16"
|
futures = "0.3.16"
|
||||||
async-trait = "0.1.52"
|
async-trait = "0.1.52"
|
||||||
actix = "0.13"
|
actix = "0.13"
|
||||||
mlua = { version = "0.7.3", features=["lua54", "async", "serde", "macros"] }
|
rhai = {version = "1.7.0"}
|
||||||
|
mlua = { version = "0.8.1", features=["lua54", "async", "serde", "macros", "vendored"] }
|
||||||
libloading = "0.7"
|
libloading = "0.7"
|
||||||
toml = "0.4.2"
|
toml = "0.4.2"
|
||||||
aquamarine = "0.1.11"
|
aquamarine = "0.1.11"
|
||||||
|
|
|
||||||
|
|
@ -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 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 uuid::Uuid;
|
||||||
|
use crate::client_management::client::messages::{ClientDataMessage, ClientDataResponse, ClientMessage, ClientObservableMessage};
|
||||||
use crate::{
|
use crate::client_management::client::messages::ClientObservableMessage::{SendGlobalMessageRequest, SendMessageRequest, UpdateRequest};
|
||||||
client_management::client::ClientObservableMessage::{
|
use crate::network::{Connection, ConnectionOuput};
|
||||||
SendGlobalMessageRequest,
|
use crate::prelude::messages::ObservableMessage;
|
||||||
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);
|
|
||||||
|
|
||||||
/// messages the client will send to itself
|
/// messages the client will send to itself
|
||||||
enum SelfMessage {
|
enum SelfMessage {
|
||||||
ReceivedMessage(ClientStreamIn),
|
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
|
/// # Client
|
||||||
/// This represents a connected client.
|
/// This represents a connected client.
|
||||||
/// it will handle received message from a connection.
|
/// it will handle received message from a connection.
|
||||||
|
|
@ -97,12 +42,13 @@ impl Client {
|
||||||
addr: SocketAddr,
|
addr: SocketAddr,
|
||||||
data: String,
|
data: String,
|
||||||
) {
|
) {
|
||||||
use ClientStreamIn::{
|
use foundation::messages::client::ClientStreamIn::{
|
||||||
Disconnect,
|
Disconnect,
|
||||||
SendGlobalMessage,
|
SendGlobalMessage,
|
||||||
SendMessage,
|
SendMessage,
|
||||||
Update,
|
Update,
|
||||||
};
|
};
|
||||||
|
use serde_json::from_str;
|
||||||
let msg = from_str::<ClientStreamIn>(data.as_str())
|
let msg = from_str::<ClientStreamIn>(data.as_str())
|
||||||
.expect("[Client] failed to decode incoming message");
|
.expect("[Client] failed to decode incoming message");
|
||||||
match msg {
|
match msg {
|
||||||
|
|
@ -161,8 +107,12 @@ impl Actor for Client {
|
||||||
|
|
||||||
// tells the client that it has been connected.
|
// tells the client that it has been connected.
|
||||||
fn started(&mut self, ctx: &mut Self::Context) {
|
fn started(&mut self, ctx: &mut Self::Context) {
|
||||||
use ClientStreamOut::Connected;
|
use foundation::messages::client::ClientStreamOut::Connected;
|
||||||
use ConnectionMessage::SendData;
|
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");
|
println!("[Client] started");
|
||||||
self.connection
|
self.connection
|
||||||
.do_send::<ObservableMessage<ConnectionOuput>>(Subscribe(ctx.address().recipient()));
|
.do_send::<ObservableMessage<ConnectionOuput>>(Subscribe(ctx.address().recipient()));
|
||||||
|
|
@ -172,8 +122,12 @@ impl Actor for Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stopped(&mut self, ctx: &mut Self::Context) {
|
fn stopped(&mut self, ctx: &mut Self::Context) {
|
||||||
use ClientStreamOut::Disconnected;
|
use foundation::messages::client::ClientStreamOut::Disconnected;
|
||||||
use ConnectionMessage::SendData;
|
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
|
self.connection
|
||||||
.do_send::<ObservableMessage<ConnectionOuput>>(Unsubscribe(ctx.address().recipient()));
|
.do_send::<ObservableMessage<ConnectionOuput>>(Unsubscribe(ctx.address().recipient()));
|
||||||
self.connection.do_send(SendData(
|
self.connection.do_send(SendData(
|
||||||
|
|
@ -183,13 +137,16 @@ impl Actor for Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Handler<ClientDataMessage> for Client {
|
impl Handler<ClientDataMessage> for Client {
|
||||||
type Result = ClientDetailsResponse;
|
type Result = ClientDataResponse;
|
||||||
fn handle(
|
fn handle(
|
||||||
&mut self,
|
&mut self,
|
||||||
msg: ClientDataMessage,
|
msg: ClientDataMessage,
|
||||||
ctx: &mut Self::Context,
|
ctx: &mut Self::Context,
|
||||||
) -> Self::Result {
|
) -> 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,
|
msg: ClientMessage,
|
||||||
_ctx: &mut Self::Context,
|
_ctx: &mut Self::Context,
|
||||||
) -> Self::Result {
|
) -> Self::Result {
|
||||||
use ClientMessage::{SendGlobalMessage, SendMessage, SendUpdate};
|
use crate::client_management::client::messages::ClientMessage::{SendGlobalMessage, SendMessage, SendUpdate};
|
||||||
use ClientStreamOut::{ConnectedClients, GlobalMessage, UserMessage};
|
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 {
|
match msg {
|
||||||
SendUpdate(clients) => self.connection.do_send(SendData(
|
SendUpdate(clients) => self.connection.do_send(SendData(
|
||||||
|
|
@ -236,7 +196,7 @@ impl Handler<ConnectionOuput> for Client {
|
||||||
msg: ConnectionOuput,
|
msg: ConnectionOuput,
|
||||||
ctx: &mut Self::Context,
|
ctx: &mut Self::Context,
|
||||||
) -> Self::Result {
|
) -> Self::Result {
|
||||||
use ConnectionOuput::RecvData;
|
use crate::network::ConnectionOuput::RecvData;
|
||||||
match msg {
|
match msg {
|
||||||
RecvData(sender, addr, data) => {
|
RecvData(sender, addr, data) => {
|
||||||
self.handle_request(ctx, sender, addr, data)
|
self.handle_request(ctx, sender, addr, data)
|
||||||
|
|
@ -255,7 +215,7 @@ impl Handler<ObservableMessage<ClientObservableMessage>> for Client {
|
||||||
msg: ObservableMessage<ClientObservableMessage>,
|
msg: ObservableMessage<ClientObservableMessage>,
|
||||||
ctx: &mut Self::Context,
|
ctx: &mut Self::Context,
|
||||||
) -> Self::Result {
|
) -> Self::Result {
|
||||||
use ObservableMessage::{Subscribe, Unsubscribe};
|
use crate::prelude::messages::ObservableMessage::{Subscribe, Unsubscribe};
|
||||||
match msg {
|
match msg {
|
||||||
Subscribe(r) => {
|
Subscribe(r) => {
|
||||||
println!("[Client] adding subscriber");
|
println!("[Client] adding subscriber");
|
||||||
|
|
@ -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>),
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
mod messages;
|
||||||
|
mod client;
|
||||||
|
|
||||||
|
pub use messages::*;
|
||||||
|
pub use client::{Client};
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use actix::{
|
use actix::{
|
||||||
fut::{wrap_future, wrap_stream},
|
|
||||||
Actor,
|
Actor,
|
||||||
ActorFutureExt,
|
ActorFutureExt,
|
||||||
ActorStreamExt,
|
ActorStreamExt,
|
||||||
|
|
@ -9,6 +8,7 @@ use actix::{
|
||||||
ArbiterHandle,
|
ArbiterHandle,
|
||||||
AsyncContext,
|
AsyncContext,
|
||||||
Context,
|
Context,
|
||||||
|
fut::{wrap_future, wrap_stream},
|
||||||
Handler,
|
Handler,
|
||||||
MailboxError,
|
MailboxError,
|
||||||
Message,
|
Message,
|
||||||
|
|
@ -20,39 +20,23 @@ use actix::{
|
||||||
WeakRecipient,
|
WeakRecipient,
|
||||||
};
|
};
|
||||||
use foundation::{
|
use foundation::{
|
||||||
messages::client::{ClientStreamIn, ClientStreamIn::SendGlobalMessage},
|
|
||||||
ClientDetails,
|
ClientDetails,
|
||||||
|
messages::client::{ClientStreamIn, ClientStreamIn::SendGlobalMessage},
|
||||||
};
|
};
|
||||||
use futures::{SinkExt, TryStreamExt};
|
use futures::{SinkExt, TryStreamExt};
|
||||||
use tokio_stream::StreamExt;
|
use tokio_stream::StreamExt;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
client_management::{
|
|
||||||
client::{
|
|
||||||
ClientDataMessage,
|
|
||||||
ClientMessage,
|
|
||||||
ClientMessage::SendMessage,
|
|
||||||
ClientObservableMessage,
|
|
||||||
},
|
|
||||||
Client,
|
|
||||||
},
|
|
||||||
network::NetworkOutput,
|
network::NetworkOutput,
|
||||||
prelude::messages::ObservableMessage,
|
prelude::messages::ObservableMessage,
|
||||||
};
|
};
|
||||||
|
use crate::client_management::client::{Client, ClientDataResponse};
|
||||||
#[derive(Message)]
|
use crate::client_management::client::{ClientDataMessage, ClientMessage, ClientObservableMessage};
|
||||||
#[rtype(result = "()")]
|
use crate::client_management::client::ClientDataResponse::Details;
|
||||||
pub(crate) enum ClientManagerMessage {
|
use crate::client_management::client::ClientMessage::SendMessage;
|
||||||
AddClient(Uuid, Addr<Client>),
|
use crate::client_management::messages::{ClientManagerDataMessage, ClientManagerDataResponse, ClientManagerMessage, ClientManagerOutput};
|
||||||
RemoveClient(Uuid),
|
use crate::client_management::messages::ClientManagerDataResponse::{ClientCount, Clients};
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Message)]
|
|
||||||
#[rtype(result = "()")]
|
|
||||||
pub enum ClientManagerOutput {
|
|
||||||
UpdateRequest(Addr<ClientManager>),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ClientManager {
|
pub struct ClientManager {
|
||||||
clients: HashMap<Uuid, Addr<Client>>,
|
clients: HashMap<Uuid, Addr<Client>>,
|
||||||
|
|
@ -60,22 +44,31 @@ pub struct ClientManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientManager {
|
impl ClientManager {
|
||||||
|
pub(crate) fn new(
|
||||||
|
delegate: WeakRecipient<ClientManagerOutput>,
|
||||||
|
) -> Addr<Self> {
|
||||||
|
ClientManager {
|
||||||
|
delegate,
|
||||||
|
clients: HashMap::new(),
|
||||||
|
}
|
||||||
|
.start()
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn send_update(
|
pub(crate) fn send_update(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &mut Context<Self>,
|
ctx: &mut Context<Self>,
|
||||||
addr: WeakAddr<Client>,
|
addr: WeakAddr<Client>,
|
||||||
) {
|
) {
|
||||||
println!("[ClientManager] sending update to client");
|
println!("[ClientManager] sending update to client");
|
||||||
use ClientMessage::SendUpdate;
|
use crate::client_management::client::ClientMessage::SendUpdate;
|
||||||
let self_addr = ctx.address();
|
let self_addr = ctx.address();
|
||||||
if let Some(to_send) = addr.upgrade() {
|
if let Some(to_send) = addr.upgrade() {
|
||||||
let client_addr: Vec<Addr<Client>> =
|
let client_addr: Vec<Addr<Client>> =
|
||||||
self.clients.iter().map(|(_, v)| v).cloned().collect();
|
self.clients.iter().map(|(_, v)| v).cloned().collect();
|
||||||
|
|
||||||
let collection = tokio_stream::iter(client_addr)
|
let collection = tokio_stream::iter(client_addr)
|
||||||
.then(|addr| addr.send(ClientDataMessage))
|
.then(|addr| addr.send(ClientDataMessage::Details))
|
||||||
.map(|val| val.unwrap().0)
|
.map(|val| if let Details(details) = val.unwrap() { details } else { ClientDetails::default() })
|
||||||
// .filter(|val| )
|
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let fut = wrap_future(async move {
|
let fut = wrap_future(async move {
|
||||||
|
|
@ -99,18 +92,30 @@ impl ClientManager {
|
||||||
self.clients.iter().map(|(_, v)| v).cloned().collect();
|
self.clients.iter().map(|(_, v)| v).cloned().collect();
|
||||||
|
|
||||||
let collection = tokio_stream::iter(client_addr)
|
let collection = tokio_stream::iter(client_addr)
|
||||||
.then(|addr| addr.send(ClientDataMessage))
|
.then(|addr| addr.send(ClientDataMessage::Details))
|
||||||
.map(|val| val.unwrap().0)
|
.map(|val| val.unwrap())
|
||||||
|
.map(|val: ClientDataResponse| if let Details(details) = val {
|
||||||
|
details
|
||||||
|
} else {
|
||||||
|
ClientDetails::default()
|
||||||
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let fut = wrap_future(async move {
|
let fut = wrap_future(async move {
|
||||||
if let Some(sender) = sender.upgrade() {
|
if let Some(sender) = sender.upgrade() {
|
||||||
let from: Uuid =
|
let details: ClientDataResponse =
|
||||||
sender.send(ClientDataMessage).await.unwrap().0.uuid;
|
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 client_details: Vec<ClientDetails> = collection.await;
|
||||||
let pos = client_details.iter().position(|i| i.uuid == from);
|
let pos = client_details.iter().position(|i| i.uuid == from);
|
||||||
if let Some(pos) = pos {
|
if let Some(pos) = pos {
|
||||||
sender.send(SendMessage { content, from }).await;
|
sender.send(SendMessage { content, from }).await.expect("TODO: panic message");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -124,14 +129,22 @@ impl ClientManager {
|
||||||
sender: WeakAddr<Client>,
|
sender: WeakAddr<Client>,
|
||||||
content: String,
|
content: String,
|
||||||
) {
|
) {
|
||||||
use ClientMessage::SendGlobalMessage;
|
use crate::client_management::client::ClientMessage::SendGlobalMessage;
|
||||||
let client_addr: Vec<Addr<Client>> =
|
let client_addr: Vec<Addr<Client>> =
|
||||||
self.clients.iter().map(|(_, v)| v).cloned().collect();
|
self.clients.iter().map(|(_, v)| v).cloned().collect();
|
||||||
|
|
||||||
if let Some(sender) = sender.upgrade() {
|
if let Some(sender) = sender.upgrade() {
|
||||||
let fut = wrap_future(async move {
|
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)
|
let collection = tokio_stream::iter(client_addr)
|
||||||
.then(move |addr| {
|
.then(move |addr| {
|
||||||
addr.send(SendGlobalMessage {
|
addr.send(SendGlobalMessage {
|
||||||
|
|
@ -145,18 +158,6 @@ impl ClientManager {
|
||||||
ctx.spawn(fut);
|
ctx.spawn(fut);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl ClientManager {
|
|
||||||
pub(crate) fn new(
|
|
||||||
delegate: WeakRecipient<ClientManagerOutput>,
|
|
||||||
) -> Addr<Self> {
|
|
||||||
ClientManager {
|
|
||||||
delegate,
|
|
||||||
clients: HashMap::new(),
|
|
||||||
}
|
|
||||||
.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_client(
|
fn add_client(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
@ -214,7 +215,7 @@ impl Handler<ClientObservableMessage> for ClientManager {
|
||||||
msg: ClientObservableMessage,
|
msg: ClientObservableMessage,
|
||||||
ctx: &mut Self::Context,
|
ctx: &mut Self::Context,
|
||||||
) -> Self::Result {
|
) -> Self::Result {
|
||||||
use ClientObservableMessage::{
|
use crate::client_management::client::ClientObservableMessage::{
|
||||||
SendGlobalMessageRequest,
|
SendGlobalMessageRequest,
|
||||||
SendMessageRequest,
|
SendMessageRequest,
|
||||||
UpdateRequest,
|
UpdateRequest,
|
||||||
|
|
@ -231,3 +232,20 @@ impl Handler<ClientObservableMessage> for ClientManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Handler<ClientManagerDataMessage> 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()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
use actix::{Addr, Message, MessageResponse, WeakAddr};
|
||||||
|
use uuid::Uuid;
|
||||||
|
use crate::client_management::ClientManager;
|
||||||
|
use crate::client_management::client::Client;
|
||||||
|
|
||||||
|
#[derive(Message)]
|
||||||
|
#[rtype(result = "()")]
|
||||||
|
pub(crate) enum ClientManagerMessage {
|
||||||
|
AddClient(Uuid, Addr<Client>),
|
||||||
|
RemoveClient(Uuid),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Message)]
|
||||||
|
#[rtype(result = "()")]
|
||||||
|
pub(crate) enum ClientManagerOutput {
|
||||||
|
UpdateRequest(Addr<ClientManager>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Message)]
|
||||||
|
#[rtype(result = "ClientManagerDataResponse")]
|
||||||
|
pub enum ClientManagerDataMessage {
|
||||||
|
ClientCount,
|
||||||
|
Clients
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(MessageResponse)]
|
||||||
|
pub enum ClientManagerDataResponse {
|
||||||
|
ClientCount(usize),
|
||||||
|
Clients(Vec<WeakAddr<Client>>)
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,12 @@
|
||||||
mod client;
|
pub mod client;
|
||||||
mod client_manager;
|
mod client_manager;
|
||||||
|
mod messages;
|
||||||
|
|
||||||
pub(crate) use client::Client;
|
|
||||||
pub(crate) use client_manager::{
|
pub(crate) use client_manager::ClientManager;
|
||||||
ClientManager,
|
pub(crate) use messages::{
|
||||||
ClientManagerMessage,
|
ClientManagerMessage,
|
||||||
ClientManagerOutput,
|
ClientManagerOutput,
|
||||||
|
ClientManagerDataMessage,
|
||||||
|
ClientManagerDataResponse,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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<Server>,
|
||||||
|
pub(super) network_manager: Addr<NetworkManager>,
|
||||||
|
pub(super) client_manager: Addr<ClientManager>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Builder {
|
||||||
|
pub(super) fn new(
|
||||||
|
server: Addr<Server>,
|
||||||
|
network_manager: Addr<NetworkManager>,
|
||||||
|
client_manager: Addr<ClientManager>,
|
||||||
|
) -> Self {
|
||||||
|
Builder {
|
||||||
|
engine: Lua::new(),
|
||||||
|
server,
|
||||||
|
network_manager,
|
||||||
|
client_manager,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn build(self) -> Addr<LuaManager> {
|
||||||
|
Addr::from(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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<Out: 'static>(pub Arc<Client<Out>>)
|
|
||||||
where
|
|
||||||
Out: From<ClientMessage> + Send;
|
|
||||||
|
|
||||||
impl<Out> ClientLua<Out>
|
|
||||||
where
|
|
||||||
Out: From<ClientMessage> + Send
|
|
||||||
{
|
|
||||||
pub fn new(client: Arc<Client<Out>>) -> Self {
|
|
||||||
ClientLua(client)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Out: 'static> LuaUserData for ClientLua<Out>
|
|
||||||
where
|
|
||||||
Out: From<ClientMessage> + 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) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<ClientManager<Out>>, pub Vec<Function<'lua>>)
|
|
||||||
where
|
|
||||||
Out: From<ClientMgrMessage> + Send;
|
|
||||||
|
|
||||||
impl<Out: 'static> ClientManagerLua<'_, Out>
|
|
||||||
where
|
|
||||||
Out: From<ClientMgrMessage> + Send
|
|
||||||
{
|
|
||||||
pub fn new(manager: Arc<ClientManager<Out>>) -> Self {
|
|
||||||
ClientManagerLua(manager, Vec::new())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Out: 'static> LuaUserData for ClientManagerLua<'_, Out>
|
|
||||||
where
|
|
||||||
Out: From<ClientMgrMessage> + 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<ClientLua<ClientMgrMessage>> = 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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
//! # 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};
|
||||||
|
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;
|
||||||
|
|
||||||
|
/// # LuaManager
|
||||||
|
/// Holds common server objects
|
||||||
|
/// todo: change to weak references
|
||||||
|
pub struct LuaManager {
|
||||||
|
pub(super) server: Addr<Server>,
|
||||||
|
pub(super) network_manager: Addr<NetworkManager>,
|
||||||
|
pub(super) client_manager: Addr<ClientManager>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LuaManager {
|
||||||
|
pub fn create(
|
||||||
|
server: Addr<Server>,
|
||||||
|
network_manager: Addr<NetworkManager>,
|
||||||
|
client_manager: Addr<ClientManager>
|
||||||
|
) -> Builder {
|
||||||
|
Builder::new(
|
||||||
|
server,
|
||||||
|
network_manager,
|
||||||
|
client_manager
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
engine.globals().set("chat", api).unwrap();
|
||||||
|
engine
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Actor for LuaManager {
|
||||||
|
type Context = Context<Self>;
|
||||||
|
|
||||||
|
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: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<Builder> for Addr<LuaManager> {
|
||||||
|
fn from(b: Builder) -> Addr<LuaManager> {
|
||||||
|
LuaManager {
|
||||||
|
server: b.server,
|
||||||
|
network_manager: b.network_manager,
|
||||||
|
client_manager: b.client_manager
|
||||||
|
}.start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,4 @@
|
||||||
mod client_lua;
|
mod lua_manager;
|
||||||
mod client_manager_lua;
|
mod builder;
|
||||||
mod server_lua;
|
|
||||||
|
|
||||||
pub use client_lua::ClientLua;
|
pub use lua_manager::LuaManager;
|
||||||
pub use client_manager_lua::ClientManagerLua;
|
|
||||||
pub use server_lua::ServerLua;
|
|
||||||
|
|
@ -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<Server>);
|
|
||||||
|
|
||||||
impl ServerLua {
|
|
||||||
pub fn new(server: Arc<Server>) -> 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) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -7,6 +7,9 @@ pub(crate) mod server;
|
||||||
pub(crate) mod client_management;
|
pub(crate) mod client_management;
|
||||||
pub(crate) mod network;
|
pub(crate) mod network;
|
||||||
pub(crate) mod prelude;
|
pub(crate) mod prelude;
|
||||||
|
pub(crate) mod rhai;
|
||||||
|
pub(crate) mod lua;
|
||||||
|
pub(crate) mod scripting;
|
||||||
|
|
||||||
use std::env::args;
|
use std::env::args;
|
||||||
use server::Server;
|
use server::Server;
|
||||||
|
|
|
||||||
|
|
@ -38,5 +38,7 @@ use listener::{ListenerMessage, ListenerOutput, NetworkListener};
|
||||||
pub(crate) use network_manager::{
|
pub(crate) use network_manager::{
|
||||||
NetworkManager,
|
NetworkManager,
|
||||||
NetworkOutput,
|
NetworkOutput,
|
||||||
NetworkMessage
|
NetworkMessage,
|
||||||
|
NetworkDataMessage,
|
||||||
|
NetworkDataOutput
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use actix::Addr;
|
use actix::Addr;
|
||||||
use foundation::ClientDetails;
|
use foundation::ClientDetails;
|
||||||
use crate::network::Connection;
|
use crate::network::Connection;
|
||||||
use actix::Message;
|
use actix::{Message, MessageResponse};
|
||||||
|
|
||||||
#[derive(Message, Debug, Ord, PartialOrd, Eq, PartialEq)]
|
#[derive(Message, Debug, Ord, PartialOrd, Eq, PartialEq)]
|
||||||
#[rtype(result = "()")]
|
#[rtype(result = "()")]
|
||||||
|
|
@ -15,4 +15,15 @@ pub enum NetworkMessage {
|
||||||
pub enum NetworkOutput {
|
pub enum NetworkOutput {
|
||||||
NewClient(Addr<Connection>, ClientDetails),
|
NewClient(Addr<Connection>, ClientDetails),
|
||||||
InfoRequested(Addr<Connection>),
|
InfoRequested(Addr<Connection>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Message, Debug, Ord, PartialOrd, Eq, PartialEq)]
|
||||||
|
#[rtype(result = "()")]
|
||||||
|
pub enum NetworkDataMessage {
|
||||||
|
IsListening
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(MessageResponse)]
|
||||||
|
pub enum NetworkDataOutput {
|
||||||
|
IsListening(bool),
|
||||||
}
|
}
|
||||||
|
|
@ -10,4 +10,4 @@ mod config;
|
||||||
use config::*;
|
use config::*;
|
||||||
pub(crate) use network_manager::{NetworkManager};
|
pub(crate) use network_manager::{NetworkManager};
|
||||||
pub(crate) use builder::*;
|
pub(crate) use builder::*;
|
||||||
pub(crate) use messages::{NetworkMessage,NetworkOutput};
|
pub(crate) use messages::{NetworkMessage, NetworkOutput, NetworkDataMessage, NetworkDataOutput};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use actix::{Actor, Addr, AsyncContext, Context, Handler, WeakRecipient};
|
use actix::{Actor, Addr, AsyncContext, Context, Handler, WeakRecipient};
|
||||||
use foundation::ClientDetails;
|
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::{ListenerMessage, ListenerOutput};
|
||||||
use crate::network::listener::NetworkListener;
|
use crate::network::listener::NetworkListener;
|
||||||
use crate::network::network_manager::Builder;
|
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 {
|
impl Handler<ListenerOutput> for NetworkManager {
|
||||||
type Result = ();
|
type Result = ();
|
||||||
fn handle(
|
fn handle(
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,13 @@ pub mod actors {
|
||||||
//! exports all actors used in the program.
|
//! exports all actors used in the program.
|
||||||
pub use crate::server::Server;
|
pub use crate::server::Server;
|
||||||
pub(crate) use crate::network::{Connection, ConnectionInitiator, NetworkManager};
|
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 {
|
pub mod messages {
|
||||||
//! exports all messages used in the program.
|
//! exports all messages used in the program.
|
||||||
pub(crate) use super::observer::ObservableMessage;
|
pub(crate) use super::observer::ObservableMessage;
|
||||||
pub(crate) use crate::network::{NetworkMessage,NetworkOutput,ConnectionMessage,ConnectionOuput};
|
pub(crate) use crate::network::{ConnectionMessage, ConnectionOuput, NetworkMessage, NetworkOutput};
|
||||||
pub(crate) use crate::client_management::{ClientManagerOutput,ClientManagerMessage};
|
pub(crate) use crate::client_management::{ClientManagerMessage, ClientManagerOutput};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -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<Server>,
|
||||||
|
network_manager: Addr<NetworkManager>,
|
||||||
|
client_manager: Addr<ClientManager>,
|
||||||
|
scope: Scope<'static>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Builder {
|
||||||
|
pub(super) fn new(
|
||||||
|
server: Addr<Server>,
|
||||||
|
network_manager: Addr<NetworkManager>,
|
||||||
|
client_manager: Addr<ClientManager>,
|
||||||
|
) -> Self {
|
||||||
|
Builder {
|
||||||
|
engine: Engine::new(),
|
||||||
|
server,
|
||||||
|
network_manager,
|
||||||
|
client_manager,
|
||||||
|
scope: Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn scope_object<T: 'static>(mut self, name: &str, obj: T) -> Self
|
||||||
|
where
|
||||||
|
T: Clone {
|
||||||
|
self.engine.register_type::<T>();
|
||||||
|
self.scope.set_value(name, obj);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn scope_fn<F, A>(mut self, name: &str, func: F ) -> Self
|
||||||
|
where
|
||||||
|
F: RegisterNativeFunction<A, ()>
|
||||||
|
{
|
||||||
|
self.engine.register_fn(name, func);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub(crate) fn build(self) -> Addr<RhaiManager> {
|
||||||
|
RhaiManager {
|
||||||
|
engine: self.engine,
|
||||||
|
scope: self.scope,
|
||||||
|
server: self.server,
|
||||||
|
network_manager: self.network_manager,
|
||||||
|
client_manager: self.client_manager
|
||||||
|
}.start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
mod rhai_manager;
|
||||||
|
mod builder;
|
||||||
|
|
||||||
|
pub use rhai_manager::RhaiManager;
|
||||||
|
|
@ -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<Server>,
|
||||||
|
pub(super) network_manager: Addr<NetworkManager>,
|
||||||
|
pub(super) client_manager: Addr<ClientManager>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RhaiManager {
|
||||||
|
pub fn create(
|
||||||
|
server: Addr<Server>,
|
||||||
|
network_manager: Addr<NetworkManager>,
|
||||||
|
client_manager: Addr<ClientManager>
|
||||||
|
) -> Builder {
|
||||||
|
Builder::new(server.clone(), network_manager.clone(), client_manager.clone())
|
||||||
|
.scope_object("server", server)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Actor for RhaiManager {
|
||||||
|
type Context = Context<Self>;
|
||||||
|
|
||||||
|
fn started(&mut self, ctx: &mut Self::Context) {
|
||||||
|
self.engine.run(r#"
|
||||||
|
print("hello rhai")
|
||||||
|
"#).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
pub(crate) mod scriptable_server;
|
||||||
|
pub(crate) mod scriptable_network_manager;
|
||||||
|
pub(crate) mod scriptable_client_manager;
|
||||||
|
pub(crate) mod scriptable_client;
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
use actix::Addr;
|
||||||
|
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 {
|
||||||
|
fn from(addr: Addr<Client>) -> Self {
|
||||||
|
Self {
|
||||||
|
addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
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<ClientManager>
|
||||||
|
}
|
||||||
|
|
||||||
|
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<ScriptableClient> = 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<Addr<ClientManager>> for ScriptableClientManager {
|
||||||
|
fn from(addr: Addr<ClientManager>) -> Self {
|
||||||
|
Self {
|
||||||
|
addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
use actix::Addr;
|
||||||
|
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 {
|
||||||
|
fn from(addr: Addr<NetworkManager>) -> Self {
|
||||||
|
Self {
|
||||||
|
addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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<Server>
|
||||||
|
}
|
||||||
|
|
||||||
|
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<ServerDataResponse> = 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<ServerDataResponse> = 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<ServerDataResponse> = 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<ServerDataResponse> = 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<ServerDataResponse> = 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<Addr<Server>> for ScriptableServer {
|
||||||
|
fn from(addr: Addr<Server>) -> Self {
|
||||||
|
Self {
|
||||||
|
addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,7 +7,7 @@ pub struct ServerBuilder {
|
||||||
pub(super) owner: Option<String>,
|
pub(super) owner: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerBuilder {
|
impl<'rhai> ServerBuilder {
|
||||||
pub(super) fn new() -> Self {
|
pub(super) fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: None,
|
name: None,
|
||||||
|
|
|
||||||
|
|
@ -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<Addr<ClientManager>>),
|
||||||
|
NetworkManager(Option<Addr<NetworkManager>>),
|
||||||
|
}
|
||||||
|
|
@ -6,7 +6,9 @@
|
||||||
mod server;
|
mod server;
|
||||||
mod config;
|
mod config;
|
||||||
mod builder;
|
mod builder;
|
||||||
|
mod messages;
|
||||||
|
|
||||||
use config::ServerConfig;
|
use config::ServerConfig;
|
||||||
pub use server::Server;
|
pub use server::Server;
|
||||||
pub(crate) use builder::ServerBuilder;
|
pub use builder::ServerBuilder;
|
||||||
|
pub use messages::*;
|
||||||
|
|
@ -1,13 +1,21 @@
|
||||||
|
//! 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::{Actor, ActorFutureExt, Addr, AsyncContext, Context, ContextFutureSpawner, Handler};
|
||||||
|
use actix::dev::MessageResponse;
|
||||||
use actix::fut::wrap_future;
|
use actix::fut::wrap_future;
|
||||||
|
use mlua::Lua;
|
||||||
use foundation::ClientDetails;
|
use foundation::ClientDetails;
|
||||||
use foundation::messages::network::NetworkSockOut::GotInfo;
|
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::client_management::ClientManagerMessage::AddClient;
|
||||||
|
use crate::lua::LuaManager;
|
||||||
|
use crate::rhai::RhaiManager;
|
||||||
use crate::network::{Connection, NetworkManager, NetworkMessage, NetworkOutput};
|
use crate::network::{Connection, NetworkManager, NetworkMessage, NetworkOutput};
|
||||||
use crate::network::ConnectionMessage::{CloseConnection, SendData};
|
use crate::network::ConnectionMessage::{CloseConnection, SendData};
|
||||||
use crate::network::NetworkOutput::{InfoRequested, NewClient};
|
use crate::network::NetworkOutput::{InfoRequested, NewClient};
|
||||||
use crate::server::{builder, ServerBuilder};
|
use crate::server::{builder, ServerBuilder, ServerDataMessage, ServerDataResponse};
|
||||||
use crate::server::config::ServerConfig;
|
use crate::server::config::ServerConfig;
|
||||||
|
|
||||||
/// This struct is the main actor of the server.
|
/// This struct is the main actor of the server.
|
||||||
|
|
@ -16,18 +24,11 @@ pub struct Server {
|
||||||
config: ServerConfig,
|
config: ServerConfig,
|
||||||
network_manager: Option<Addr<NetworkManager>>,
|
network_manager: Option<Addr<NetworkManager>>,
|
||||||
client_management: Option<Addr<ClientManager>>,
|
client_management: Option<Addr<ClientManager>>,
|
||||||
|
rhai_manager: Option<Addr<RhaiManager>>,
|
||||||
|
lua_manager: Option<Addr<LuaManager>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Server {
|
impl Server {
|
||||||
pub(crate) fn new() -> Addr<Self> {
|
|
||||||
Server {
|
|
||||||
config: Default::default(),
|
|
||||||
network_manager: None,
|
|
||||||
client_management: None,
|
|
||||||
}
|
|
||||||
.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create() -> builder::ServerBuilder {
|
pub fn create() -> builder::ServerBuilder {
|
||||||
ServerBuilder::new()
|
ServerBuilder::new()
|
||||||
}
|
}
|
||||||
|
|
@ -75,11 +76,20 @@ impl Actor for Server {
|
||||||
let nm = NetworkManager::create(addr.clone().recipient())
|
let nm = NetworkManager::create(addr.clone().recipient())
|
||||||
.port(self.config.port)
|
.port(self.config.port)
|
||||||
.build();
|
.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(),
|
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() {
|
if let Some(net_mgr) = self.network_manager.as_ref() {
|
||||||
net_mgr.do_send(NetworkMessage::StartListening);
|
net_mgr.do_send(NetworkMessage::StartListening);
|
||||||
|
|
@ -87,6 +97,21 @@ impl Actor for Server {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Handler<ServerDataMessage> 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<NetworkOutput> for Server {
|
impl Handler<NetworkOutput> for Server {
|
||||||
type Result = ();
|
type Result = ();
|
||||||
fn handle(
|
fn handle(
|
||||||
|
|
@ -118,7 +143,7 @@ impl Handler<ClientManagerOutput> for Server {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<builder::ServerBuilder> for Server {
|
impl From<ServerBuilder> for Server {
|
||||||
fn from(builder: ServerBuilder) -> Self {
|
fn from(builder: ServerBuilder) -> Self {
|
||||||
Server {
|
Server {
|
||||||
config: ServerConfig {
|
config: ServerConfig {
|
||||||
|
|
@ -127,7 +152,9 @@ impl From<builder::ServerBuilder> for Server {
|
||||||
owner: builder.owner.unwrap_or_else(|| "Default owner".to_string()),
|
owner: builder.owner.unwrap_or_else(|| "Default owner".to_string()),
|
||||||
},
|
},
|
||||||
network_manager: None,
|
network_manager: None,
|
||||||
client_management: None
|
client_management: None,
|
||||||
|
rhai_manager: None,
|
||||||
|
lua_manager: None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue