From f29da3591910d834d42918fcde0247d9e2edc357 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sun, 26 Jul 2020 15:50:13 +0100 Subject: [PATCH] before undo PieceUpdateOp with ID --- src/api.rs | 68 ++++++---------------- src/gamestate.rs | 1 + src/imports.rs | 1 + src/updates.rs | 147 +++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 142 insertions(+), 75 deletions(-) diff --git a/src/api.rs b/src/api.rs index 6b09c87a..b99e1eac 100644 --- a/src/api.rs +++ b/src/api.rs @@ -14,10 +14,11 @@ trait ApiPieceOp : Debug { #[throws(GameError)] fn op(&self, gs: &mut GameState, player: PlayerId, piece: PieceId, lens: &dyn Lens /* used for LogEntry and PieceId but not Pos */) - -> (PieceUpdateOp<()>, Vec); + -> (PieceUpdateOp<(),()>, Vec); } -trait Lens { +pub trait Lens { + fn visible_pieceid(&self, piece: PieceId) -> VisiblePieceId; fn log_pri(&self, piece: PieceId, pc: &PieceState) -> PieceRenderInstructions; fn svg_pri(&self, piece: PieceId, pc: &PieceState, player: PlayerId) @@ -28,10 +29,13 @@ trait Lens { } struct TransparentLens { } impl Lens for TransparentLens { + fn visible_pieceid(&self, piece: PieceId) -> VisiblePieceId { + let kd : slotmap::KeyData = piece.into(); + VisiblePieceId(kd); + } fn log_pri(&self, piece: PieceId, pc: &PieceState) -> PieceRenderInstructions { - let kd : slotmap::KeyData = piece.into(); - let id = VisiblePieceId(kd); + let id = self.make_piece_visible(piece); PieceRenderInstructions { id, face : pc.face } } fn svg_pri(&self, piece: PieceId, pc: &PieceState, _player: PlayerId) @@ -85,48 +89,12 @@ fn api_piece_op(form : Json>) eprintln!("API {:?} => {:?}", &form, &err); }, Ok((update, logents)) => { - let pc = gs.pieces.byid_mut(piece).expect("xxx piece deleted by op!"); - - gs.gen.increment(); - let gen = gs.gen; - if client != pc.lastclient { - pc.gen_before_lastclient = pc.gen; - pc.lastclient = client; - } - pc.gen = gen; - eprintln!("PC GEN_LC={:?} LC={:?}", pc.gen, pc.lastclient); - - let pri_for_all = lens.svg_pri(piece,pc,Default::default()); - - let update = update.try_map_new_state(|_|{ - let mut ns = pc.prep_piecestate(&pri_for_all)?; - lens.massage_prep_piecestate(&mut ns); - >::Ok(ns) - })?; - - let mut us = Vec::with_capacity(1 + logents.len()); - - us.push(PreparedUpdateEntry::Piece { - client, - sameclient_cseq : form.cseq, - piece : pri_for_all.id, - op : update, - }); - - for logentry in logents { - let logentry = Arc::new(logentry); - gs.log.push((gen, logentry.clone())); - us.push(PreparedUpdateEntry::Log(logentry)); - } - - let update = PreparedUpdate { gen, us, }; - let update = Arc::new(update); - eprintln!("UPDATE {:?}", &update); - - for (_tplayer, tplupdates) in &mut g.updates { - tplupdates.log.push_back(update.clone()); - tplupdates.cv.notify_all(); - } + let mut buf = PrepareUpdatesBuffer::new(g, client, form.cseq, + 1 + logents.len()); + + buf.piece_update(piece, update, &lens); + buf.log_updates(logents); + eprintln!("API {:?} OK", &form); } } @@ -146,7 +114,7 @@ impl ApiPieceOp for ApiPieceGrab { #[throws(GameError)] fn op(&self, gs: &mut GameState, player: PlayerId, piece: PieceId, lens: &dyn Lens) - -> (PieceUpdateOp<()>, Vec) { + -> (PieceUpdateOp<(),()>, Vec) { let pl = gs.players.byid(player).unwrap(); let pc = gs.pieces.byid_mut(piece).unwrap(); @@ -178,7 +146,7 @@ impl ApiPieceOp for ApiPieceUngrab { #[throws(GameError)] fn op(&self, gs: &mut GameState, player: PlayerId, piece: PieceId, lens: &dyn Lens) - -> (PieceUpdateOp<()>, Vec) { + -> (PieceUpdateOp<(),()>, Vec) { let pl = gs.players.byid(player).unwrap(); let pc = gs.pieces.byid_mut(piece).unwrap(); @@ -211,7 +179,7 @@ impl ApiPieceOp for ApiPieceRaise { #[throws(GameError)] fn op(&self, gs: &mut GameState, _: PlayerId, piece: PieceId, _: &dyn Lens) - -> (PieceUpdateOp<()>, Vec) { + -> (PieceUpdateOp<(),()>, Vec) { let pc = gs.pieces.byid_mut(piece).unwrap(); pc.zlevel = ZLevel { z : self.z, zg : gs.gen }; let update = PieceUpdateOp::SetZLevel(pc.zlevel); @@ -230,7 +198,7 @@ impl ApiPieceOp for ApiPieceMove { #[throws(GameError)] fn op(&self, gs: &mut GameState, _: PlayerId, piece: PieceId, _lens: &dyn Lens) - -> (PieceUpdateOp<()>, Vec) { + -> (PieceUpdateOp<(),()>, Vec) { let pc = gs.pieces.byid_mut(piece).unwrap(); pc.pos = self.0; diff --git a/src/gamestate.rs b/src/gamestate.rs index ce6633e3..a3517c49 100644 --- a/src/gamestate.rs +++ b/src/gamestate.rs @@ -163,6 +163,7 @@ impl PieceState { pub fn prep_piecestate(&self, pri : &PieceRenderInstructions) -> PreparedPieceState { PreparedPieceState { + piece : pri.id, pos : self.pos, held : self.held, svg : self.make_defs(pri)?, diff --git a/src/imports.rs b/src/imports.rs index 5d810839..c0eac3bf 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -64,6 +64,7 @@ pub use crate::error::*; pub use crate::commands::*; pub use crate::slotmap_slot_idx::*; pub use crate::cmdlistener::*; +pub use crate::api::Lens; pub use libc::uid_t; diff --git a/src/updates.rs b/src/updates.rs index 9b97d749..f17fc7a2 100644 --- a/src/updates.rs +++ b/src/updates.rs @@ -29,14 +29,14 @@ pub enum PreparedUpdateEntry { Piece { client : ClientId, sameclient_cseq : ClientSequence, - piece : VisiblePieceId, - op : PieceUpdateOp, + op : PieceUpdateOp, }, Log (Arc), } #[derive(Debug,Serialize)] pub struct PreparedPieceState { + pub piece : VisiblePieceId, pub pos : Pos, pub svg : String, pub held : Option, @@ -47,12 +47,12 @@ pub struct PreparedPieceState { // ---------- piece updates ---------- #[derive(Debug,Serialize)] -pub enum PieceUpdateOp { - Delete(), +pub enum PieceUpdateOp { + Delete(ID), Insert(NS), Modify(NS), - Move(Pos), - SetZLevel(ZLevel), + Move(ID,Pos), + SetZLevel(ID,ZLevel), } // ---------- for traansmission ---------- @@ -71,8 +71,7 @@ enum TransmitUpdateEntry<'u> { zg : Option, }, Piece { - piece : VisiblePieceId, - op : &'u PieceUpdateOp, + op : &'u PieceUpdateOp, }, Log (&'u LogEntry), } @@ -111,43 +110,141 @@ impl PreparedUpdateEntry { // ---------- PieceUpdatesOp ---------- -impl PieceUpdateOp { +impl PieceUpdateOp { pub fn new_state(&self) -> Option<&NS> { use PieceUpdateOp::*; match self { - Delete() => None, + Delete(_) => None, Insert(ns) => Some(ns), Modify(ns) => Some(ns), - Move(_) => None, - SetZLevel(_) => None, + Move(..) => None, + SetZLevel(..) => None, } } - pub fn try_map_new_state Result> - (self, f:F) -> Result,E> + pub fn try_map Result, + NSF: FnOnce(NS) -> Result> + (self, f:NSF, idf:IDF) -> Result,E> { use PieceUpdateOp::*; Ok(match self { - Delete() => Delete(), + Delete(i) => Delete(idf(i)?), Insert(ns) => Insert(f(ns)?), Modify(ns) => Modify(f(ns)?), - Move(pos) => Move(pos), - SetZLevel(zl) => SetZLevel(zl), + Move(i,pos) => Move(idf(i)?,pos), + SetZLevel(i,zl) => SetZLevel(idf(i)?,zl), }) } - pub fn map_new_state NS2>(self, f:F) - -> PieceUpdateOp { - #[derive(Error,Debug)] - enum Never { } - self.try_map_new_state(|ns| >::Ok(f(ns))).unwrap() + pub fn map ID2, + NSF: FnOnce(NS) -> NS2> + (self, nsf:NSF, idf:IDF) -> PieceUpdateOp + { + #[derive(Error,Debug)] enum Never { } + self.try_map( + |ns| >::Ok(nsf(ns)), + |id| >::Ok(idf(id)), + ).unwrap() } pub fn new_z_generation(&self) -> Option { use PieceUpdateOp::*; match self { - Delete() => None, + Delete(_) => None, Insert(_) => None, Modify(_) => None, - Move(_) => None, - SetZLevel(ZLevel{zg,..}) => Some(*zg), + Move(..) => None, + SetZLevel(_,ZLevel{zg,..}) => Some(*zg), + } + } + pub fn pieceid<'ns>(&'ns self) -> ID where &'ns NS : Into, ID : Copy { + use PieceUpdateOp::*; + match self { + Delete(i) => *i, + Insert(ns) | Modify(ns) => ns.into(), + Move(i,_) => *i, + SetZLevel(i,_) => *i, + } + } +} + +pub struct PrepareUpdatesBuffer<'r> { + g : &'r mut Instance, + us : Vec, + gen : Generation, + by_client : ClientId, + cseq : ClientSequence, +} + +impl<'r> PrepareUpdatesBuffer<'r> { + pub fn new(g: &'r mut Instance, by_client: ClientId, cseq: ClientSequence, + estimate: usize) -> Self + { + g.gs.gen.increment(); + PrepareUpdatesBuffer { + us: Vec::with_capacity(estimate), + gen: g.gs.gen, + g, by_client, cseq, + } + } + + pub fn piece_update(&mut self, piece: PieceId, update: PieceUpdateOp<(),()>, + lens: &dyn Lens) { + let gs = &mut self.g.gs; + + let update = match gs.pieces.byid_mut(piece) { + Some(pc) => { + if self.by_client != pc.lastclient { + pc.gen_before_lastclient = pc.gen; + pc.lastclient = self.by_client; + } + pc.gen = self.gen; + eprintln!("PC GEN_LC={:?} LC={:?}", pc.gen, pc.lastclient); + + let pri_for_all = lens.svg_pri(piece,pc,Default::default()); + + let update = update.try_map( + |_|{ + let mut ns = pc.prep_piecestate(&pri_for_all)?; + lens.massage_prep_piecestate(&mut ns); + >::Ok(ns) + }, + |_|{ + >::Ok(pri_for_all.id) + }, + )?; + + update + }, + None => { + PieceUpdateOp::Delete(lens.make_piece_visible(piece)) + } + }; + + self.us.push(PreparedUpdateEntry::Piece { + client : self.by_client, + sameclient_cseq : self.cseq, + op : update, + }); + } + + pub fn log_updates(&mut self, logents: Vec) { + for logentry in logents { + let logentry = Arc::new(logentry); + self.g.gs.log.push((self.gen, logentry.clone())); + self.us.push(PreparedUpdateEntry::Log(logentry)); + } + } +} + +impl<'r> Drop for PrepareUpdatesBuffer<'r> { + fn drop(&mut self) { + let update = PreparedUpdate { gen: self.gen, us: self.us.take(), }; + let update = Arc::new(update); + eprintln!("UPDATE {:?}", &update); + + for (_tplayer, tplupdates) in &mut self.g.updates { + tplupdates.log.push_back(update.clone()); + tplupdates.cv.notify_all(); } } } -- 2.30.2