From 97a1ba2fc4b08ea8411d29f76419e4e5ddac09b3 Mon Sep 17 00:00:00 2001 From: yukirij Date: Sat, 5 Oct 2024 00:04:37 -0700 Subject: [PATCH] Add online user tracking and notification. --- server/src/app/session.rs | 5 +++ server/src/manager/data.rs | 65 ++++++++++++++++++++++++++++++++++++-- www/js/interface.js | 12 +++++-- 3 files changed, 77 insertions(+), 5 deletions(-) diff --git a/server/src/app/session.rs b/server/src/app/session.rs index b24d843..548c46f 100644 --- a/server/src/app/session.rs +++ b/server/src/app/session.rs @@ -74,4 +74,9 @@ impl Session { } } } + + pub fn spectators(&self) -> usize + { + self.connections.len() + } } diff --git a/server/src/manager/data.rs b/server/src/manager/data.rs index d942143..c4b52fd 100644 --- a/server/src/manager/data.rs +++ b/server/src/manager/data.rs @@ -474,6 +474,8 @@ pub async fn thread_system(mut app:App, bus:Bus) QRPacketData::QSessionView(request) => { println!("Request: Session Join"); + let mut packets = Vec::::new(); + let mut response = PacketSessionViewResponse::new(); response.status = STATUS_ERROR; response.token = request.token; @@ -498,6 +500,16 @@ pub async fn thread_system(mut app:App, bus:Bus) if Some(session.p_dawn.user) == user_id || Some(session.p_dusk.user) == user_id { println!("User resumes session."); response.status = STATUS_OK; + + for (cid, _) in session.get_connections() { + packets.push(QRPacket::new( + cid, + QRPacketData::GameMessage(PacketGameMessage { + data: GameMessageData::Online(1 + (Some(session.p_dusk.user) == user_id) as u8, 1), + }), + )); + } + true } else { false } } else { response.status = STATUS_NOAUTH; false } @@ -506,8 +518,18 @@ pub async fn thread_system(mut app:App, bus:Bus) // Join game as spectator. else { println!("User spectates session."); - response.status = STATUS_OK; + + // 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), + }), + )); + } + true } { // Associate session and connection on join @@ -525,6 +547,11 @@ pub async fn thread_system(mut app:App, bus:Bus) } } + // Send notification packets + for packet in packets { + app.send_response(packet).await; + } + Some(QRPacket::new(qr.id, QRPacketData::RSessionView(response))) } @@ -575,15 +602,47 @@ pub async fn thread_system(mut app:App, bus:Bus) QRPacketData::QSessionLeave => { println!("Request: Session Leave"); + let mut packets = Vec::::new(); + // Verify that session exists. if let Some(session_token) = session_id { if let Some(session) = app.sessions.get_mut(&session_token) { - if user_id == Some(session.p_dawn.user) { session.remove_connection(0, qr.id); } - else if user_id == Some(session.p_dusk.user) { session.remove_connection(1, qr.id); } + if user_id == Some(session.p_dawn.user) { + session.remove_connection(0, qr.id); + + if session.p_dawn.connections.len() == 0 { + for (cid, _) in session.get_connections() { + packets.push(QRPacket::new( + cid, + QRPacketData::GameMessage(PacketGameMessage { + data: GameMessageData::Online(1, 0), + }), + )); + } + } + } + else if user_id == Some(session.p_dusk.user) { + session.remove_connection(1, qr.id); + + if session.p_dawn.connections.len() == 0 { + for (cid, _) in session.get_connections() { + packets.push(QRPacket::new( + cid, + QRPacketData::GameMessage(PacketGameMessage { + data: GameMessageData::Online(2, 0), + }), + )); + } + } + } else { session.remove_connection(2, qr.id); } } } + for packet in packets { + app.send_response(packet).await; + } + Some(QRPacket::new(0, QRPacketData::None)) } diff --git a/www/js/interface.js b/www/js/interface.js index 2beb52f..fec510d 100644 --- a/www/js/interface.js +++ b/www/js/interface.js @@ -643,7 +643,11 @@ const INTERFACE = { if(INTERFACE_DATA.Session.Client.Dawn.handle !== null) { let pos = handle_pos[(1 ^ INTERFACE_DATA.player ^ INTERFACE_DATA.rotate) & 1]; - ctx.fillStyle = INTERFACE.Color.Dawn; + if(INTERFACE_DATA.Session.Client.Dawn.online) { + ctx.fillStyle = INTERFACE.Color.Dawn; + } else { + ctx.fillStyle = INTERFACE.Color.DawnDark; + } ctx.textBaseline = "middle"; ctx.textAlign = "center"; ctx.fillText(INTERFACE_DATA.Session.Client.Dawn.handle, pos.x, pos.y); @@ -652,7 +656,11 @@ const INTERFACE = { if(INTERFACE_DATA.Session.Client.Dusk.handle !== null) { let pos = handle_pos[(INTERFACE_DATA.player ^ INTERFACE_DATA.rotate) & 1]; - ctx.fillStyle = INTERFACE.Color.Dusk; + if(INTERFACE_DATA.Session.Client.Dusk.online) { + ctx.fillStyle = INTERFACE.Color.Dusk; + } else { + ctx.fillStyle = INTERFACE.Color.DuskDark; + } ctx.textBaseline = "middle"; ctx.textAlign = "center"; ctx.fillText(INTERFACE_DATA.Session.Client.Dusk.handle, pos.x, pos.y);