From 5497873189859ae88f8e421be92642ade621a45f Mon Sep 17 00:00:00 2001 From: yukirij Date: Sat, 5 Oct 2024 02:00:12 -0700 Subject: [PATCH] Add online user indicators; add spectator counter. --- server/src/manager/data.rs | 22 +++++++++++++--- server/src/protocol/packet/game_message.rs | 2 +- server/src/protocol/packet/game_state.rs | 11 +++++++- www/js/interface.js | 29 +++++++++++++++++++--- www/js/system.js | 12 ++++++++- 5 files changed, 66 insertions(+), 10 deletions(-) diff --git a/server/src/manager/data.rs b/server/src/manager/data.rs index c4b52fd..4d03451 100644 --- a/server/src/manager/data.rs +++ b/server/src/manager/data.rs @@ -525,7 +525,7 @@ pub async fn thread_system(mut app:App, bus:Bus) packets.push(QRPacket::new( cid, QRPacketData::GameMessage(PacketGameMessage { - data: GameMessageData::Online(0, session.spectators() as u32), + data: GameMessageData::Online(0, 1 + session.spectators() as u32), }), )); } @@ -624,7 +624,7 @@ pub async fn thread_system(mut app:App, bus:Bus) else if user_id == Some(session.p_dusk.user) { session.remove_connection(1, qr.id); - if session.p_dawn.connections.len() == 0 { + if session.p_dusk.connections.len() == 0 { for (cid, _) in session.get_connections() { packets.push(QRPacket::new( cid, @@ -635,7 +635,19 @@ pub async fn thread_system(mut app:App, bus:Bus) } } } - else { session.remove_connection(2, qr.id); } + else { + session.remove_connection(2, qr.id); + + // Add user online packets. + for (cid, _) in session.get_connections() { + packets.push(QRPacket::new( + cid, + QRPacketData::GameMessage(PacketGameMessage { + data: GameMessageData::Online(0, session.spectators() as u32), + }), + )); + } + } } } @@ -973,6 +985,10 @@ fn generate_game_state(app:&App, session:&Session) -> protocol::PacketGameStateR response.dusk_handle = user.handle.clone(); } + response.dawn_online = session.p_dawn.connections.len() > 0; + response.dusk_online = session.p_dusk.connections.len() > 0; + response.spectators = session.connections.len() as u32; + // Get history response.history = session.game.history.clone(); diff --git a/server/src/protocol/packet/game_message.rs b/server/src/protocol/packet/game_message.rs index 8abee51..f92eb7e 100644 --- a/server/src/protocol/packet/game_message.rs +++ b/server/src/protocol/packet/game_message.rs @@ -103,7 +103,7 @@ impl Packet for PacketGameMessage { } GameMessageData::Online(client, state) => { - GMSG_PLAY_ALT as u64 + GMSG_ONLINE as u64 | ((client as u64) << 8) | ((state as u64) << 10) } diff --git a/server/src/protocol/packet/game_state.rs b/server/src/protocol/packet/game_state.rs index a15efe3..cd734c9 100644 --- a/server/src/protocol/packet/game_state.rs +++ b/server/src/protocol/packet/game_state.rs @@ -1,6 +1,6 @@ use crate::{ app::session::SessionToken, - util::pack::pack_u16, + util::pack::{pack_u16, pack_u32}, }; use game::history::Play; @@ -45,6 +45,9 @@ pub struct PacketGameStateResponse { pub player:u8, pub dawn_handle:String, pub dusk_handle:String, + pub dawn_online:bool, + pub dusk_online:bool, + pub spectators:u32, pub history:Vec, } impl PacketGameStateResponse { @@ -56,6 +59,9 @@ impl PacketGameStateResponse { player:2, dawn_handle:String::new(), dusk_handle:String::new(), + dawn_online:false, + dusk_online:false, + spectators:0, history:Vec::new(), } } @@ -76,11 +82,14 @@ impl Packet for PacketGameStateResponse { let mut flags = 0u16; flags |= self.player as u16; + flags |= (self.dawn_online as u16) << 2; + flags |= (self.dusk_online as u16) << 3; [ pack_u16(self.status), self.token.to_vec(), pack_u16(flags), + pack_u32(self.spectators), pack_u16(self.dawn_handle.len() as u16), self.dawn_handle.as_bytes().to_vec(), pack_u16(self.dusk_handle.len() as u16), diff --git a/www/js/interface.js b/www/js/interface.js index fec510d..51f4722 100644 --- a/www/js/interface.js +++ b/www/js/interface.js @@ -21,11 +21,13 @@ const INTERFACE = { Promote: "#a52121", Dawn: "#ffe082", + DawnShade: "#a59154", DawnMedium: "#fca03f", DawnDark: "#ff6d00", DawnDarkest: "#4c3422", Dusk: "#f6a1bd", + DuskShade: "#a56b7f", DuskMedium: "#e84a79", DuskDark: "#c51162", DuskDarkest: "#4c2235", @@ -646,7 +648,7 @@ const INTERFACE = { if(INTERFACE_DATA.Session.Client.Dawn.online) { ctx.fillStyle = INTERFACE.Color.Dawn; } else { - ctx.fillStyle = INTERFACE.Color.DawnDark; + ctx.fillStyle = INTERFACE.Color.DawnShade; } ctx.textBaseline = "middle"; ctx.textAlign = "center"; @@ -659,7 +661,7 @@ const INTERFACE = { if(INTERFACE_DATA.Session.Client.Dusk.online) { ctx.fillStyle = INTERFACE.Color.Dusk; } else { - ctx.fillStyle = INTERFACE.Color.DuskDark; + ctx.fillStyle = INTERFACE.Color.DuskShade; } ctx.textBaseline = "middle"; ctx.textAlign = "center"; @@ -695,6 +697,12 @@ const INTERFACE = { ctx.textAlign = "right"; ctx.fillText(GAME_DATA.turn, width - gui_margin.t, gui_margin.t); + // Number of spectators + ctx.fillStyle = INTERFACE.Color.Text; + ctx.textBaseline = "bottom"; + ctx.textAlign = "right"; + ctx.fillText("👁" + INTERFACE_DATA.Session.Client.Spectators.count, width - gui_margin.t, height - gui_margin.t); + // Game state message let message = null; ctx.fillStyle = INTERFACE.Color.Text; @@ -1249,6 +1257,10 @@ const INTERFACE = { INTERFACE_DATA.Game.history = data.history; let turn = INTERFACE_DATA.Game.history.length; + INTERFACE_DATA.Session.Client.Dawn.online = data.dawn_online; + INTERFACE_DATA.Session.Client.Dusk.online = data.dusk_online; + INTERFACE_DATA.Session.Client.Spectators.count = data.spectators; + if(INTERFACE_DATA.Game.history.length > 0) { if(INTERFACE_DATA.Replay.turn == 0) { //if(INTERFACE_DATA.Game.history[INTERFACE_DATA.Game.history.length-1].source == 2) { @@ -1304,9 +1316,10 @@ const INTERFACE = { case 2: { // Dusk - INTERFACE_DATA.Session.Client.Dawn.online = (data.state != 0); + INTERFACE_DATA.Session.Client.Dusk.online = (data.state != 0); } break; } + INTERFACE.redraw(); } break; case GameMessage.Undo: { @@ -1322,11 +1335,11 @@ const INTERFACE = { INTERFACE.undo(); } break; } - } break; case GameMessage.Retire: { GAME_DATA.state.code = GAME.Const.State.Resign; + INTERFACE.redraw(); } break; case GameMessage.Reaction: { @@ -1338,6 +1351,14 @@ const INTERFACE = { } }, + redraw() { + if(INTERFACE_DATA !== null) { + if(INTERFACE_DATA.Timeout.draw === null) { + INTERFACE.draw(); + } + } + }, + process(play) { let valid = true; diff --git a/www/js/system.js b/www/js/system.js index 45b7a64..96137e1 100644 --- a/www/js/system.js +++ b/www/js/system.js @@ -265,6 +265,9 @@ function MESSAGE(event) { player:2, dawn:"", dusk:"", + dawn_online:false, + dusk_online:false, + spectators:0, history:[ ], }; @@ -282,6 +285,12 @@ function MESSAGE(event) { let flags = result.data; data.player = flags & 0x3; + data.dawn_online = (flags >> 2) & 1; + data.dusk_online = (flags >> 3) & 1; + + result = UNPACK.u32(bytes, index); + index = result.index; + data.spectators = result.data; // Handles result = UNPACK.string(bytes, index); @@ -351,7 +360,8 @@ function MESSAGE(event) { case GameMessage.Online: { data.client = dat & 0x3; - data.state = (dat & 0x4) != 0; + data.state = (dat >> 2) & 0xFFFF_FFFF; + console.log(data.client + " = " + data.state); } break; case GameMessage.Undo: {