use a SendTo enum instead of using Option to know who to send the broadcast message
This commit is contained in:
parent
23e23ad1a2
commit
0d99649e56
3 changed files with 58 additions and 30 deletions
|
@ -63,6 +63,7 @@ pub enum Request {
|
|||
GetScene {
|
||||
id: usize,
|
||||
},
|
||||
/// TODO: Perhaps remove it, as the client should auto get it on login and on scene list updates
|
||||
GetSceneList,
|
||||
GetTokens {
|
||||
scene: usize,
|
||||
|
|
72
src/lib.rs
72
src/lib.rs
|
@ -78,7 +78,7 @@ impl GameServer {
|
|||
pub async fn server_loop(
|
||||
mut self,
|
||||
mut msgs: mpsc::Receiver<(String, api::Request)>,
|
||||
broadcast: broadcast::Sender<(Option<String>, api::Response)>,
|
||||
broadcast: broadcast::Sender<(SendTo, api::Response)>,
|
||||
) {
|
||||
while let Some(req) = msgs.recv().await {
|
||||
let (id, req) = req;
|
||||
|
@ -98,18 +98,18 @@ impl GameServer {
|
|||
self.users.insert(login.username.clone(), admin);
|
||||
// Send login confirmation
|
||||
_ = broadcast.send((
|
||||
Some(id.clone()),
|
||||
SendTo::User(id.clone()),
|
||||
api::Response::Login(api::login::LoginResult {
|
||||
success: true,
|
||||
username: login.username.clone(),
|
||||
}),
|
||||
));
|
||||
// Send the list of scenes and chat history and such
|
||||
_ = broadcast.send((Some(login.username.clone()), self.get_scene_list(admin)));
|
||||
_ = broadcast.send((Some(login.username.clone()), self.get_last_messages(50)));
|
||||
_ = broadcast.send((SendTo::User(login.username.clone()), self.get_scene_list(admin)));
|
||||
_ = broadcast.send((SendTo::User(login.username.clone()), self.get_last_messages(50)));
|
||||
} else {
|
||||
_ = broadcast.send((
|
||||
Some(id.clone()),
|
||||
SendTo::User(id.clone()),
|
||||
api::Response::Login(api::login::LoginResult {
|
||||
success: false,
|
||||
username: login.username,
|
||||
|
@ -131,15 +131,18 @@ impl GameServer {
|
|||
|
||||
self.chat.push((id.clone(), msg.clone()));
|
||||
if msg.whisper.is_some() {
|
||||
_ = broadcast.send((Some(id.clone()), api::Response::Message(msg.clone())));
|
||||
_ = broadcast.send((SendTo::User(id.clone()), api::Response::Message(msg.clone())));
|
||||
}
|
||||
_ = broadcast.send((msg.whisper.clone(), api::Response::Message(msg)));
|
||||
_ = broadcast.send((
|
||||
msg.whisper.clone().map(|id| SendTo::User(id)).unwrap_or_default(),
|
||||
api::Response::Message(msg),
|
||||
));
|
||||
}
|
||||
api::Request::GetChatHistory { amount, from } => {
|
||||
_ = broadcast.send((Some(id), self.get_chat_history(amount, from)));
|
||||
_ = broadcast.send((SendTo::User(id), self.get_chat_history(amount, from)));
|
||||
}
|
||||
api::Request::GetLastMessages { amount } => {
|
||||
_ = broadcast.send((Some(id), self.get_last_messages(amount)));
|
||||
_ = broadcast.send((SendTo::User(id), self.get_last_messages(amount)));
|
||||
}
|
||||
api::Request::GetTokens { scene } => {
|
||||
for token_id in self.game.available_tokens(scene, self.is_admin(&id)) {
|
||||
|
@ -147,7 +150,7 @@ impl GameServer {
|
|||
(ti.visible_to_players)
|
||||
{
|
||||
_ = broadcast.send((
|
||||
Some(id.clone()),
|
||||
SendTo::User(id.clone()),
|
||||
api::Response::SpawnToken(SpawnToken {
|
||||
token_id: token_id,
|
||||
x: ti.x,
|
||||
|
@ -160,14 +163,14 @@ impl GameServer {
|
|||
}
|
||||
api::Request::GetScene { id: scene_id } => {
|
||||
if let Some(response) = self.get_scene(&id, scene_id) {
|
||||
_ = broadcast.send((Some(id), response));
|
||||
_ = broadcast.send((SendTo::User(id), response));
|
||||
}
|
||||
}
|
||||
api::Request::CreateScene { title } => {
|
||||
if self.is_admin(&id) {
|
||||
self.game.create_scene(title);
|
||||
let scenes = self.get_scene_list(true);
|
||||
_ = broadcast.send((Some(id), scenes));
|
||||
_ = broadcast.send((SendTo::User(id), scenes));
|
||||
}
|
||||
}
|
||||
api::Request::SetSceneGrid {
|
||||
|
@ -180,7 +183,11 @@ impl GameServer {
|
|||
if let Some(map) = s.map.as_mut() {
|
||||
map.grid_cell_size = grid_cell_size;
|
||||
map.grid_offset = grid_offset;
|
||||
let return_id = if s.visible_to_users { None } else { Some(id.clone()) };
|
||||
let return_id = if s.visible_to_users {
|
||||
SendTo::All
|
||||
} else {
|
||||
SendTo::User(id.clone())
|
||||
};
|
||||
if let Some(scene) = self.get_scene(&id, scene) {
|
||||
_ = broadcast.send((return_id, scene));
|
||||
}
|
||||
|
@ -191,12 +198,12 @@ impl GameServer {
|
|||
api::Request::SceneSetVisible { scene, visible } => {
|
||||
if self.is_admin(&id) {
|
||||
self.game.scene_visible(scene, visible);
|
||||
_ = broadcast.send((None, self.get_scene_list(false)));
|
||||
_ = broadcast.send((Some(id), self.get_scene_list(true)));
|
||||
_ = broadcast.send((SendTo::AllBut(id.clone()), self.get_scene_list(false)));
|
||||
_ = broadcast.send((SendTo::User(id), self.get_scene_list(true)));
|
||||
}
|
||||
}
|
||||
api::Request::GetSceneList => {
|
||||
_ = broadcast.send((Some(id.clone()), self.get_scene_list(self.is_admin(&id))));
|
||||
_ = broadcast.send((SendTo::User(id.clone()), self.get_scene_list(self.is_admin(&id))));
|
||||
}
|
||||
api::Request::SpawnToken {
|
||||
map_id,
|
||||
|
@ -213,9 +220,9 @@ impl GameServer {
|
|||
.create_token(map_id, character, img_path.clone(), x, y, visible_to_players);
|
||||
_ = broadcast.send((
|
||||
if visible_to_players && scene_visible {
|
||||
None
|
||||
SendTo::All
|
||||
} else {
|
||||
Some(id)
|
||||
SendTo::User(id)
|
||||
},
|
||||
api::Response::SpawnToken(SpawnToken {
|
||||
token_id,
|
||||
|
@ -231,7 +238,7 @@ impl GameServer {
|
|||
if self.game.move_token(0, token_id, x, y) {
|
||||
// TODO: maybe chage move_token to return optional x,y values if succeeded to make sure the token is where it was going to be
|
||||
// TODO: Check if the token is visible to players and if not, only update it's position to admins or something
|
||||
_ = broadcast.send((None, api::Response::MoveToken { token_id, x, y }));
|
||||
_ = broadcast.send((SendTo::All, api::Response::MoveToken { token_id, x, y }));
|
||||
}
|
||||
}
|
||||
api::Request::ActionResult(result) => {
|
||||
|
@ -249,27 +256,27 @@ impl GameServer {
|
|||
.targets(Some(result.targets))
|
||||
.id(self.chat.len() + 1);
|
||||
self.chat.push((id, msg.clone()));
|
||||
_ = broadcast.send((None, api::Response::Message(msg)));
|
||||
_ = broadcast.send((SendTo::All, api::Response::Message(msg)));
|
||||
}
|
||||
api::Request::CreateCharacter => {
|
||||
// check if user is admin
|
||||
if self.is_admin(&id) {
|
||||
let new_id = self.game.create_character();
|
||||
// return the new id with the character i think
|
||||
_ = broadcast.send((Some(id), api::Response::CharacterCreated(new_id)));
|
||||
_ = broadcast.send((SendTo::User(id), api::Response::CharacterCreated(new_id)));
|
||||
}
|
||||
}
|
||||
api::Request::Quit => {
|
||||
if self.users.contains_key(&id) {
|
||||
self.users.remove(&id);
|
||||
}
|
||||
_ = broadcast.send((None, api::Response::Quit { id }));
|
||||
_ = broadcast.send((SendTo::All, api::Response::Quit { id }));
|
||||
}
|
||||
api::Request::Kick(id) => {
|
||||
if self.users.contains_key(&id) {
|
||||
self.users.remove(&id);
|
||||
}
|
||||
_ = broadcast.send((Some(id), api::Response::Shutdown));
|
||||
_ = broadcast.send((SendTo::User(id), api::Response::Shutdown));
|
||||
}
|
||||
api::Request::Shutdown => {
|
||||
if self.is_admin(&id) {
|
||||
|
@ -292,7 +299,7 @@ impl GameServer {
|
|||
self.save().await;
|
||||
}
|
||||
}
|
||||
_ = broadcast.send((None, api::Response::Shutdown));
|
||||
_ = broadcast.send((SendTo::All, api::Response::Shutdown));
|
||||
self.save().await; // Save the game one last time :)
|
||||
}
|
||||
|
||||
|
@ -369,3 +376,20 @@ impl GameServer {
|
|||
self.users.get(id).map(|a| *a).unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub enum SendTo {
|
||||
#[default]
|
||||
All,
|
||||
User(String),
|
||||
AllBut(String),
|
||||
}
|
||||
impl SendTo {
|
||||
pub fn should_send(&self, to: &str) -> bool {
|
||||
match self {
|
||||
SendTo::All => true,
|
||||
SendTo::User(user) => user == to,
|
||||
SendTo::AllBut(user) => user != to,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
15
src/main.rs
15
src/main.rs
|
@ -9,7 +9,10 @@ use futures_util::{
|
|||
SinkExt, StreamExt,
|
||||
stream::{SplitSink, SplitStream},
|
||||
};
|
||||
use open_tavern::api::{Request, RequestError, Response};
|
||||
use open_tavern::{
|
||||
SendTo,
|
||||
api::{Request, RequestError, Response},
|
||||
};
|
||||
use tokio::sync::{broadcast, mpsc};
|
||||
use tokio_util::io::ReaderStream;
|
||||
|
||||
|
@ -55,7 +58,7 @@ async fn run_web_server(listener: tokio::net::TcpListener, app: Router) {
|
|||
async fn ws_handler(
|
||||
ws: ws::WebSocketUpgrade,
|
||||
msend: mpsc::Sender<(String, Request)>,
|
||||
brecv: broadcast::Receiver<(Option<String>, Response)>,
|
||||
brecv: broadcast::Receiver<(SendTo, Response)>,
|
||||
) -> impl axum::response::IntoResponse {
|
||||
ws.on_upgrade(|w| handle_socket(w, msend, brecv))
|
||||
}
|
||||
|
@ -89,10 +92,10 @@ async fn socket_receiver(mut recv: SplitStream<ws::WebSocket>, msend: mpsc::Send
|
|||
async fn socket_sender(
|
||||
id: String,
|
||||
mut send: SplitSink<ws::WebSocket, ws::Message>,
|
||||
mut brecv: broadcast::Receiver<(Option<String>, Response)>,
|
||||
mut brecv: broadcast::Receiver<(SendTo, Response)>,
|
||||
) {
|
||||
while let Ok((to_id, msg)) = brecv.recv().await {
|
||||
if to_id.is_none() || to_id.map(|t| t == id).unwrap_or(false) {
|
||||
if to_id.should_send(&id) {
|
||||
println!("Sending a message to {}: {:?}", &id, &msg);
|
||||
let err = send
|
||||
.send(ws::Message::Text(serde_json::to_string(&msg).unwrap().into()))
|
||||
|
@ -110,7 +113,7 @@ async fn socket_sender(
|
|||
async fn handle_socket(
|
||||
mut socket: ws::WebSocket,
|
||||
msend: mpsc::Sender<(String, Request)>,
|
||||
mut brecv: broadcast::Receiver<(Option<String>, Response)>,
|
||||
mut brecv: broadcast::Receiver<(SendTo, Response)>,
|
||||
) {
|
||||
let mut id: Option<String> = None;
|
||||
// this is a temp id, and as long as 2 people dont try to connect to the socket at the same milisecond and to the same user it would be fine (i hope)
|
||||
|
@ -128,7 +131,7 @@ async fn handle_socket(
|
|||
println!("{} trying to log in: {:?}", &temp_id, &b);
|
||||
if let Ok((to_id, msg)) = b {
|
||||
if let Response::Login(open_tavern::api::login::LoginResult { success, username }) = &msg {
|
||||
let to_id = to_id.map(|ti| ti == temp_id).unwrap_or(false);
|
||||
let to_id = to_id.should_send(&temp_id);
|
||||
if to_id && *success && id.as_ref().map(|id| id == username).unwrap_or(false) {
|
||||
_ = socket.send(Message::Text(serde_json::to_string(&msg).unwrap_or_default().into())).await;
|
||||
break;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue