From: Ian Jackson Date: Sun, 28 Jun 2020 19:04:07 +0000 (+0100) Subject: wip update protocol X-Git-Tag: otter-0.2.0~1508 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=58308c2f8eee8eb1b53b32605ac121609ec6602b;p=otter.git wip update protocol --- diff --git a/junk/gamestate.rs b/junk/gamestate.rs index 7c23ad3c..ef9b2193 100644 --- a/junk/gamestate.rs +++ b/junk/gamestate.rs @@ -9,13 +9,6 @@ impl Deref for GameRef { fn deref(&self) -> &GameState { self.0.read() } } -enum GameUpdate { - NoUpdate, - PieceInsert(usize, PieceRecord), - PieceDelete(usize, PieceRecord), - PieceUpdate(usize, PieceRecord, PieceRecord), -} - struct LogMessage (HtmlString); impl PieceRecord { diff --git a/src/bin/server.rs b/src/bin/server.rs index 4fcd6c84..9e6af503 100644 --- a/src/bin/server.rs +++ b/src/bin/server.rs @@ -115,6 +115,7 @@ fn session(form : Json) -> Result { #[derive(Error,Debug)] #[error("operation error {:?}",self)] enum OpError { + Conflict, PieceGone, PieceHeld, } @@ -122,18 +123,50 @@ enum OpError { #[derive(Debug,Serialize,Deserialize)] struct ApiGrab { t : String, + c : ClientId, p : VisiblePieceId, + g : Counter, + s : ClientSequence, } #[post("/_/api/grab", format="json", data="
")] #[throws(RE)] fn api_grab(form : Json) -> impl response::Responder<'static> { let iad = lookup_token(&form.t).ok_or_else(||anyhow!("unknown token"))?; let mut g = iad.i.lock().map_err(|e| anyhow!("lock poison {:?}",&e))?; + let client = form.c; let r : Result<(),OpError> = (||{ let p = decode_visible_pieceid(form.p); - let p = g.gs.pieces.get_mut(p).ok_or(OpError::PieceGone)?; + let gs = &mut g.gs; + let p = gs.pieces.get_mut(p).ok_or(OpError::PieceGone)?; + let q_gen = form.g; + let u_gen = + if client == p.lastclient { p.gen_lastclient } + else { p.gen_before_lastclient }; + if p.gen > u_gen { Err(OpError::Conflict)? } if p.held != None { Err(OpError::PieceHeld)? }; p.held = Some(iad.player); + gs.gen += 1; + let gen = gs.gen; + if client != p.lastclient { + p.gen_before_lastclient = p.gen_lastclient; + p.lastclient = client; + } + p.gen_lastclient = gen; + for (tplayer, tpl) in g.gs.players { + for (tclient, cl) in ig.clients.get(tplayer) { + if tclient == cl { + cl.transmit_update(client, Update { + gen, + u : GameUpdate::ClientSequence(form.s) + }); + } else { + cl.transmit_update(client, Update { + gen, + u : GameUpdate::PieceUpdate(p, p.update()), + }); + } + } + } Ok(()) })(); eprintln!("API {:?} => {:?}", &form, &r); diff --git a/src/gamestate.rs b/src/gamestate.rs index 7eca3e8e..3d07b1c6 100644 --- a/src/gamestate.rs +++ b/src/gamestate.rs @@ -48,6 +48,9 @@ pub struct PieceRecord { pub p : Box, pub face : FaceId, pub held : Option, + pub lastclient : ClientId, + pub gen_lastclient : Counter, + pub gen_before_lastclient : Counter, } #[derive(Debug)] @@ -69,6 +72,7 @@ pub fn xxx_gamestate_init() -> GameState { pos, p, face : 0.into(), held : None, + gen : 0, }; pieces.insert(pr); } diff --git a/src/updates.rs b/src/updates.rs new file mode 100644 index 00000000..674ad79c --- /dev/null +++ b/src/updates.rs @@ -0,0 +1,13 @@ + +struct Update { + gen : Counter, + u : UpdatePayload, +} + +enum UpdatePayload { + NoUpdate, + ClientSequence(ClientCounter), + PieceDelete(PieceId), + PieceInsert(PieceId, PieceUpdate), + PieceUpdate(PieceId, PieceUpdate), +} diff --git a/templates/script.js b/templates/script.js index 42e45568..6734939a 100644 --- a/templates/script.js +++ b/templates/script.js @@ -8,6 +8,7 @@ var our_dnd_type = "text/puvnex-game-server-dummy"; api_queue = []; api_posting = false; var us; +var gen = 0; function xhr_post_then(url,data,good) { var xhr = new XMLHttpRequest(); @@ -95,6 +96,7 @@ function drag_mousedown(e) { set_grab(delt, us); api('grab', { t : token, + g : gen, p : delt.dataset.p, }) }