From c5e8e6aa2b55a5d71d6d75bf12dac61ac3809d1c Mon Sep 17 00:00:00 2001 From: yukirij Date: Sat, 17 Aug 2024 14:50:53 -0700 Subject: [PATCH] Add practice mode and last play hints. --- server/src/manager/data.rs | 3 + server/src/protocol/packet/game_state.rs | 10 +++- server/src/system/filesystem/mod.rs | 4 +- www/.html | 2 +- www/js/interface.js | 70 +++++++++++++++++------- www/js/scene.js | 24 +++++++- www/js/system.js | 16 ++++-- www/js/ui.js | 1 + 8 files changed, 100 insertions(+), 30 deletions(-) diff --git a/server/src/manager/data.rs b/server/src/manager/data.rs index a2a8487..3435fd1 100644 --- a/server/src/manager/data.rs +++ b/server/src/manager/data.rs @@ -597,6 +597,9 @@ fn generate_gamestate(app:&App, session:&Session) -> protocol::PacketGameStateRe response.player = 2; response.turn = session.game.turn; + if session.game.history.len() > 0 { + response.play = session.game.history[session.game.history.len() - 1]; + } // Get Dawn handle if let Some(id) = session.p_dawn.user { diff --git a/server/src/protocol/packet/game_state.rs b/server/src/protocol/packet/game_state.rs index b4ae755..3cf1c0a 100644 --- a/server/src/protocol/packet/game_state.rs +++ b/server/src/protocol/packet/game_state.rs @@ -3,7 +3,7 @@ use crate::{ util::pack::pack_u16, }; -use game::game::Pool; +use game::{game::Pool, history::Play}; use super::Packet; @@ -65,6 +65,7 @@ pub struct PacketGameStateResponse { pub status:u16, pub turn:u16, pub player:u8, + pub play:Play, pub dawn_handle:String, pub dusk_handle:String, pub dawn_pool:Pool, @@ -78,6 +79,7 @@ impl PacketGameStateResponse { status:0, turn:0, player:0, + play:Play::new(), dawn_handle:String::new(), dusk_handle:String::new(), dawn_pool:Pool::default(), @@ -94,6 +96,11 @@ impl Packet for PacketGameStateResponse { let mut flags = 0u16; flags |= self.player as u16; + let mut play = 0; + play |= self.play.source as u16; + play |= (self.play.from as u16) << 1; + play |= (self.play.to as u16) << 7; + let mut piece_bytes = Vec::new(); for piece in &self.pieces { let piece_data: u16 = piece.valid as u16 @@ -124,6 +131,7 @@ impl Packet for PacketGameStateResponse { [ pack_u16(self.status), pack_u16(flags), + pack_u16(play), pack_u16(self.turn), pack_u16(self.dawn_handle.len() as u16), self.dawn_handle.as_bytes().to_vec(), diff --git a/server/src/system/filesystem/mod.rs b/server/src/system/filesystem/mod.rs index c73f0dd..5f13fc9 100644 --- a/server/src/system/filesystem/mod.rs +++ b/server/src/system/filesystem/mod.rs @@ -271,9 +271,7 @@ impl FileSystem { to:((data >> 7) & 0x3F) as u8, }); } - - println!("len {}", result.len()); - + Ok(result) } else { Err(()) } } diff --git a/www/.html b/www/.html index 88845bf..a52b463 100644 --- a/www/.html +++ b/www/.html @@ -5,7 +5,7 @@ - + diff --git a/www/js/interface.js b/www/js/interface.js index 3ee09db..abd268f 100644 --- a/www/js/interface.js +++ b/www/js/interface.js @@ -189,13 +189,24 @@ const INTERFACE = { } if(is_valid) { - let move_data = INTERFACE_DATA.select.source | (INTERFACE_DATA.select.tile << 1) | (INTERFACE_DATA.hover.tile << 7); - MESSAGE_COMPOSE([ - PACK.u16(OpCode.GamePlay), - PACK.u16(0), - PACK.u16(GAME_DATA.turn), - PACK.u16(move_data), - ]); + if(INTERFACE_DATA.online) { + let move_data = INTERFACE_DATA.select.source | (INTERFACE_DATA.select.tile << 1) | (INTERFACE_DATA.hover.tile << 7); + MESSAGE_COMPOSE([ + PACK.u16(OpCode.GamePlay), + PACK.u16(0), + PACK.u16(GAME_DATA.turn), + PACK.u16(move_data), + ]); + } else { + let play = new GAME.Play(INTERFACE_DATA.select.source, INTERFACE_DATA.select.tile, INTERFACE_DATA.hover.tile); + INTERFACE_DATA.play = play; + GAME_DATA.process(play); + + INTERFACE_DATA.player = +(!INTERFACE_DATA.player); + INTERFACE_DATA.rotate = +(!INTERFACE_DATA.rotate); + + INTERFACE.draw(); + } INTERFACE_DATA.select = null; } else { INTERFACE_DATA.select = null; @@ -339,7 +350,9 @@ const INTERFACE = { case 1: ctx.fillStyle = INTERFACE.Color.TileLight; break; case 2: ctx.fillStyle = INTERFACE.Color.TileDark; break; } - if(GAME_DATA.state.check && piece !== null && piece.piece == GAME.Const.PieceId.Omen && piece.player == (GAME_DATA.turn & 1)) { + if(GAME_DATA.turn > 0 && (INTERFACE_DATA.play.to == i || (INTERFACE_DATA.play.source == 0 && INTERFACE_DATA.play.from == i))) { + ctx.fillStyle = INTERFACE.Color.HintPlay; + } else if(GAME_DATA.state.check && piece !== null && piece.piece == GAME.Const.PieceId.Omen && piece.player == (GAME_DATA.turn & 1)) { ctx.fillStyle = INTERFACE.Color.HintCheck; } switch(tile_state) { @@ -657,16 +670,25 @@ const INTERFACE = { }, }, - init(data) { + init(data, online) { GAME.init(); + let token = null; + let player = 0; + if(data !== null) { + token = data.token; + player = data.mode; + } + INTERFACE_DATA = { - token:data.token, + online: online, + + token: token, canvas: document.getElementById("game"), context: null, - player: data.mode, + player: player, rotate: 0, hover: null, @@ -674,6 +696,7 @@ const INTERFACE = { handles: [null, null], board_state: [ ], + play: null, Ui: { scale: 0, @@ -696,17 +719,23 @@ const INTERFACE = { canvas.addEventListener("mousedown", INTERFACE.click); window.addEventListener("resize", INTERFACE.draw); - MESSAGE_COMPOSE([ - PACK.u16(OpCode.GameState), - INTERFACE_DATA.token, - ]); + if(INTERFACE_DATA.online) { + MESSAGE_COMPOSE([ + PACK.u16(OpCode.GameState), + INTERFACE_DATA.token, + ]); + } else { + INTERFACE.draw(); + } } }, uninit() { - MESSAGE_COMPOSE([ - PACK.u16(OpCode.SessionLeave), - ]); + if(INTERFACE_DATA.online) { + MESSAGE_COMPOSE([ + PACK.u16(OpCode.SessionLeave), + ]); + } if(INTERFACE_DATA !== null) { MAIN.removeChild(INTERFACE_DATA.canvas); @@ -717,9 +746,9 @@ const INTERFACE = { message(code, data) { switch(code) { case OpCode.GameState: { - console.log(data.player); INTERFACE_DATA.player = data.player; GAME_DATA.turn = data.turn; + INTERFACE_DATA.play = data.play; if(data.dawn.length > 0) { INTERFACE_DATA.handles[0] = data.dawn; } if(data.dusk.length > 0) { INTERFACE_DATA.handles[1] = data.dusk; } @@ -747,7 +776,8 @@ const INTERFACE = { case OpCode.GamePlay: { if(data.status == Status.Ok && data.turn == GAME_DATA.turn) { - GAME_DATA.process(data.move); + INTERFACE_DATA.play = data.play; + GAME_DATA.process(data.play); INTERFACE.draw(); } } break; diff --git a/www/js/scene.js b/www/js/scene.js index c527828..9141f1d 100644 --- a/www/js/scene.js +++ b/www/js/scene.js @@ -488,7 +488,7 @@ const SCENES = { canvas.setAttribute("id", "game"); MAIN.appendChild(canvas); - INTERFACE.init(data); + INTERFACE.init(data, true); return true; }, @@ -510,6 +510,28 @@ const SCENES = { } }, }, + + GamePractice:{ + load(data) { + let buttons_bottom = [ ]; + buttons_bottom.push(UI.button("Back", () => { LOAD(SCENES.Browse) })); + + UI.nav([ + UI.button("Rotate", () => { INTERFACE.rotate(); }), + ], buttons_bottom); + + let canvas = document.createElement("canvas"); + canvas.setAttribute("id", "game"); + MAIN.appendChild(canvas); + + INTERFACE.init(data, false); + + return true; + }, + unload() { + INTERFACE.uninit(); + }, + }, }; function LOAD(scene, data=null) { diff --git a/www/js/system.js b/www/js/system.js index 3590e07..45b8d85 100644 --- a/www/js/system.js +++ b/www/js/system.js @@ -207,6 +207,7 @@ function MESSAGE(event) { status:0, player:2, turn:0, + play:new GAME.Play(), dawn:"", dusk:"", pool_dawn:[ ], @@ -226,6 +227,13 @@ function MESSAGE(event) { data.player = flags & 0x3; + // Last Play + result = UNPACK.u16(bytes, index); + index = result.index; + data.play.source = result.data & 1; + data.play.from = (result.data >> 1) & 0x3F; + data.play.to = (result.data >> 7) & 0x3F; + // Turn result = UNPACK.u16(bytes, index); index = result.index; @@ -290,7 +298,7 @@ function MESSAGE(event) { data = { status:0, - move:new GAME.Play(0, 0, 0), + play:new GAME.Play(0, 0, 0), }; // Status @@ -306,9 +314,9 @@ function MESSAGE(event) { // Play description result = UNPACK.u16(bytes, index); index = result.index; - data.move.source = result.data & 1; - data.move.from = (result.data >> 1) & 0x3F; - data.move.to = (result.data >> 7) & 0x3F; + data.play.source = result.data & 1; + data.play.from = (result.data >> 1) & 0x3F; + data.play.to = (result.data >> 7) & 0x3F; } break; default: diff --git a/www/js/ui.js b/www/js/ui.js index 6d3f9f2..793d1e9 100644 --- a/www/js/ui.js +++ b/www/js/ui.js @@ -121,6 +121,7 @@ const UI = { } top.push(UI.button("Live", () => { LOAD(SCENES.Live); })); top.push(UI.button("History", () => { LOAD(SCENES.History); })); + top.push(UI.button("Practice", () => { LOAD(SCENES.GamePractice); })); top.push(UI.button("Guide", () => { LOAD(SCENES.Guide); })); top.push(UI.button("About", () => { LOAD(SCENES.About); }));