Finish rewriting socket request handling
This commit is contained in:
@@ -10,9 +10,11 @@ use visions_core::{
|
||||
commands::{GmGame, PlayGame, SpectateGame},
|
||||
substrate::Substrate,
|
||||
types::User,
|
||||
Fatal,
|
||||
Error, Fatal,
|
||||
};
|
||||
use visions_types::{
|
||||
identifier, GameId, GameMessage, GameOverview, GameRequest, SessionId, Tabletop, UserId,
|
||||
};
|
||||
use visions_types::{identifier, GameId, GameMessage, GameRequest, SessionId, Tabletop, UserId};
|
||||
|
||||
use crate::{executor::invoke, AppData};
|
||||
|
||||
@@ -43,8 +45,9 @@ impl Socket {
|
||||
pub enum SocketState {
|
||||
Connected,
|
||||
Authenticated(SessionId, User),
|
||||
InGame(SessionId, User, GameId),
|
||||
Spectator(GameId, Option<(SessionId, UserId)>),
|
||||
Gm(SessionId, User, GameId),
|
||||
Player(SessionId, User, GameId),
|
||||
Spectator(GameId, Option<(SessionId, User)>),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -74,8 +77,9 @@ impl SocketManager {
|
||||
.filter(|s| match s.state {
|
||||
SocketState::Connected => false,
|
||||
SocketState::Authenticated(_, ref user) => user.id == user_id,
|
||||
SocketState::InGame(_, ref user, _) => user.id == user_id,
|
||||
SocketState::Spectator(_, Some((_, ref uid))) => *uid == user_id,
|
||||
SocketState::Gm(_, ref user, _) => user.id == user_id,
|
||||
SocketState::Player(_, ref user, _) => user.id == user_id,
|
||||
SocketState::Spectator(_, Some((_, ref user))) => user.id == user_id,
|
||||
SocketState::Spectator(_, _) => false,
|
||||
})
|
||||
.collect();
|
||||
@@ -87,7 +91,8 @@ impl SocketManager {
|
||||
.filter(|s| match s.state {
|
||||
SocketState::Connected => false,
|
||||
SocketState::Authenticated(_, _) => false,
|
||||
SocketState::InGame(_, _, ref game_id_) => *game_id_ == game_id,
|
||||
SocketState::Gm(_, _, ref game_id_) => *game_id_ == game_id,
|
||||
SocketState::Player(_, _, ref game_id_) => *game_id_ == game_id,
|
||||
SocketState::Spectator(ref game_id_, _) => *game_id_ == game_id,
|
||||
})
|
||||
.collect();
|
||||
@@ -176,95 +181,136 @@ pub async fn handle_request(
|
||||
}
|
||||
};
|
||||
|
||||
let result = if game.gm == user.id {
|
||||
invoke(
|
||||
app,
|
||||
GmGame {
|
||||
game_id: game_id.clone(),
|
||||
},
|
||||
Some(&user),
|
||||
)
|
||||
.await?
|
||||
} else if game.contains_user(&user.id) {
|
||||
invoke(
|
||||
app,
|
||||
PlayGame {
|
||||
game_id: game_id.clone(),
|
||||
},
|
||||
Some(&user),
|
||||
)
|
||||
.await?
|
||||
} else {
|
||||
invoke(
|
||||
app,
|
||||
SpectateGame {
|
||||
game_id: game_id.clone(),
|
||||
},
|
||||
Some(&user),
|
||||
)
|
||||
.await?
|
||||
};
|
||||
let classification = classify_user(&user, &game);
|
||||
let result = invoke_join(app, &user, &game.id, classification).await?;
|
||||
|
||||
match result {
|
||||
Ok(messages) => {
|
||||
match (result, classification) {
|
||||
(Ok(messages), UserClassification::Spectator) => {
|
||||
app.socket_manager
|
||||
.change_socket_state(
|
||||
&socket_id,
|
||||
SocketState::InGame(session_id, user, game_id),
|
||||
SocketState::Spectator(game_id, Some((session_id, user))),
|
||||
)
|
||||
.await;
|
||||
Ok(messages)
|
||||
}
|
||||
Err(err) => Ok(vec![GameMessage::Error(err.to_string())]),
|
||||
(Ok(messages), UserClassification::Player) => {
|
||||
app.socket_manager
|
||||
.change_socket_state(
|
||||
&socket_id,
|
||||
SocketState::Player(session_id, user, game_id),
|
||||
)
|
||||
.await;
|
||||
Ok(messages)
|
||||
}
|
||||
(Ok(messages), UserClassification::Gm) => {
|
||||
app.socket_manager
|
||||
.change_socket_state(&socket_id, SocketState::Gm(session_id, user, game_id))
|
||||
.await;
|
||||
Ok(messages)
|
||||
}
|
||||
(Err(err), _) => Ok(vec![GameMessage::Error(err.to_string())]),
|
||||
}
|
||||
}
|
||||
// Authenticated spectator trying to switch games (might become player)
|
||||
(
|
||||
SocketState::Spectator(_, Some((_session_id, _user_id))),
|
||||
GameRequest::JoinGame(_game_id),
|
||||
) => {
|
||||
// Retrieve the user from the session
|
||||
/*
|
||||
let user = match self.user(&user_id).await? {
|
||||
Ok(Some(user)) => user,
|
||||
Ok(_) => return Ok(Some(GameMessage::PermissionDenied)),
|
||||
Err(err) => return Ok(Some(GameMessage::Error(err.to_string()))),
|
||||
};
|
||||
|
||||
let game = match self.game(&game_id).await? {
|
||||
(SocketState::Spectator(_, Some((session_id, user))), GameRequest::JoinGame(game_id)) => {
|
||||
let game = match app.substrate.game(&game_id).await? {
|
||||
Ok(game) => game,
|
||||
Err(err) => {
|
||||
return Ok(Some(GameMessage::Error(err.to_string())));
|
||||
Err(_) => {
|
||||
return Ok(vec![GameMessage::Error("Game not found".to_string())]);
|
||||
}
|
||||
};
|
||||
|
||||
if game.contains_user(&user.id) {
|
||||
// User is a player or GM in the game
|
||||
self.change_websocket_state(
|
||||
&socket_id,
|
||||
SocketState::InGame(session_id.clone(), user.clone(), game_id),
|
||||
)
|
||||
.await;
|
||||
Ok(Some(GameMessage::Ok))
|
||||
} else if game.open_to_spectators {
|
||||
// User is not a player but game is open to spectators
|
||||
self.change_websocket_state(
|
||||
&socket_id,
|
||||
SocketState::Spectator(
|
||||
game_id,
|
||||
Some((session_id.clone(), user.id.clone())),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
Ok(Some(GameMessage::Ok))
|
||||
} else {
|
||||
Ok(Some(GameMessage::PermissionDenied))
|
||||
let classification = classify_user(&user, &game);
|
||||
let result = invoke_join(app, &user, &game.id, classification).await?;
|
||||
|
||||
match (result, classification) {
|
||||
(Ok(messages), UserClassification::Spectator) => {
|
||||
app.socket_manager
|
||||
.change_socket_state(
|
||||
&socket_id,
|
||||
SocketState::Spectator(game_id, Some((session_id, user))),
|
||||
)
|
||||
.await;
|
||||
Ok(messages)
|
||||
}
|
||||
(Ok(messages), UserClassification::Player) => {
|
||||
app.socket_manager
|
||||
.change_socket_state(
|
||||
&socket_id,
|
||||
SocketState::Player(session_id, user, game_id),
|
||||
)
|
||||
.await;
|
||||
Ok(messages)
|
||||
}
|
||||
(Ok(messages), UserClassification::Gm) => {
|
||||
app.socket_manager
|
||||
.change_socket_state(&socket_id, SocketState::Gm(session_id, user, game_id))
|
||||
.await;
|
||||
Ok(messages)
|
||||
}
|
||||
(Err(err), _) => Ok(vec![GameMessage::Error(err.to_string())]),
|
||||
}
|
||||
*/
|
||||
Ok(vec![GameMessage::Error("Unhandled".to_owned())])
|
||||
}
|
||||
// Spectators cannot send any other messages
|
||||
(SocketState::Spectator(_, _), _) => Ok(vec![GameMessage::PermissionDenied]),
|
||||
_ => Ok(vec![GameMessage::InvalidState]),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum UserClassification {
|
||||
Spectator,
|
||||
Player,
|
||||
Gm,
|
||||
}
|
||||
|
||||
fn classify_user(user: &User, game: &GameOverview) -> UserClassification {
|
||||
if game.gm == user.id {
|
||||
UserClassification::Gm
|
||||
} else if game.contains_user(&user.id) {
|
||||
UserClassification::Player
|
||||
} else {
|
||||
UserClassification::Spectator
|
||||
}
|
||||
}
|
||||
|
||||
async fn invoke_join(
|
||||
app: &AppData,
|
||||
user: &User,
|
||||
game_id: &GameId,
|
||||
classification: UserClassification,
|
||||
) -> Result<Result<Vec<GameMessage>, Error>, Fatal> {
|
||||
match classification {
|
||||
UserClassification::Spectator => {
|
||||
invoke(
|
||||
app,
|
||||
SpectateGame {
|
||||
game_id: game_id.clone(),
|
||||
},
|
||||
Some(&user),
|
||||
)
|
||||
.await
|
||||
}
|
||||
UserClassification::Player => {
|
||||
invoke(
|
||||
app,
|
||||
PlayGame {
|
||||
game_id: game_id.clone(),
|
||||
},
|
||||
Some(&user),
|
||||
)
|
||||
.await
|
||||
}
|
||||
UserClassification::Gm => {
|
||||
invoke(
|
||||
app,
|
||||
GmGame {
|
||||
game_id: game_id.clone(),
|
||||
},
|
||||
Some(&user),
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user