Skip to content

Commit

Permalink
Disband lobby if host leaves during setup, and when HostClient discon…
Browse files Browse the repository at this point in the history
…nects during sync.
  • Loading branch information
SLiV9 committed May 21, 2021
1 parent f6547b6 commit 08e064f
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 14 deletions.
41 changes: 32 additions & 9 deletions src/server/game.rs
Expand Up @@ -1117,6 +1117,7 @@ async fn rest(
{
handle_leave(
lobby.id,
None,
players,
bots,
watchers,
Expand Down Expand Up @@ -1156,7 +1157,7 @@ async fn rest(
{}
Update::FromHost(..) =>
{
return Err(Error::InvalidUpdate);
debug!("Ignoring FromHost while not hostsyncing");
}
Update::Msg(message) =>
{
Expand Down Expand Up @@ -1247,6 +1248,7 @@ async fn check(
{
handle_leave(
lobby.id,
None,
players,
bots,
watchers,
Expand Down Expand Up @@ -1286,7 +1288,7 @@ async fn check(
{}
Update::FromHost(..) =>
{
return Err(Error::InvalidUpdate);
debug!("Ignoring FromHost while not hostsyncing");
}
Update::Msg(message) =>
{
Expand Down Expand Up @@ -1417,6 +1419,7 @@ async fn sleep(
{
handle_leave(
lobby.id,
None,
players,
connected_bots,
watchers,
Expand Down Expand Up @@ -1461,7 +1464,7 @@ async fn sleep(
{}
Update::FromHost(..) =>
{
return Err(Error::InvalidUpdate);
debug!("Ignoring FromHost while not hostsyncing");
}
Update::Msg(message) =>
{
Expand Down Expand Up @@ -1585,6 +1588,7 @@ async fn stage(
{
handle_leave(
lobby.id,
None,
players,
connected_bots,
watchers,
Expand Down Expand Up @@ -1624,7 +1628,7 @@ async fn stage(
{}
Update::FromHost(..) =>
{
return Err(Error::InvalidUpdate);
debug!("Ignoring FromHost while not hostsyncing");
}
Update::Msg(message) =>
{
Expand Down Expand Up @@ -1655,11 +1659,19 @@ async fn sync_host(
{
host.handle.send(Message::HostSync { metadata: None });

let mut synced = false;
while !synced
let mut has_synced = false;
while !has_synced
{
trace!("Waiting for host sync...");

// We only check this here, but if the host disconnected before,
// sending the HostSync at the start of this function should (?)
// have let us know that it is disconnected.
if !host.is_connected()
{
return Err(Error::HostDisconnected);
}

let update = match updates.recv().await
{
Some(update) => update,
Expand All @@ -1675,7 +1687,7 @@ async fn sync_host(
{
if client_id == host.id
{
synced = true;
has_synced = true;

if let Some(metadata) = metadata
{
Expand Down Expand Up @@ -1735,6 +1747,7 @@ async fn sync_host(
{
handle_leave(
lobby.id,
Some(host),
players,
&mut Vec::new(),
watchers,
Expand Down Expand Up @@ -1837,6 +1850,7 @@ async fn linger(
{
handle_leave(
lobby.id,
None,
players,
bots,
watchers,
Expand Down Expand Up @@ -2286,13 +2300,22 @@ impl RejoinAndResignHandler for HostClient

async fn handle_leave(
lobby_id: Keycode,
host: Option<&mut HostClient>,
players: &mut Vec<PlayerClient>,
bots: &mut Vec<BotClient>,
watchers: &mut Vec<WatcherClient>,
client_id: Keycode,
general_chat: &mut mpsc::Sender<chat::Update>,
) -> Result<(), Error>
{
if let Some(host) = host
{
if host.id == client_id
{
host.handle.take();
}
}

let mut was_bot = false;
for bot in bots
{
Expand Down Expand Up @@ -2361,8 +2384,8 @@ async fn handle_leave(
pub enum Error
{
Abandoned,
HostDisconnected,
InvalidSetup,
InvalidUpdate,
MissingChallengeId,
ClientGone
{
Expand Down Expand Up @@ -2423,7 +2446,7 @@ impl fmt::Display for Error
{
Error::Abandoned => write!(f, "{:#?}", &self),
Error::InvalidSetup => write!(f, "{:#?}", &self),
Error::InvalidUpdate => write!(f, "{:#?}", &self),
Error::HostDisconnected => write!(f, "{:#?}", &self),
Error::MissingChallengeId => write!(f, "{:#?}", &self),
Error::ClientGone { .. } => write!(f, "{:#?}", &self),
Error::ResultDropped { .. } => write!(f, "{:#?}", &self),
Expand Down
33 changes: 28 additions & 5 deletions src/server/lobby.rs
Expand Up @@ -1013,9 +1013,22 @@ async fn handle_leave(
general_chat: &mut mpsc::Sender<chat::Update>,
) -> Result<(), Error>
{
let removed: Vec<Client> = clients
.e_drain_where(|client| client.id == client_id)
.collect();
let host_left = lobby
.host
.as_ref()
.map(|x| x.id == client_id)
.unwrap_or(false);
let removed: Vec<Client> = if host_left
{
// When the host leaves, the lobby is disbanded.
clients.drain(0..).collect()
}
else
{
clients
.e_drain_where(|client| client.id == client_id)
.collect()
};

handle_removed(lobby, clients, removed).await?;

Expand Down Expand Up @@ -2784,8 +2797,18 @@ async fn start(

if host_client.is_some()
{
// TODO HostedGame: get this name from the host?
let descriptive_name = bot.slot.get_display_name().to_string();
let difficulty_str = match bot.difficulty
{
Difficulty::None => "Easy",
Difficulty::Easy => "Easy",
Difficulty::Medium => "Medium",
Difficulty::Hard => "Hard",
};
let display_name = bot.slot.get_display_name();
let descriptive_name = format!(
"{} ({} {})",
display_name, difficulty_str, bot.ai_name
);
hosted_bots.push(game::HostedBot {
descriptive_name,
color,
Expand Down

0 comments on commit 08e064f

Please sign in to comment.