From d50cbd513c7208cb2a5c13571a964544b9470017 Mon Sep 17 00:00:00 2001 From: metamuffin Date: Tue, 4 Jun 2024 21:53:00 +0200 Subject: show chat and winners --- src/spectate/index.html | 1 + src/spectate/main.ts | 21 +++++++++++++++++++++ src/spectate/mod.rs | 20 +++++++++++++++++++- src/spectate/server.rs | 6 ++++-- src/spectate/style.css | 16 ++++++++++++++++ 5 files changed, 61 insertions(+), 3 deletions(-) (limited to 'src/spectate') diff --git a/src/spectate/index.html b/src/spectate/index.html index 5b9dc5a..0c86aec 100644 --- a/src/spectate/index.html +++ b/src/spectate/index.html @@ -44,6 +44,7 @@

Chat

+
diff --git a/src/spectate/main.ts b/src/spectate/main.ts index 508ca30..3fcf414 100644 --- a/src/spectate/main.ts +++ b/src/spectate/main.ts @@ -7,6 +7,8 @@ type Packet = "tick" | { game: { width: number, height: number } } | { player: { id: number, name: string } } | { die: number[] } + | { win: [number, number] } + | { chat: string } class Snake { parts: { x: number, y: number, dx: number, dy: number }[] = [] @@ -132,15 +134,34 @@ ws.onmessage = message => { } else if ("game" in p) { snakes.clear() size = p.game.width + } else if ("win" in p) { + const winner = snakes.get(p.win[0])?.name; + if (winner) chat(`${winner} won this round.`, "win") + else chat(`round ended in a tie.`, "tie") } else if ("player" in p) { snakes.set(p.player.id, new Snake(p.player.name)) } else if ("pos" in p) { snakes.get(p.pos.id)?.add_part(p.pos.x, p.pos.y) } else if ("die" in p) { + chat(`${p.die.map(e => snakes.get(e)?.name).join(", ")} died.`, "die") for (const d of p.die) { const s = snakes.get(d) if (s) s.dead = true } + } else if ("chat" in p) { + chat(p.chat) } } +const chat_history: HTMLElement[] = []; +function chat(message: string, clas = "chat") { + const e = document.createElement("p") + e.textContent = message; + e.classList.add("message") + e.classList.add(clas) + document.getElementById("chat_messages")!.prepend(e) + chat_history.push(e); + while (chat_history.length > 64) { + chat_history.splice(0, 1).forEach(e => e.remove()) + } +} diff --git a/src/spectate/mod.rs b/src/spectate/mod.rs index f80551e..3da4a0d 100644 --- a/src/spectate/mod.rs +++ b/src/spectate/mod.rs @@ -1,5 +1,6 @@ +use crate::State; use serde::Deserialize; -use std::net::SocketAddr; +use std::{net::SocketAddr, sync::Arc}; pub mod server; @@ -7,3 +8,20 @@ pub mod server; pub struct Config { bind: SocketAddr, } + +async fn stats_loop(state: Arc) { + let mut ticks = state.tick.subscribe(); + while let Ok(end) = ticks.recv().await { + if let Some(winner) = end { + if let Some(winner) = winner { + if let Some(winner) = state.players.write().await.get(&winner).cloned() { + let mut h = state.win_history.write().await; + h.push_front(winner); + while h.len() > 64 { + h.pop_back(); + } + } + } + } + } +} diff --git a/src/spectate/server.rs b/src/spectate/server.rs index 11c4d5a..0f51c2a 100644 --- a/src/spectate/server.rs +++ b/src/spectate/server.rs @@ -1,5 +1,5 @@ use super::Config; -use crate::{game::protocol::Packet, State}; +use crate::{game::protocol::Packet, spectate::stats_loop, State}; use anyhow::{anyhow, Result}; use axum::{ extract::{ @@ -26,6 +26,7 @@ struct SpectateState { } pub async fn spectate_server(config: Config, state: Arc) -> Result<()> { + spawn(stats_loop(state.clone())); let sstate = Arc::new(SpectateState { past_events: Default::default(), events: broadcast::channel(512).0, @@ -115,7 +116,8 @@ async fn broadcaster(sstate: Arc, state: Arc) { { let g = state.game.read().await; events.push(Packet::Tick); - if new_game { + if let Some(winner) = new_game { + events.push(Packet::Win(winner.unwrap_or(u32::MAX) as usize, 0)); // TODO packet misuse sstate.past_events.write().await.clear(); events.push(Packet::Game { my_id: 0, diff --git a/src/spectate/style.css b/src/spectate/style.css index c391020..5d15e9a 100644 --- a/src/spectate/style.css +++ b/src/spectate/style.css @@ -41,3 +41,19 @@ canvas { height: 40%; overflow-y: scroll; } + +.message { + margin: 2px; +} +.message.chat { + color: rgb(187, 187, 187); +} +.message.die { + color: rgb(255, 136, 136); +} +.message.win { + color: rgb(138, 255, 128); +} +.message.tie { + color: rgb(255, 221, 128); +} -- cgit v1.2.3-70-g09d2