Skip to content

feat(chat): optimistic local echo + moderation delivery notices (v1) - #12

Open
ChronoFinale wants to merge 2 commits into
Balatro-Multiplayer:mainfrom
ChronoFinale:feat/chat-moderation-v1
Open

feat(chat): optimistic local echo + moderation delivery notices (v1)#12
ChronoFinale wants to merge 2 commits into
Balatro-Multiplayer:mainfrom
ChronoFinale:feat/chat-moderation-v1

Conversation

@ChronoFinale

Copy link
Copy Markdown
Contributor

What

Client half of the chat-moderation v1 rollout — pairs with the relay bridge PR (Balatro-Multiplayer/BalatroMultiplayerAPI-Server#40):

  • Optimistic local echo — the sender's message renders instantly on enter; the MQTT self-echo is dropped so it never double-renders. Recipients are unaffected (they only ever receive the moderated form).
  • "not delivered" — if moderation blocks the message, the sender's echo is replaced with a notice that other players never saw it.
  • "delivered as …" — if moderation rewrote it, the sender sees exactly what was delivered (the relay returns publishText in the /chat response).
  • MPAPI.chat.mute_player local mute, bridge-guarded: the aggregate mute signal only fires when the v2 intake bridge exists, so on the v1 relay it's a clean local-only mute.

With the relay's MODERATION_SERVICE_URL unset, all of this degrades gracefully — messages just deliver as they do today.

Stacking

⚠️ Depends on #10 (api_client FIFO fix) — this branch is stacked on it, so the diff currently shows both. Review the last two commits only; once #10 merges I'll rebase and this collapses to just the chat work.

Testing

Tested end-to-end in-game against the live moderation service through the relay bridge: instant echo, block notice, rewrite notice ("suck my cock" → delivered as: suck my cocktail), and preset messages surviving a simulated moderation outage.

Sender sees their message instantly; the MQTT self-echo is dropped to avoid
double-render. A moderation block replaces the echo with a "not delivered to
other players" notice; a rewrite shows "delivered as ..." using the relay's
publishText. Matches the forward-only v1 relay (POST /:code/chat only).
mute_player called MPAPI._internal.mute_signal unconditionally, but the intake
bridge only ships with the v2 moderation UX — on the v1 tree the field is nil
and any caller would crash. Local mute works either way; the signal fires only
when the bridge exists.
@ChronoFinale
ChronoFinale force-pushed the feat/chat-moderation-v1 branch from 82a7715 to 4c07484 Compare July 23, 2026 23:48
@ChronoFinale
ChronoFinale marked this pull request as ready for review July 23, 2026 23:53
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