Skip to content

feat: improved debuff control and prepared games#15

Open
jooakar wants to merge 18 commits intomainfrom
improved-debuff-control
Open

feat: improved debuff control and prepared games#15
jooakar wants to merge 18 commits intomainfrom
improved-debuff-control

Conversation

@jooakar
Copy link
Copy Markdown
Collaborator

@jooakar jooakar commented Mar 13, 2026

Summary

  • Next Round Panel: new side panel to prepare the next round before launching — select puzzle, configure initial debuffs (applied to all players on launch), and build a minigame debuff pool (available debuffs for audience challenges, currently not sent to the backend)
  • Active Debuffs Panel: real-time view of all currently active debuffs per player with live countdown timers; supports clearing individual debuffs, all debuffs for one player, all debuffs globally, or a single debuff type across all players
  • "All players" option added to the debuff selector for bulk administration
  • Infinite duration: dragging the duration slider to the max shows ∞ and sends duration=0, which the backend treats as ~1 year; displayed as ∞ in both player and admin views
  • Debuffs cleared on puzzle switch: switching puzzles (manually or via Launch Round) clears all active debuffs for all players
  • Backend clear_debuff command and launch_round command added
  • Debuff updates now broadcast to all admins regardless of spectate selection

fixes #13, fixes #14

@jooakar jooakar self-assigned this Mar 13, 2026
Copilot AI review requested due to automatic review settings March 13, 2026 18:26
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds new admin UX and backend support for round preparation and debuff management (apply to all, clear active debuffs, and “infinite” duration handling), plus ensures debuffs are reset on puzzle switches.

Changes:

  • Extend admin protocol with launch_round and clear_debuff, and implement corresponding backend handlers.
  • Add new admin panels: “Active Debuffs” (view/clear) and “Prepare Next Round” (select puzzle + initial debuffs).
  • Update debuff UI to support “All players” targeting and an ∞ duration display/sentinel.

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
frontend/src/player/DebuffSelector.tsx Add “All players” option and encode ∞ duration via duration=0.
frontend/src/player/DebuffQueue.tsx Display ∞ for long durations.
frontend/src/admin/SpectatorController.ts Treat empty debuff lists as a clear signal for spectators.
frontend/src/admin/NextRoundPanel.tsx New UI to select next puzzle and configure initial debuffs for round launch.
frontend/src/admin/adminState.ts Add new admin command types and PreparedDebuff type.
frontend/src/admin/Admin.tsx Integrate new admin panels into the dashboard layout.
frontend/src/admin/ActiveDebuffsPanel.tsx New UI to view active debuffs per player and issue clear commands.
frontend/package-lock.json Lockfile regeneration changes.
backend/main.py Implement infinite-duration sentinel, clear-debuff command, launch-round command, spectator debuff broadcasting, and debuff resets on puzzle switch.
Files not reviewed (1)
  • frontend/package-lock.json: Language not supported
Comments suppressed due to low confidence (2)

frontend/src/player/DebuffQueue.tsx:12

  • formatDuration returns "∞" for any debuff with > 1 hour remaining. Debuff durations can legitimately exceed an hour (e.g. repeated stacking in administer_debuff accumulates duration), so this will mislabel long-but-finite debuffs as infinite. Consider detecting infinity via a much higher threshold aligned with the server sentinel (e.g. ~1 year), or having the server explicitly mark infinite debuffs.
function formatDuration(ms: number): string {
  if (ms > 3_600_000) return "∞";
  const total = Math.max(0, Math.ceil(ms / 1000));
  const m = Math.floor(total / 60);
  const s = total % 60;
  return `${m}:${s.toString().padStart(2, "0")}`;

backend/main.py:756

  • Broadcasting spectate_debuffs to all admins (even when they are not spectating a player) means controllers can accumulate incremental debuff updates. When an admin later starts spectating a player, the server also sends a full debuff snapshot (debuffs_json) for that player, and the client-side updateDebuffs logic merges rather than replaces—this can lead to duplicate debuff entries. To avoid this, consider clearing before sending snapshot debuffs (send an empty debuffs message first) or introducing a distinct "replace debuffs" message type for snapshots.
        data = json.dumps(converted)
        for admin in self.admins.values():
            if converted["type"] in ("spectate_state", "spectate_debuffs") or admin.is_spectating(player_name):
                try:
                    # TODO: use queue tasks like with players
                    asyncio.create_task(admin.ws.send(data, True))
                except Exception:

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 49 to 55
type: "administer_debuff",
players: [selectedPlayer],
players: selectedPlayer === "*" ? (players ?? []) : [selectedPlayer],
name: selectedName,
debuff_type: info.type,
strength,
duration,
duration: duration === 120 ? 0 : duration,
});
Comment thread frontend/src/admin/NextRoundPanel.tsx Outdated
Comment thread frontend/src/admin/NextRoundPanel.tsx Outdated
Comment thread frontend/src/admin/ActiveDebuffsPanel.tsx Outdated
Comment thread frontend/src/admin/ActiveDebuffsPanel.tsx Outdated
Comment thread backend/main.py Outdated
Comment on lines +1003 to +1014
elif msg["type"] == "administer_debuff":
if error := manager.administer_debuff(msg):
await send(ws, error)
elif msg["type"] == "clear_debuff":
player_names = msg.get("players")
name = msg.get("name")
targets = list(manager.players.keys()) if player_names == "all" else player_names
for player_name in targets:
manager.clear_debuff(player_name, name)
elif msg["type"] == "launch_round":
puzzle_id = msg["puzzle"]
initial_debuffs = msg.get("initial_debuffs", [])
Comment thread backend/main.py Outdated
Comment on lines +1020 to +1021
debuff_cmd["players"] = list(manager.players.keys())
manager.administer_debuff(debuff_cmd)
PurkkaKoodari and others added 4 commits March 13, 2026 20:52
also adds UI functionality for the prepared game's debuff pool. currently does nothing as minigames have not been implemented
@PurkkaKoodari PurkkaKoodari force-pushed the improved-debuff-control branch from a5aacee to cbab814 Compare March 13, 2026 22:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow admins to assign debuffs to one team or all teams via UI Implement admin UI for preparing next round

4 participants