@@ 20,7 20,7 @@ impl State {
}
let x = mode.w as i16 / 2;
let y = mode.h as i16 - 108;
- sdl.draw_text_centered(&to_hex(&self.lobby.code), WHITE, x as i32, y as i32);
+ sdl.draw_text_centered(&to_hex(&self.lobby.code), WHITE, x as i32, y as i32 - 108);
let clicked = sdl.button(x - 216, y, "Leave", GREEN, BLACK);
if clicked {
outgoing.lock().unwrap().push(GlobalAction::Leave);
@@ 54,6 54,9 @@ impl Globals {
(State::Search(state), GlobalEvent::Available(lobby)) => {
state.lobbies.push(lobby);
},
+ (State::Search(state), GlobalEvent::Unavailable(code)) => {
+ state.lobbies.retain(|l| l.code != code);
+ },
(State::Search(_), GlobalEvent::Created(code)) => {
self.state = State::Lobby(lobby::State::from_create(self.me.clone(), code));
},
@@ 2,6 2,7 @@ use roguelike_common::*;
use sodiumoxide::crypto::box_::*;
use sodiumoxide::crypto::sealedbox::{self, SEALBYTES};
use sodiumoxide::randombytes;
+use std::collections::HashMap;
use std::env;
use std::io::Read;
use std::net::{TcpListener, TcpStream};
@@ 46,17 47,31 @@ impl Lobby {
}
pub struct Context {
- searchers: Vec<Arc<RwLock<Player>>>,
+ searchers: HashMap<Id, Arc<RwLock<Player>>>,
lobbies: Vec<Arc<RwLock<Lobby>>>,
incoming: Vec<(Arc<RwLock<Player>>, GlobalAction)>,
}
+impl Context {
+ pub fn add_searcher(&mut self, player: Arc<RwLock<Player>>) {
+ let mut player_unlocked = player.write().unwrap();
+ player_unlocked.status = PlayerStatus::Searching;
+ self.searchers.insert(player_unlocked.external.id, Arc::clone(&player));
+ for lobby in &self.lobbies {
+ let lobby = lobby.read().unwrap();
+ if lobby.public {
+ player_unlocked.outgoing.push(GlobalEvent::Available(lobby.external()));
+ }
+ }
+
+ }
+}
fn main() {
sodiumoxide::init().unwrap();
let addr = env::args().nth(1).unwrap_or_else(|| "[::]".into());
let listener = TcpListener::bind(format!("{}:{}", addr, PORT)).unwrap();
let ctx = Arc::new(RwLock::new(Context{
- searchers: vec![],
+ searchers: HashMap::new(),
lobbies: vec![],
incoming: vec![],
}));
@@ 86,15 101,10 @@ fn handle_lobby_action(ctx: &Arc<RwLock<Context>>, player: Arc<RwLock<Player>>,
match action {
GlobalAction::Name(name) => {
let mut ctx = ctx.write().unwrap();
- ctx.searchers.push(Arc::clone(&player));
- let mut player = player.write().unwrap();
- player.external.name = name;
- for lobby in &ctx.lobbies {
- let lobby = lobby.read().unwrap();
- if lobby.public {
- player.outgoing.push(GlobalEvent::Available(lobby.external()));
- }
- }
+ let mut player_unlocked = player.write().unwrap();
+ player_unlocked.external.name = name;
+ drop(player_unlocked);
+ ctx.add_searcher(player);
},
GlobalAction::Create => {
let mut player_unlocked = player.write().unwrap();
@@ 107,13 117,15 @@ fn handle_lobby_action(ctx: &Arc<RwLock<Context>>, player: Arc<RwLock<Player>>,
in_game: false,
}));
player_unlocked.status = PlayerStatus::Lobby(Arc::clone(&lobby));
- ctx.write().unwrap().lobbies.push(lobby);
player_unlocked.outgoing.push(GlobalEvent::Created(code));
+ let mut ctx = ctx.write().unwrap();
+ ctx.lobbies.push(lobby);
+ ctx.searchers.remove(&player_unlocked.external.id);
},
GlobalAction::Join(code) => {
let mut player_unlocked = player.write().unwrap();
if !matches!(player_unlocked.status, PlayerStatus::Searching) { return }
- let ctx = ctx.read().unwrap();
+ let mut ctx = ctx.write().unwrap();
for lobby in &ctx.lobbies {
let mut lobby_unlocked = lobby.write().unwrap();
if lobby_unlocked.code == code {
@@ 124,19 136,20 @@ fn handle_lobby_action(ctx: &Arc<RwLock<Context>>, player: Arc<RwLock<Player>>,
}
player_unlocked.outgoing.push(GlobalEvent::Accepted(lobby_unlocked.external()));
lobby_unlocked.players.push(Arc::clone(&player));
+ drop(lobby_unlocked);
+ ctx.searchers.remove(&player_unlocked.external.id);
+ break;
}
}
},
GlobalAction::Leave => {
- let mut player = player.write().unwrap();
- let id = player.external.id;
- let lobby = match &player.status {
+ let player_unlocked = player.read().unwrap();
+ let id = player_unlocked.external.id;
+ let lobby = match &player_unlocked.status {
PlayerStatus::Lobby(l) => Arc::clone(l),
_ => return,
};
- // TODO send them the list
- player.status = PlayerStatus::Searching;
- drop(player);
+ drop(player_unlocked);
let mut lobby = lobby.write().unwrap();
let mut i = 0;
while i < lobby.players.len() {
@@ 150,6 163,14 @@ fn handle_lobby_action(ctx: &Arc<RwLock<Context>>, player: Arc<RwLock<Player>>,
i += 1;
}
}
+ let empty = lobby.players.is_empty();
+ let code = lobby.code;
+ drop(lobby);
+ let mut ctx = ctx.write().unwrap();
+ if empty {
+ ctx.lobbies.retain(|l| l.read().unwrap().code != code);
+ }
+ ctx.add_searcher(player);
},
GlobalAction::SetPublic(public) => {
let lobby = match &player.read().unwrap().status {
@@ 168,7 189,7 @@ fn handle_lobby_action(ctx: &Arc<RwLock<Context>>, player: Arc<RwLock<Player>>,
} else {
GlobalEvent::Unavailable(lobby_unlocked.code)
};
- for searcher in &ctx.read().unwrap().searchers {
+ for searcher in ctx.read().unwrap().searchers.values() {
searcher.write().unwrap().outgoing.push(event.clone());
}
},
@@ 197,7 218,6 @@ fn handle_lobby_action(ctx: &Arc<RwLock<Context>>, player: Arc<RwLock<Player>>,
player.write().unwrap().outgoing.push(GlobalEvent::Action(id, action.clone()));
}
},
- _ => {},
}
}