From: Ian Jackson Date: Sun, 23 Aug 2020 20:02:48 +0000 (+0100) Subject: dupe nick handling X-Git-Tag: otter-0.2.0~1071 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=ab4d5884f991339e7c9609f0bf01c3081246e159;p=otter.git dupe nick handling --- diff --git a/src/bin/otter.rs b/src/bin/otter.rs index 45a91697..7fa66944 100644 --- a/src/bin/otter.rs +++ b/src/bin/otter.rs @@ -288,7 +288,8 @@ fn connect(ma: &MainOpts) -> Conn { chan } -fn setup_table(chan: &mut ConnForGame, spec: &TableSpec) -> Result<(),AE> { +fn setup_table(ma: &MainOpts, chan: &mut ConnForGame, + spec: &TableSpec) -> Result<(),AE> { // xxx should delete old players // create missing players @@ -306,6 +307,9 @@ fn setup_table(chan: &mut ConnForGame, spec: &TableSpec) -> Result<(),AE> { let mut insns = vec![]; for pspec in &spec.players { let st = nick2st.entry(pspec.nick.clone()).or_default(); + if st.new { + Err(anyhow!("duplicate player nick {:?} in spec", &pspec.nick))?; + } st.new = true; if !st.old { insns.push(MgmtGameInstruction::AddPlayer(PlayerState { @@ -313,14 +317,24 @@ fn setup_table(chan: &mut ConnForGame, spec: &TableSpec) -> Result<(),AE> { })); } } + + for (nick, st) in nick2st { + if st.new { continue } + if !st.old { continue } + if ma.verbose >= 1 { + eprintln!("removing old player {:?}", &nick); + } + insns.push(Insn::RemovePlayer(st.id)); + } + let mut added_players = HashSet::new(); chan.alter_game(insns, Some(&mut |response| { - let player = match response { - &Resp::AddPlayer(player) => player, - _ => Err(anyhow!("AddPlayer strange answer {:?}", - &response))?, + match response { + &Resp::AddPlayer(player) => { + added_players.insert(player); + }, + _ => { }, }; - added_players.insert(player); Ok(()) }))?; @@ -426,7 +440,7 @@ mod create_table { how: MgmtGameUpdateMode::Bulk, }; - setup_table(&mut chan, &spec)?; + setup_table(&ma, &mut chan, &spec)?; if ma.verbose >= 0 { eprintln!("create-table successful. game still needs setup."); @@ -486,7 +500,7 @@ mod reset_game { Err(e) })?; - setup_table(&mut chan, &table_spec)?; + setup_table(&ma, &mut chan, &table_spec)?; } let mut insns = vec![]; diff --git a/src/global.rs b/src/global.rs index 6ed1ac58..fc6867fb 100644 --- a/src/global.rs +++ b/src/global.rs @@ -306,11 +306,14 @@ impl DerefMut for InstanceGuard<'_> { impl InstanceGuard<'_> { /// caller is responsible for logging; threading it through /// proves the caller has a log entry. - #[throws(ServerFailure)] + #[throws(MgmtError)] pub fn player_new(&mut self, newplayer: PlayerState, logentry: LogEntry) -> (PlayerId, LogEntry) { // saving is fallible, but we can't attempt to save unless // we have a thing to serialise with the player in it + if self.c.g.gs.players.values().any(|pl| pl.nick == newplayer.nick) { + Err(MgmtError::AlreadyExists)?; + } let player = self.c.g.gs.players.insert(newplayer); self.save_game_now().map_err(|e|{ self.c.g.gs.players.remove(player);