feat: remove the need for constant polling data
This commit is contained in:
@@ -326,6 +326,8 @@ async fn handle_connection(
|
|||||||
sd.clients.write().await.remove(&username);
|
sd.clients.write().await.remove(&username);
|
||||||
sd.usernames.write().await.remove(&addr);
|
sd.usernames.write().await.remove(&addr);
|
||||||
|
|
||||||
|
sd.broadcast(&format!("DISCONNECT:{}", username)).await;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,14 +44,21 @@ impl Server {
|
|||||||
) -> Result<(), anyhow::Error> {
|
) -> Result<(), anyhow::Error> {
|
||||||
if requested_username.is_empty() {
|
if requested_username.is_empty() {
|
||||||
return Err(anyhow::anyhow!(format!(
|
return Err(anyhow::anyhow!(format!(
|
||||||
"ERROR:INVALID:ID:{}",
|
"ERROR:INVALID:CONNECT:{}",
|
||||||
|
requested_username
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if requested_username.chars().any(|c| matches!(c, ':' | ',' | '|') || c.is_control()) {
|
||||||
|
return Err(anyhow::anyhow!(format!(
|
||||||
|
"ERROR:INVALID:CONNECT:{}",
|
||||||
requested_username
|
requested_username
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if requested_username == SERVER_PLAYER_USERNAME {
|
if requested_username == SERVER_PLAYER_USERNAME {
|
||||||
return Err(anyhow::anyhow!(format!(
|
return Err(anyhow::anyhow!(format!(
|
||||||
"ERROR:INVALID:ID:{}",
|
"ERROR:INVALID:CONNECT:{}",
|
||||||
requested_username
|
requested_username
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
@@ -66,7 +73,7 @@ impl Server {
|
|||||||
let existing_client = clients_guard.get(&requested_username).cloned();
|
let existing_client = clients_guard.get(&requested_username).cloned();
|
||||||
if existing_client.is_some() && !reconnecting {
|
if existing_client.is_some() && !reconnecting {
|
||||||
return Err(anyhow::anyhow!(format!(
|
return Err(anyhow::anyhow!(format!(
|
||||||
"ERROR:INVALID:ID:{}",
|
"ERROR:INVALID:CONNECT:{}",
|
||||||
requested_username
|
requested_username
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
@@ -81,12 +88,14 @@ impl Server {
|
|||||||
self.clients.write().await.insert(
|
self.clients.write().await.insert(
|
||||||
requested_username.clone(),
|
requested_username.clone(),
|
||||||
Arc::new(RwLock::new(Client::new(
|
Arc::new(RwLock::new(Client::new(
|
||||||
requested_username,
|
requested_username.clone(),
|
||||||
tx.clone(),
|
tx.clone(),
|
||||||
addr.to_string().parse()?,
|
addr.to_string().parse()?,
|
||||||
))),
|
))),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
self.broadcast(&format!("CONNECT:{}", requested_username)).await;
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,6 +226,7 @@ impl Server {
|
|||||||
self.clients.write().await.remove(&username);
|
self.clients.write().await.remove(&username);
|
||||||
self.usernames.write().await.remove(&addr);
|
self.usernames.write().await.remove(&addr);
|
||||||
let _ = send(&tx, "DISCONNECT:ACK");
|
let _ = send(&tx, "DISCONNECT:ACK");
|
||||||
|
self.broadcast(&format!("DISCONNECT:{}", username)).await;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -264,6 +274,7 @@ impl Server {
|
|||||||
let _ = send(&tx, "READY:ACK");
|
let _ = send(&tx, "READY:ACK");
|
||||||
drop(client);
|
drop(client);
|
||||||
drop(clients_guard);
|
drop(clients_guard);
|
||||||
|
self.broadcast(&format!("READY:{}:{}", username, true)).await;
|
||||||
|
|
||||||
if let Some(opponent_username) = self.find_reservation_opponent(&username).await {
|
if let Some(opponent_username) = self.find_reservation_opponent(&username).await {
|
||||||
let clients_guard = self.clients.read().await;
|
let clients_guard = self.clients.read().await;
|
||||||
@@ -278,6 +289,14 @@ impl Server {
|
|||||||
false,
|
false,
|
||||||
)));
|
)));
|
||||||
self.matches.write().await.insert(match_id, new_match.clone());
|
self.matches.write().await.insert(match_id, new_match.clone());
|
||||||
|
let match_guard = new_match.read().await;
|
||||||
|
self
|
||||||
|
.broadcast(&format!(
|
||||||
|
"GAME:START:{},{},{}",
|
||||||
|
match_id, match_guard.player1, match_guard.player2
|
||||||
|
))
|
||||||
|
.await;
|
||||||
|
drop(match_guard);
|
||||||
|
|
||||||
client.ready = false;
|
client.ready = false;
|
||||||
client.current_match = Some(match_id);
|
client.current_match = Some(match_id);
|
||||||
@@ -294,6 +313,7 @@ impl Server {
|
|||||||
opponent.ready = false;
|
opponent.ready = false;
|
||||||
opponent.current_match = Some(match_id);
|
opponent.current_match = Some(match_id);
|
||||||
opponent.color = !client.color;
|
opponent.color = !client.color;
|
||||||
|
let opponent_username = opponent.username.clone();
|
||||||
|
|
||||||
self
|
self
|
||||||
.reservations
|
.reservations
|
||||||
@@ -301,6 +321,12 @@ impl Server {
|
|||||||
.await
|
.await
|
||||||
.retain(|(p1, p2)| !(p1 == &client.username && p2 == &opponent.username));
|
.retain(|(p1, p2)| !(p1 == &client.username && p2 == &opponent.username));
|
||||||
|
|
||||||
|
drop(opponent);
|
||||||
|
drop(client);
|
||||||
|
drop(clients_guard);
|
||||||
|
self.broadcast(&format!("READY:{}:{}", username, false)).await;
|
||||||
|
self.broadcast(&format!("READY:{}:{}", opponent_username, false)).await;
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,6 +342,15 @@ impl Server {
|
|||||||
is_demo_mode,
|
is_demo_mode,
|
||||||
)));
|
)));
|
||||||
self.matches.write().await.insert(match_id, new_match.clone());
|
self.matches.write().await.insert(match_id, new_match.clone());
|
||||||
|
let match_guard = new_match.read().await;
|
||||||
|
self
|
||||||
|
.broadcast(&format!(
|
||||||
|
"GAME:START:{},{},{}",
|
||||||
|
match_id, match_guard.player1, match_guard.player2
|
||||||
|
))
|
||||||
|
.await;
|
||||||
|
drop(match_guard);
|
||||||
|
|
||||||
client.ready = false;
|
client.ready = false;
|
||||||
client.current_match = Some(match_id);
|
client.current_match = Some(match_id);
|
||||||
client.color = if new_match.read().await.player1 == username {
|
client.color = if new_match.read().await.player1 == username {
|
||||||
@@ -355,6 +390,9 @@ impl Server {
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drop(client);
|
||||||
|
self.broadcast(&format!("READY:{}:{}", username, false)).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -1202,8 +1240,17 @@ impl Server {
|
|||||||
false,
|
false,
|
||||||
)));
|
)));
|
||||||
self.matches.write().await.insert(match_id, new_match.clone());
|
self.matches.write().await.insert(match_id, new_match.clone());
|
||||||
|
let match_guard = new_match.read().await;
|
||||||
|
self
|
||||||
|
.broadcast(&format!(
|
||||||
|
"GAME:START:{},{},{}",
|
||||||
|
match_id, match_guard.player1, match_guard.player2
|
||||||
|
))
|
||||||
|
.await;
|
||||||
|
drop(match_guard);
|
||||||
|
|
||||||
player1.ready = false;
|
player1.ready = false;
|
||||||
|
let player1_name = player1.username.clone();
|
||||||
player1.current_match = Some(match_id);
|
player1.current_match = Some(match_id);
|
||||||
player1.color = if new_match.read().await.player1 == player1_username {
|
player1.color = if new_match.read().await.player1 == player1_username {
|
||||||
let _ = send(&tx, "GAME:START:1");
|
let _ = send(&tx, "GAME:START:1");
|
||||||
@@ -1216,6 +1263,7 @@ impl Server {
|
|||||||
};
|
};
|
||||||
|
|
||||||
player2.ready = false;
|
player2.ready = false;
|
||||||
|
let player2_name = player2.username.clone();
|
||||||
player2.current_match = Some(match_id);
|
player2.current_match = Some(match_id);
|
||||||
player2.color = !player1.color;
|
player2.color = !player1.color;
|
||||||
|
|
||||||
@@ -1224,6 +1272,12 @@ impl Server {
|
|||||||
.write()
|
.write()
|
||||||
.await
|
.await
|
||||||
.retain(|(p1, p2)| !(p1 == &player1_username && p2 == &player2_username));
|
.retain(|(p1, p2)| !(p1 == &player1_username && p2 == &player2_username));
|
||||||
|
|
||||||
|
drop(player2);
|
||||||
|
drop(player1);
|
||||||
|
drop(clients_guard);
|
||||||
|
self.broadcast(&format!("READY:{}:{}", player1_name, false)).await;
|
||||||
|
self.broadcast(&format!("READY:{}:{}", player2_name, false)).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ pub struct KnockoutBracket {
|
|||||||
pub started: bool,
|
pub started: bool,
|
||||||
pub clients: Clients,
|
pub clients: Clients,
|
||||||
pub matches: Matches,
|
pub matches: Matches,
|
||||||
|
pub observers: Observers,
|
||||||
pub usernames: Vec<String>,
|
pub usernames: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,12 +40,16 @@ impl KnockoutBracket {
|
|||||||
player2_username.clone(),
|
player2_username.clone(),
|
||||||
false,
|
false,
|
||||||
)));
|
)));
|
||||||
|
|
||||||
let match_guard = new_match.read().await;
|
let match_guard = new_match.read().await;
|
||||||
let mut player1 = clients_guard.get(&player1_username).unwrap().write().await;
|
|
||||||
|
|
||||||
|
let mut player1 = clients_guard.get(&player1_username).unwrap().write().await;
|
||||||
player1.current_match = Some(match_id);
|
player1.current_match = Some(match_id);
|
||||||
player1.ready = false;
|
player1.ready = false;
|
||||||
|
broadcast_message(
|
||||||
|
&self.observers,
|
||||||
|
&format!("READY:{}:{}", player1.username.clone(), false),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
if match_guard.player1 == player1_username {
|
if match_guard.player1 == player1_username {
|
||||||
player1.color = Color::Red;
|
player1.color = Color::Red;
|
||||||
@@ -53,13 +58,16 @@ impl KnockoutBracket {
|
|||||||
player1.color = Color::Yellow;
|
player1.color = Color::Yellow;
|
||||||
let _ = send(&player1.connection, "GAME:START:0");
|
let _ = send(&player1.connection, "GAME:START:0");
|
||||||
}
|
}
|
||||||
|
|
||||||
drop(player1);
|
drop(player1);
|
||||||
|
|
||||||
let mut player2 = clients_guard.get(&player2_username).unwrap().write().await;
|
let mut player2 = clients_guard.get(&player2_username).unwrap().write().await;
|
||||||
|
|
||||||
player2.current_match = Some(match_id);
|
player2.current_match = Some(match_id);
|
||||||
player2.ready = false;
|
player2.ready = false;
|
||||||
|
broadcast_message(
|
||||||
|
&self.observers,
|
||||||
|
&format!("READY:{}:{}", player2.username.clone(), false),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
if match_guard.player1 == player2_username {
|
if match_guard.player1 == player2_username {
|
||||||
player2.color = Color::Red;
|
player2.color = Color::Red;
|
||||||
@@ -68,10 +76,17 @@ impl KnockoutBracket {
|
|||||||
player2.color = Color::Yellow;
|
player2.color = Color::Yellow;
|
||||||
let _ = send(&player2.connection, "GAME:START:0");
|
let _ = send(&player2.connection, "GAME:START:0");
|
||||||
}
|
}
|
||||||
|
|
||||||
drop(player2);
|
drop(player2);
|
||||||
|
|
||||||
self.matches.write().await.insert(match_id, new_match.clone());
|
self.matches.write().await.insert(match_id, new_match.clone());
|
||||||
|
broadcast_message(
|
||||||
|
&self.observers,
|
||||||
|
&format!(
|
||||||
|
"GAME:START:{},{},{}",
|
||||||
|
match_id, match_guard.player1, match_guard.player2
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
i += 2
|
i += 2
|
||||||
}
|
}
|
||||||
@@ -95,6 +110,7 @@ impl Tournament for KnockoutBracket {
|
|||||||
started: false,
|
started: false,
|
||||||
clients: server.clients.clone(),
|
clients: server.clients.clone(),
|
||||||
matches: server.matches.clone(),
|
matches: server.matches.clone(),
|
||||||
|
observers: server.observers.clone(),
|
||||||
usernames: ready_players.to_vec(),
|
usernames: ready_players.to_vec(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -219,6 +235,7 @@ impl Tournament for KnockoutBracket {
|
|||||||
|
|
||||||
player1.current_match = Some(match_id);
|
player1.current_match = Some(match_id);
|
||||||
player1.ready = false;
|
player1.ready = false;
|
||||||
|
let player1_name = player1.username.clone();
|
||||||
|
|
||||||
if match_guard.player1 == player1.username {
|
if match_guard.player1 == player1.username {
|
||||||
player1.color = Color::Red;
|
player1.color = Color::Red;
|
||||||
@@ -234,6 +251,7 @@ impl Tournament for KnockoutBracket {
|
|||||||
|
|
||||||
player2.current_match = Some(match_id);
|
player2.current_match = Some(match_id);
|
||||||
player2.ready = false;
|
player2.ready = false;
|
||||||
|
let player2_name = player2.username.clone();
|
||||||
|
|
||||||
if match_guard.player1 == player2.username {
|
if match_guard.player1 == player2.username {
|
||||||
player2.color = Color::Red;
|
player2.color = Color::Red;
|
||||||
@@ -245,8 +263,27 @@ impl Tournament for KnockoutBracket {
|
|||||||
|
|
||||||
drop(player2);
|
drop(player2);
|
||||||
|
|
||||||
|
broadcast_message(
|
||||||
|
&self.observers,
|
||||||
|
&format!("READY:{}:{}", player1_name, false),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
broadcast_message(
|
||||||
|
&self.observers,
|
||||||
|
&format!("READY:{}:{}", player2_name, false),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
self.current_matches.push(match_id);
|
self.current_matches.push(match_id);
|
||||||
self.matches.write().await.insert(match_id, new_match.clone());
|
self.matches.write().await.insert(match_id, new_match.clone());
|
||||||
|
broadcast_message(
|
||||||
|
&self.observers,
|
||||||
|
&format!(
|
||||||
|
"GAME:START:{},{},{}",
|
||||||
|
match_id, match_guard.player1, match_guard.player2
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut loser = String::new();
|
let mut loser = String::new();
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ pub struct RoundRobin {
|
|||||||
pub completed: bool,
|
pub completed: bool,
|
||||||
pub current_matches: Vec<ID>,
|
pub current_matches: Vec<ID>,
|
||||||
pub usernames: Vec<String>,
|
pub usernames: Vec<String>,
|
||||||
|
pub observers: Observers,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RoundRobin {
|
impl RoundRobin {
|
||||||
@@ -39,12 +40,16 @@ impl RoundRobin {
|
|||||||
)));
|
)));
|
||||||
|
|
||||||
self.current_matches.push(match_id.clone());
|
self.current_matches.push(match_id.clone());
|
||||||
|
|
||||||
let match_guard = new_match.read().await;
|
let match_guard = new_match.read().await;
|
||||||
let mut player1 = clients_guard.get(&player1_username.0).unwrap().write().await;
|
|
||||||
|
|
||||||
|
let mut player1 = clients_guard.get(&player1_username.0).unwrap().write().await;
|
||||||
player1.current_match = Some(match_id);
|
player1.current_match = Some(match_id);
|
||||||
player1.ready = false;
|
player1.ready = false;
|
||||||
|
broadcast_message(
|
||||||
|
&self.observers,
|
||||||
|
&format!("READY:{}:{}", player1.username.clone(), false),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
if match_guard.player1 == player1_username.0 {
|
if match_guard.player1 == player1_username.0 {
|
||||||
player1.color = Color::Red;
|
player1.color = Color::Red;
|
||||||
@@ -53,13 +58,16 @@ impl RoundRobin {
|
|||||||
player1.color = Color::Yellow;
|
player1.color = Color::Yellow;
|
||||||
let _ = send(&player1.connection, "GAME:START:0");
|
let _ = send(&player1.connection, "GAME:START:0");
|
||||||
}
|
}
|
||||||
|
|
||||||
drop(player1);
|
drop(player1);
|
||||||
|
|
||||||
let mut player2 = clients_guard.get(&player2_addr.0).unwrap().write().await;
|
let mut player2 = clients_guard.get(&player2_addr.0).unwrap().write().await;
|
||||||
|
|
||||||
player2.current_match = Some(match_id);
|
player2.current_match = Some(match_id);
|
||||||
player2.ready = false;
|
player2.ready = false;
|
||||||
|
broadcast_message(
|
||||||
|
&self.observers,
|
||||||
|
&format!("READY:{}:{}", player2.username.clone(), false),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
if match_guard.player1 == player2_addr.0 {
|
if match_guard.player1 == player2_addr.0 {
|
||||||
player2.color = Color::Red;
|
player2.color = Color::Red;
|
||||||
@@ -68,17 +76,24 @@ impl RoundRobin {
|
|||||||
player2.color = Color::Yellow;
|
player2.color = Color::Yellow;
|
||||||
let _ = send(&player2.connection, "GAME:START:0");
|
let _ = send(&player2.connection, "GAME:START:0");
|
||||||
}
|
}
|
||||||
|
|
||||||
drop(player2);
|
drop(player2);
|
||||||
|
|
||||||
matches.write().await.insert(match_id, new_match.clone());
|
matches.write().await.insert(match_id, new_match.clone());
|
||||||
|
broadcast_message(
|
||||||
|
&self.observers,
|
||||||
|
&format!(
|
||||||
|
"GAME:START:{},{},{}",
|
||||||
|
match_id, match_guard.player1, match_guard.player2
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Tournament for RoundRobin {
|
impl Tournament for RoundRobin {
|
||||||
async fn new(ready_players: &[String], _: &Server) -> RoundRobin {
|
async fn new(ready_players: &[String], server: &Server) -> RoundRobin {
|
||||||
let mut result = RoundRobin {
|
let mut result = RoundRobin {
|
||||||
players: HashMap::new(),
|
players: HashMap::new(),
|
||||||
top_half: Vec::new(),
|
top_half: Vec::new(),
|
||||||
@@ -86,6 +101,7 @@ impl Tournament for RoundRobin {
|
|||||||
completed: false,
|
completed: false,
|
||||||
current_matches: Vec::new(),
|
current_matches: Vec::new(),
|
||||||
usernames: ready_players.to_vec(),
|
usernames: ready_players.to_vec(),
|
||||||
|
observers: server.observers.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let size = ready_players.len();
|
let size = ready_players.len();
|
||||||
|
|||||||
Reference in New Issue
Block a user