diff options
| author | metamuffin <metamuffin@disroot.org> | 2025-10-20 20:58:14 +0200 |
|---|---|---|
| committer | metamuffin <metamuffin@disroot.org> | 2025-10-21 00:18:11 +0200 |
| commit | eaed442578c3b1765ec48c84489a122096b6a08f (patch) | |
| tree | bd5eeb82ea6f49691a4c5bad91a1b1614f0948a8 | |
| parent | a3b0879a98bf5a0881b426913d7dd4cb9010e327 (diff) | |
| download | hurrycurry-eaed442578c3b1765ec48c84489a122096b6a08f.tar hurrycurry-eaed442578c3b1765ec48c84489a122096b6a08f.tar.bz2 hurrycurry-eaed442578c3b1765ec48c84489a122096b6a08f.tar.zst | |
Send paths as debug events
| -rw-r--r-- | server/bot/Cargo.toml | 1 | ||||
| -rw-r--r-- | server/bot/src/algos/customer.rs | 5 | ||||
| -rw-r--r-- | server/bot/src/pathfinding.rs | 26 | ||||
| -rw-r--r-- | server/bot/src/step.rs | 26 | ||||
| -rw-r--r-- | server/protocol/src/lib.rs | 13 | ||||
| -rw-r--r-- | test-client/main.ts | 8 | ||||
| -rw-r--r-- | test-client/protocol.ts | 10 | ||||
| -rw-r--r-- | test-client/visual.ts | 24 |
8 files changed, 95 insertions, 18 deletions
diff --git a/server/bot/Cargo.toml b/server/bot/Cargo.toml index 8a841843..64b0f028 100644 --- a/server/bot/Cargo.toml +++ b/server/bot/Cargo.toml @@ -13,4 +13,5 @@ rustls = { version = "0.23.31", features = ["ring"] } clap = { version = "4.5.47", features = ["derive"] } [features] +# default = ["debug_events"] debug_events = [] diff --git a/server/bot/src/algos/customer.rs b/server/bot/src/algos/customer.rs index 6ae67f69..fa10410b 100644 --- a/server/bot/src/algos/customer.rs +++ b/server/bot/src/algos/customer.rs @@ -180,6 +180,8 @@ impl CustomerState { *self = CustomerState::Exiting { path }; } } else { + #[cfg(feature = "debug_events")] + out.push(PacketS::Debug(path.debug(me))); out.push(PacketS::Movement { player: me, dir: path.next_direction(pos, dt) * 0.6, @@ -380,6 +382,7 @@ impl CustomerState { hand: Hand(0), }); } + out.push(PacketS::Movement { player: me, dir: (table.as_vec2() + 0.5) - pos, @@ -393,6 +396,8 @@ impl CustomerState { debug!("{me:?} -> leave"); *self = CustomerState::Exited } else { + #[cfg(feature = "debug_events")] + out.push(PacketS::Debug(path.debug(me))); out.push(PacketS::Movement { player: me, dir: path.next_direction(pos, dt) * 0.6, diff --git a/server/bot/src/pathfinding.rs b/server/bot/src/pathfinding.rs index ec098495..5c5551dd 100644 --- a/server/bot/src/pathfinding.rs +++ b/server/bot/src/pathfinding.rs @@ -16,7 +16,12 @@ */ use hurrycurry_game_core::Game; -use hurrycurry_protocol::glam::{IVec2, Vec2}; +#[cfg(feature = "debug_events")] +use hurrycurry_protocol::{DebugEvent, PlayerID}; +use hurrycurry_protocol::{ + DebugEventDisplay, + glam::{IVec2, Vec2}, +}; use log::{debug, trace}; use std::{ cmp::Ordering, @@ -57,6 +62,25 @@ impl Path { pub fn remaining_segments(&self) -> usize { self.segments.len() } + + #[cfg(feature = "debug_events")] + pub fn debug(&self, id: PlayerID) -> DebugEvent { + use std::f32::consts::TAU; + + use hurrycurry_protocol::glam::Vec3; + let a = id.0 as f32; + DebugEvent { + key: format!("path-{id}"), + color: Vec3::new( + (a + TAU / 3. * 0.).sin(), + (a + TAU / 3. * 1.).sin(), + (a + TAU / 3. * 2.).sin(), + ), + display: DebugEventDisplay::Path { + points: self.segments.clone(), + }, + } + } } pub fn find_path_to_neighbour(game: &Game, from: IVec2, to: IVec2) -> Option<Path> { diff --git a/server/bot/src/step.rs b/server/bot/src/step.rs index 001935ac..34793466 100644 --- a/server/bot/src/step.rs +++ b/server/bot/src/step.rs @@ -26,7 +26,8 @@ use hurrycurry_protocol::{Hand, ItemIndex, ItemLocation, PacketS, PlayerID, glam pub struct StepState { path: Path, interact_position: IVec2, - destination_item: Option<ItemIndex>, + item_expected: Option<ItemIndex>, + item_current: Option<ItemIndex>, hand: Hand, wait_timer: f32, interact_start_pending: bool, @@ -40,12 +41,13 @@ impl StepState { } pub fn new_wait(me: PlayerID, timer: f32) -> Self { Self { - destination_item: None, + item_expected: None, interact_position: IVec2::ZERO, hand: Hand(0), interact_start_pending: false, interact_stop_pending: false, me, + item_current: None, path: Path::EMPTY, wait_timer: timer, } @@ -59,6 +61,10 @@ impl StepState { ) -> Option<Self> { let own_pos = game.players.get(&me)?.movement.position.as_ivec2(); let path = find_path_to_neighbour(game, own_pos, pos)?; + let destination_item = game + .tiles + .get(&pos) + .and_then(|t| t.item.as_ref().map(|i| i.kind)); Some(Self { me, path, @@ -67,15 +73,14 @@ impl StepState { interact_stop_pending: true, interact_start_pending: true, interact_position: pos, - destination_item: game - .tiles - .get(&pos) - .and_then(|t| t.item.as_ref().map(|i| i.kind)), + item_expected: destination_item, + item_current: None, }) } pub fn is_busy(&self) -> bool { self.wait_timer >= 0. || self.interact_stop_pending + // && self.item_current == self.item_expected } pub fn tick(&mut self, out: &mut PacketSink, game: &Game, dt: f32) { @@ -103,6 +108,11 @@ impl StepState { } } + self.item_current = game + .tiles + .get(&self.interact_position) + .and_then(|t| t.item.as_ref().map(|i| i.kind)); + let position = game .players .get(&self.me) @@ -111,6 +121,10 @@ impl StepState { .unwrap_or_default(); let dir = self.path.next_direction(position, dt); + + #[cfg(feature = "debug_events")] + out.push(PacketS::Debug(self.path.debug(self.me))); + out.push(PacketS::Movement { player: self.me, dir, diff --git a/server/protocol/src/lib.rs b/server/protocol/src/lib.rs index a89d9c30..2d9aa0f0 100644 --- a/server/protocol/src/lib.rs +++ b/server/protocol/src/lib.rs @@ -16,7 +16,7 @@ */ use crate::book::Book; -use glam::{IVec2, Vec2}; +use glam::{IVec2, Vec2, Vec3}; use helpers::deser::*; use serde::{Deserialize, Serialize}; use std::{ @@ -381,12 +381,13 @@ pub enum ItemLocation { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct DebugEvent { - key: String, - display: Vec<DebugEventDisplay>, - timeout: Option<f32>, + pub key: String, + pub color: Vec3, + pub display: DebugEventDisplay, } #[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "snake_case", tag = "ty")] pub enum DebugEventDisplay { - Path(Vec<Vec2>), - Label(Vec2, String), + Path { points: Vec<Vec2> }, + Label { pos: Vec2, text: String }, } diff --git a/test-client/main.ts b/test-client/main.ts index fd2e733a..091e0535 100644 --- a/test-client/main.ts +++ b/test-client/main.ts @@ -20,7 +20,7 @@ import { init_locale } from "./locale.ts"; import { MovementBase, collide_player_player, update_movement } from "./movement.ts"; import { particle_splash, tick_particles } from "./particles.ts"; -import { Gamedata, ItemIndex, ItemLocation, Message, MessageTimeout, PacketC, PacketS, PlayerClass, PlayerID, Score, TileIndex } from "./protocol.ts"; +import { DebugEvent, Gamedata, ItemIndex, ItemLocation, Message, MessageTimeout, PacketC, PacketS, PlayerClass, PlayerID, Score, TileIndex } from "./protocol.ts"; import { V2, lerp_exp_v2_mut, normalize, lerp_exp } from "./util.ts"; import { draw_ingame, draw_wait } from "./visual.ts"; @@ -116,6 +116,7 @@ export const players = new Map<PlayerID, PlayerData>() export const tiles = new Map<string, TileData>() export const items_removed = new Set<ItemData>() export const server_hints = new Map<string, MessageData>() +export const debug_events: Map<string, DebugEvent & { timeout: number }> = new Map() export let data: Gamedata = { item_names: [], @@ -158,7 +159,7 @@ function send(p: PacketS) { ws.send(JSON.stringify(p)) } function packet(p: PacketC) { - if (!["movement", "update_map"].includes(p.type)) + if (!["movement", "update_map", "debug"].includes(p.type)) console.log(p); switch (p.type) { case "version": @@ -334,6 +335,9 @@ function packet(p: PacketC) { default: console.warn("unknown menu"); } break; + case "debug": + debug_events.set(p.key, { timeout: 0.1, ...p }) + break; default: console.warn("unknown packet", p); } diff --git a/test-client/protocol.ts b/test-client/protocol.ts index b43646a9..d0789376 100644 --- a/test-client/protocol.ts +++ b/test-client/protocol.ts @@ -74,6 +74,7 @@ export type PacketC = | { type: "tutorial_ended", item: ItemIndex, player: PlayerID, success: boolean } | { type: "set_ingame", state: boolean, lobby: boolean } // Set to false when entering the game or switching maps | { type: "pause", state: boolean } // Set game paused so clients dont increment timers + | { type: "debug" } & DebugEvent // Set game paused so clients dont increment timers export interface Character { color: number, @@ -153,3 +154,12 @@ export type NodeStyle = | "process_active" | "process_passive" | "process_instant" + +export interface DebugEvent { + key: string, + color: [number, number, number] + display: DebugEventDisplay +} +export type DebugEventDisplay = + { ty: "path", points: Vec2[] } + | { ty: "label", pos: Vec2, text: string }
\ No newline at end of file diff --git a/test-client/visual.ts b/test-client/visual.ts index d75f90f5..20bd7ae2 100644 --- a/test-client/visual.ts +++ b/test-client/visual.ts @@ -16,7 +16,7 @@ */ import { tr } from "./locale.ts"; -import { ItemData, MessageData, MessageStyle, PlayerData, TileData, camera, camera_scale, canvas, ctx, data, get_interact_target, global_message, interact_active_anim, interact_possible_anim, interact_target_anim, is_lobby, items_removed, keys_down, my_id, overlay_vis_anim, players, score, server_hints, tiles } from "./main.ts"; +import { ItemData, MessageData, MessageStyle, PlayerData, TileData, camera, camera_scale, canvas, ctx, data, debug_events, get_interact_target, global_message, interact_active_anim, interact_possible_anim, interact_target_anim, is_lobby, items_removed, keys_down, my_id, overlay_vis_anim, players, score, server_hints, tiles } from "./main.ts"; import { PLAYER_SIZE } from "./movement.ts"; import { draw_item_sprite, draw_tile_sprite, ItemName, TileName } from "./tiles.ts"; import { V2, ceil_v2, floor_v2 } from "./util.ts"; @@ -78,6 +78,8 @@ export function draw_ingame() { for (const [_, message] of server_hints) draw_message(message, true) + draw_debug_events() + ctx.restore() ctx.save() ctx.translate(50, 50) @@ -94,7 +96,23 @@ export function draw_ingame() { draw_score() if (keys_down.has("KeyP")) - draw_debug() + draw_info_overlay() +} + +function draw_debug_events() { + for (const ev of debug_events.values()) { + if (ev.display.ty == "path") { + ctx.lineWidth = 0.1 + ctx.lineCap = "round" + ctx.strokeStyle = `rgb(${ev.color[0] * 100}%,${ev.color[1] * 100}%,${ev.color[2] * 100}%)` + ctx.beginPath() + if (ev.display.points.length) + ctx.moveTo(...ev.display.points[0]) + for (let i = 1; i < ev.display.points.length; i++) + ctx.lineTo(...ev.display.points[i]) + ctx.stroke() + } + } } function draw_score() { @@ -110,7 +128,7 @@ function draw_score() { ctx.fillText(`${tr("c.score.demands_failed")}: ${score.demands_failed}`, 10, canvas.height - 10) } -function draw_debug() { +function draw_info_overlay() { ctx.fillStyle = "white" ctx.textAlign = "left" ctx.textBaseline = "bottom" |