diff --git a/server/src/manager/data.rs b/server/src/manager/data.rs index 0799e8b..43abb54 100644 --- a/server/src/manager/data.rs +++ b/server/src/manager/data.rs @@ -336,6 +336,39 @@ pub async fn thread_system(mut app:App, bus:Bus) QRPacketData::QAuthRevoke => { println!("Request: Auth Revoke"); + // Remove connection from chain. + if let Some(conn) = app.connections.get(qr.id as usize).cloned() { + if let Some(auth_id) = conn.auth { + if let Some(auth) = app.auths.get(&auth_id).cloned() { + + // Update user connection reference. + if let Some(user) = app.get_user_by_id_mut(auth.user) { + if Some(qr.id) == user.connection { + + // Set connection to next if exists. + if conn.next != qr.id { + user.connection = Some(conn.next); + } else { + user.connection = None; + } + } + } + + // Link prev and next connections. + if conn.next != qr.id { + if let Some(prev_conn) = app.connections.get_mut(conn.prev as usize) { + prev_conn.next = conn.next; + } + + if let Some(next_conn) = app.connections.get_mut(conn.next as usize) { + next_conn.prev = conn.prev; + } + } + } + } + } + + // Remove authentication from connection. if let Some(conn) = app.connections.get_mut(qr.id as usize) { match conn.auth { Some(auth) => { @@ -346,6 +379,7 @@ pub async fn thread_system(mut app:App, bus:Bus) } conn.auth = None; } + Some(QRPacket::new(0, QRPacketData::None)) } @@ -376,7 +410,9 @@ pub async fn thread_system(mut app:App, bus:Bus) else if Some(session.p_dusk.user) == user_id { 2 } else { 0 } } else { 0 }; + let is_turn = player != 0 && (session.game.turn & 1) == player as u16 - 1; + let is_complete = (session.game.is_complete() as u8) * (((session.game.turn & 1) == 0) as u8 + 1); let dawn_handle = if let Some(user) = app.get_user_by_id(session.p_dawn.user) { user.handle.clone() @@ -397,6 +433,7 @@ pub async fn thread_system(mut app:App, bus:Bus) viewers:session.connections.len() as u32, player, is_turn, + is_complete, }); count += 1; @@ -739,6 +776,7 @@ pub async fn thread_system(mut app:App, bus:Bus) if let Some(user) = app.get_user_by_id(uid) { response.records.push(PacketUserListData { handle:user.handle.clone(), + is_online:user.connection.is_some(), }); } } diff --git a/server/src/protocol/packet/session_list.rs b/server/src/protocol/packet/session_list.rs index 4c31577..4434ec5 100644 --- a/server/src/protocol/packet/session_list.rs +++ b/server/src/protocol/packet/session_list.rs @@ -61,6 +61,7 @@ pub struct PacketSessionListResponseRecord { pub viewers:u32, pub player:u8, pub is_turn:bool, + pub is_complete:u8, } #[derive(Clone)] @@ -88,6 +89,7 @@ impl Packet for PacketSessionListResponse { let mut flags = 0u32; flags |= record.player as u32; flags |= (record.is_turn as u32) << 2; + flags |= (record.is_complete as u32) << 3; // Flags chunk.append(&mut pack_u32(flags)); diff --git a/server/src/protocol/packet/user_list.rs b/server/src/protocol/packet/user_list.rs index fb3d41b..0a6a4d2 100644 --- a/server/src/protocol/packet/user_list.rs +++ b/server/src/protocol/packet/user_list.rs @@ -5,6 +5,7 @@ use super::Packet; #[derive(Clone)] pub struct PacketUserListData { pub handle:String, + pub is_online:bool, } #[derive(Clone)] @@ -33,6 +34,11 @@ impl Packet for PacketUserListResponse { for record in &self.records { let mut chunk = Vec::new(); + // Flags + let mut flags = 0u8; + flags |= record.is_online as u8; + chunk.append(&mut pack_u8(flags)); + // Handle let mut bytes = record.handle.as_bytes().to_vec(); chunk.append(&mut pack_u8(bytes.len() as u8)); diff --git a/www/css/util.css b/www/css/util.css index 4ea3e23..d292e9e 100644 --- a/www/css/util.css +++ b/www/css/util.css @@ -1,4 +1,6 @@ span.text-system{color:#909090;} +span.c_dawn{color:#ffe082;} +span.c_dusk{color:#f6a1bd;} button#button-resign.warn { background-color:#471414; diff --git a/www/js/scene.js b/www/js/scene.js index 9257698..a558255 100644 --- a/www/js/scene.js +++ b/www/js/scene.js @@ -856,8 +856,13 @@ const SCENES = { callback = callback.bind({handle: data.users[r].handle}); buttons.push(UI.button(LANG("challenge"), callback)); + let handle = UI.text(data.users[r].handle); + if(!data.users[r].is_online) { + handle = UI.span([handle], "text-system"); + } + rows.push([ - UI.text(data.users[r].handle), + handle, UI.text(LANG("unranked")), buttons, ]); diff --git a/www/js/system.js b/www/js/system.js index 3f7cbc3..60bff3a 100644 --- a/www/js/system.js +++ b/www/js/system.js @@ -160,6 +160,7 @@ function MESSAGE(event) { viewers: 0, player: false, is_turn: false, + is_complete: 0, }; // Token @@ -177,6 +178,7 @@ function MESSAGE(event) { record.player = flags & 3; record.is_turn = ((flags >> 2) & 1) != 0; + record.is_complete = ((flags >> 3) & 3); // Dawn handle result = UNPACK.string(bytes, index); @@ -378,8 +380,15 @@ function MESSAGE(event) { for(let i = 0; i < length; ++i) { let record = { handle:"", + is_online:false, }; + // Flags + result = UNPACK.u8(bytes, index); + index = result.index; + let flags = result.data; + record.is_online = (flags & 1) == 1; + // Handle result = UNPACK.string(bytes, index, UNPACK.u8); index = result.index; diff --git a/www/js/ui.js b/www/js/ui.js index c55f824..7f228ec 100644 --- a/www/js/ui.js +++ b/www/js/ui.js @@ -363,6 +363,11 @@ const UI = { let dawn = UI.text(records[r].dawn); let dusk = UI.text(records[r].dusk); + switch(records[r].is_complete) { + case 1: dawn = UI.span([dawn], "c_dawn"); break; + case 2: dusk = UI.span([dusk], "c_dusk"); break; + } + rows.push([ dawn, dusk,