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 {
|
GetScene {
|
||||||
id: usize,
|
id: usize,
|
||||||
},
|
},
|
||||||
|
/// TODO: Perhaps remove it, as the client should auto get it on login and on scene list updates
|
||||||
GetSceneList,
|
GetSceneList,
|
||||||
GetTokens {
|
GetTokens {
|
||||||
scene: usize,
|
scene: usize,
|
||||||
|
|
72
src/lib.rs
72
src/lib.rs
|
@ -78,7 +78,7 @@ impl GameServer {
|
||||||
pub async fn server_loop(
|
pub async fn server_loop(
|
||||||
mut self,
|
mut self,
|
||||||
mut msgs: mpsc::Receiver<(String, api::Request)>,
|
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 {
|
while let Some(req) = msgs.recv().await {
|
||||||
let (id, req) = req;
|
let (id, req) = req;
|
||||||
|
@ -98,18 +98,18 @@ impl GameServer {
|
||||||
self.users.insert(login.username.clone(), admin);
|
self.users.insert(login.username.clone(), admin);
|
||||||
// Send login confirmation
|
// Send login confirmation
|
||||||
_ = broadcast.send((
|
_ = broadcast.send((
|
||||||
Some(id.clone()),
|
SendTo::User(id.clone()),
|
||||||
api::Response::Login(api::login::LoginResult {
|
api::Response::Login(api::login::LoginResult {
|
||||||
success: true,
|
success: true,
|
||||||
username: login.username.clone(),
|
username: login.username.clone(),
|
||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
// Send the list of scenes and chat history and such
|
// Send the list of scenes and chat history and such
|
||||||
_ = broadcast.send((Some(login.username.clone()), self.get_scene_list(admin)));
|
_ = broadcast.send((SendTo::User(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_last_messages(50)));
|
||||||
} else {
|
} else {
|
||||||
_ = broadcast.send((
|
_ = broadcast.send((
|
||||||
Some(id.clone()),
|
SendTo::User(id.clone()),
|
||||||
api::Response::Login(api::login::LoginResult {
|
api::Response::Login(api::login::LoginResult {
|
||||||
success: false,
|
success: false,
|
||||||
username: login.username,
|
username: login.username,
|
||||||
|
@ -131,15 +131,18 @@ impl GameServer {
|
||||||
|
|
||||||
self.chat.push((id.clone(), msg.clone()));
|
self.chat.push((id.clone(), msg.clone()));
|
||||||
if msg.whisper.is_some() {
|
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 } => {
|
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 } => {
|
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 } => {
|
api::Request::GetTokens { scene } => {
|
||||||
for token_id in self.game.available_tokens(scene, self.is_admin(&id)) {
|
for token_id in self.game.available_tokens(scene, self.is_admin(&id)) {
|
||||||
|
@ -147,7 +150,7 @@ impl GameServer {
|
||||||
(ti.visible_to_players)
|
(ti.visible_to_players)
|
||||||
{
|
{
|
||||||
_ = broadcast.send((
|
_ = broadcast.send((
|
||||||
Some(id.clone()),
|
SendTo::User(id.clone()),
|
||||||
api::Response::SpawnToken(SpawnToken {
|
api::Response::SpawnToken(SpawnToken {
|
||||||
token_id: token_id,
|
token_id: token_id,
|
||||||
x: ti.x,
|
x: ti.x,
|
||||||
|
@ -160,14 +163,14 @@ impl GameServer {
|
||||||
}
|
}
|
||||||
api::Request::GetScene { id: scene_id } => {
|
api::Request::GetScene { id: scene_id } => {
|
||||||
if let Some(response) = self.get_scene(&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 } => {
|
api::Request::CreateScene { title } => {
|
||||||
if self.is_admin(&id) {
|
if self.is_admin(&id) {
|
||||||
self.game.create_scene(title);
|
self.game.create_scene(title);
|
||||||
let scenes = self.get_scene_list(true);
|
let scenes = self.get_scene_list(true);
|
||||||
_ = broadcast.send((Some(id), scenes));
|
_ = broadcast.send((SendTo::User(id), scenes));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
api::Request::SetSceneGrid {
|
api::Request::SetSceneGrid {
|
||||||
|
@ -180,7 +183,11 @@ impl GameServer {
|
||||||
if let Some(map) = s.map.as_mut() {
|
if let Some(map) = s.map.as_mut() {
|
||||||
map.grid_cell_size = grid_cell_size;
|
map.grid_cell_size = grid_cell_size;
|
||||||
map.grid_offset = grid_offset;
|
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) {
|
if let Some(scene) = self.get_scene(&id, scene) {
|
||||||
_ = broadcast.send((return_id, scene));
|
_ = broadcast.send((return_id, scene));
|
||||||
}
|
}
|
||||||
|
@ -191,12 +198,12 @@ impl GameServer {
|
||||||
api::Request::SceneSetVisible { scene, visible } => {
|
api::Request::SceneSetVisible { scene, visible } => {
|
||||||
if self.is_admin(&id) {
|
if self.is_admin(&id) {
|
||||||
self.game.scene_visible(scene, visible);
|
self.game.scene_visible(scene, visible);
|
||||||
_ = broadcast.send((None, self.get_scene_list(false)));
|
_ = broadcast.send((SendTo::AllBut(id.clone()), self.get_scene_list(false)));
|
||||||
_ = broadcast.send((Some(id), self.get_scene_list(true)));
|
_ = broadcast.send((SendTo::User(id), self.get_scene_list(true)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
api::Request::GetSceneList => {
|
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 {
|
api::Request::SpawnToken {
|
||||||
map_id,
|
map_id,
|
||||||
|
@ -213,9 +220,9 @@ impl GameServer {
|
||||||
.create_token(map_id, character, img_path.clone(), x, y, visible_to_players);
|
.create_token(map_id, character, img_path.clone(), x, y, visible_to_players);
|
||||||
_ = broadcast.send((
|
_ = broadcast.send((
|
||||||
if visible_to_players && scene_visible {
|
if visible_to_players && scene_visible {
|
||||||
None
|
SendTo::All
|
||||||
} else {
|
} else {
|
||||||
Some(id)
|
SendTo::User(id)
|
||||||
},
|
},
|
||||||
api::Response::SpawnToken(SpawnToken {
|
api::Response::SpawnToken(SpawnToken {
|
||||||
token_id,
|
token_id,
|
||||||
|
@ -231,7 +238,7 @@ impl GameServer {
|
||||||
if self.game.move_token(0, token_id, x, y) {
|
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: 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
|
// 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) => {
|
api::Request::ActionResult(result) => {
|
||||||
|
@ -249,27 +256,27 @@ impl GameServer {
|
||||||
.targets(Some(result.targets))
|
.targets(Some(result.targets))
|
||||||
.id(self.chat.len() + 1);
|
.id(self.chat.len() + 1);
|
||||||
self.chat.push((id, msg.clone()));
|
self.chat.push((id, msg.clone()));
|
||||||
_ = broadcast.send((None, api::Response::Message(msg)));
|
_ = broadcast.send((SendTo::All, api::Response::Message(msg)));
|
||||||
}
|
}
|
||||||
api::Request::CreateCharacter => {
|
api::Request::CreateCharacter => {
|
||||||
// check if user is admin
|
// check if user is admin
|
||||||
if self.is_admin(&id) {
|
if self.is_admin(&id) {
|
||||||
let new_id = self.game.create_character();
|
let new_id = self.game.create_character();
|
||||||
// return the new id with the character i think
|
// 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 => {
|
api::Request::Quit => {
|
||||||
if self.users.contains_key(&id) {
|
if self.users.contains_key(&id) {
|
||||||
self.users.remove(&id);
|
self.users.remove(&id);
|
||||||
}
|
}
|
||||||
_ = broadcast.send((None, api::Response::Quit { id }));
|
_ = broadcast.send((SendTo::All, api::Response::Quit { id }));
|
||||||
}
|
}
|
||||||
api::Request::Kick(id) => {
|
api::Request::Kick(id) => {
|
||||||
if self.users.contains_key(&id) {
|
if self.users.contains_key(&id) {
|
||||||
self.users.remove(&id);
|
self.users.remove(&id);
|
||||||
}
|
}
|
||||||
_ = broadcast.send((Some(id), api::Response::Shutdown));
|
_ = broadcast.send((SendTo::User(id), api::Response::Shutdown));
|
||||||
}
|
}
|
||||||
api::Request::Shutdown => {
|
api::Request::Shutdown => {
|
||||||
if self.is_admin(&id) {
|
if self.is_admin(&id) {
|
||||||
|
@ -292,7 +299,7 @@ impl GameServer {
|
||||||
self.save().await;
|
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 :)
|
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)
|
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,
|
SinkExt, StreamExt,
|
||||||
stream::{SplitSink, SplitStream},
|
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::sync::{broadcast, mpsc};
|
||||||
use tokio_util::io::ReaderStream;
|
use tokio_util::io::ReaderStream;
|
||||||
|
|
||||||
|
@ -55,7 +58,7 @@ async fn run_web_server(listener: tokio::net::TcpListener, app: Router) {
|
||||||
async fn ws_handler(
|
async fn ws_handler(
|
||||||
ws: ws::WebSocketUpgrade,
|
ws: ws::WebSocketUpgrade,
|
||||||
msend: mpsc::Sender<(String, Request)>,
|
msend: mpsc::Sender<(String, Request)>,
|
||||||
brecv: broadcast::Receiver<(Option<String>, Response)>,
|
brecv: broadcast::Receiver<(SendTo, Response)>,
|
||||||
) -> impl axum::response::IntoResponse {
|
) -> impl axum::response::IntoResponse {
|
||||||
ws.on_upgrade(|w| handle_socket(w, msend, brecv))
|
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(
|
async fn socket_sender(
|
||||||
id: String,
|
id: String,
|
||||||
mut send: SplitSink<ws::WebSocket, ws::Message>,
|
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 {
|
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);
|
println!("Sending a message to {}: {:?}", &id, &msg);
|
||||||
let err = send
|
let err = send
|
||||||
.send(ws::Message::Text(serde_json::to_string(&msg).unwrap().into()))
|
.send(ws::Message::Text(serde_json::to_string(&msg).unwrap().into()))
|
||||||
|
@ -110,7 +113,7 @@ async fn socket_sender(
|
||||||
async fn handle_socket(
|
async fn handle_socket(
|
||||||
mut socket: ws::WebSocket,
|
mut socket: ws::WebSocket,
|
||||||
msend: mpsc::Sender<(String, Request)>,
|
msend: mpsc::Sender<(String, Request)>,
|
||||||
mut brecv: broadcast::Receiver<(Option<String>, Response)>,
|
mut brecv: broadcast::Receiver<(SendTo, Response)>,
|
||||||
) {
|
) {
|
||||||
let mut id: Option<String> = None;
|
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)
|
// 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);
|
println!("{} trying to log in: {:?}", &temp_id, &b);
|
||||||
if let Ok((to_id, msg)) = b {
|
if let Ok((to_id, msg)) = b {
|
||||||
if let Response::Login(open_tavern::api::login::LoginResult { success, username }) = &msg {
|
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) {
|
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;
|
_ = socket.send(Message::Text(serde_json::to_string(&msg).unwrap_or_default().into())).await;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue