Skip to content

feat: server-driven banned/approved mod policy#28

Draft
ChronoFinale wants to merge 1 commit into
Balatro-Multiplayer:mainfrom
ChronoFinale:feat/mod-policy
Draft

feat: server-driven banned/approved mod policy#28
ChronoFinale wants to merge 1 commit into
Balatro-Multiplayer:mainfrom
ChronoFinale:feat/mod-policy

Conversation

@ChronoFinale

@ChronoFinale ChronoFinale commented Jun 17, 2026

Copy link
Copy Markdown

What this adds

Server-driven banned/approved mod policy. The server keeps the policy in memory and sends it to a client when it joins/creates a lobby, so the client can colour opponents' mods red (banned) / green (approved) / white (unknown) — and staff can update the lists without a mod release.

This is the game-server piece. The admin UI + source of truth is a companion PR to www (adds GET /api/mod-policy); the client rendering is a companion PR to BalatroMultiplayer.

How it works

  • modPolicy.ts — in-memory { banned, approved } with get/set. At boot it loads an optional mod_policy.json fallback, else a minimal hardcoded default. fetchRemotePolicy() pulls the normalized { mods: [...] } array from <BALATROMP_BASE_URL>/api/mod-policy.
  • main.ts — a background poll refreshes the cached policy on an interval (no restart). The admin setModPolicy command updates it live and broadcasts to clients in lobbies.
  • actionHandlers.tssendModPolicy on lobby create / join / rejoin.
  • actions.ts — the setModPolicy server→client action type.

The website is the source of truth: staff edit the lists there; the server polls and caches.

Config (.env.example)

  • BALATROMP_BASE_URL — defaults to production; override to http://localhost:3000 for local dev.
  • MOD_POLICY_REFRESH_MS — poll interval (default 5 min, min 5 s).
  • MOD_POLICY_TOKEN — optional bearer token if the endpoint is ever gated.

mod_policy.json is gitignored — it's only a local offline fallback.

Verification

  • tsc clean.
  • End-to-end locally: edit list on the website → server poll picks it up (~5 s) → setModPolicy delivered to the client on lobby join.

@ChronoFinale ChronoFinale marked this pull request as draft June 17, 2026 12:24
@ChronoFinale ChronoFinale reopened this Jun 24, 2026
@ChronoFinale ChronoFinale force-pushed the feat/mod-policy branch 3 times, most recently from 877e001 to 1b2fe5a Compare June 24, 2026 13:53
Keeps a banned/approved mod policy in memory and sends it to a client when it
joins or creates a lobby, so the client can colour opponents' mods red (banned)
/ green (approved) / white (unknown) without a mod release.

- modPolicy.ts: in-memory policy with get/set; loads an optional mod_policy.json
  fallback at boot, else a minimal hardcoded default. fetchRemotePolicy() pulls
  the normalized { mods: [...] } array from <BALATROMP_BASE_URL>/api/mod-policy.
- main.ts: a background poll refreshes the cached policy without a restart; the
  admin `setModPolicy` command updates it live and broadcasts to lobby clients.
- actionHandlers.ts: sendModPolicy on lobby create/join/rejoin.
- actions.ts: ActionSetModPolicy type.
- .env.example documents BALATROMP_BASE_URL / refresh interval / optional token.

The website (Balatro-Multiplayer/www) is the source of truth — staff edit the
lists there and the server polls them.
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.

1 participant