Skip to content

Tell Companion what the game plays and its packs on events, not by polling - #86

Merged
Pelotrio merged 3 commits into
1.21.1from
claude/game-events
Sep 29, 2026
Merged

Pelotrio merged 3 commits into
1.21.1from
claude/game-events

Conversation

@Pelotrio

Copy link
Copy Markdown
Member

What

The game no longer checks once a second what it plays and which packs are enabled. It tells Companion when the game's own events change them:

Told When
PLAYING LoggingIn (the level and player exist) / LoggingOut (before teardown)
Resource packs A client resource reload applies; a new selection only takes effect through one
Singleplayer datapacks The server's tags arrive on the client after a data load or reload (/reload, /datapack, Companion's own)
Packs the game could enable The pack screen closes, and after each reload or pack selection Companion asks for
Both again After PLAYING changes, and when Companion connects

Why it's better

  • A rejoin is a change by construction. Leave is Menu, join is the server. The forced Menu send from A2 layer 2: one relay for every server operation #81 is simply how it works now.
  • No bogus state during teardown. While a singleplayer world closes, the game keeps ticking until its server stops. By then it has already cleared the server but not yet the level, so the old poll could report a server with an empty address.
  • No lag: Companion hears the change in the same tick.
  • ResourceReloads.tick is gone. A rolled-back reload is failed when the recovery reload reaches the reload listener.

Cleanup

  • ChangePublisher and its test are removed. PLAYING is one field of TotalDebugClient, and PackStackPublisher keeps its own last-told value.
  • PLAYING drops the LAN flag (an opened world is the same world) and the permission level (nothing read it; the server answers permission questions, as SERVER_SCRIPTS does). Protocol 34.
  • Join, leave, reload, tag and pack-screen events live together in ClientLifecycleEvents. ClientTickTaskEvents only drains tick tasks.
  • Docs: GAME_LOCATION.md gains the event table; MOD_SIDES.md and RESOURCE_EDITING.md no longer describe polling or the permission level.

Not covered

A proxy that moves the player to another backend (reconfiguration) fires no LoggingOut, only a new LoggingIn. PLAYING then changes only if the backend's TotalDebug channel differs. Before, the poll noticed this only by chance.

Tests

  • :protocol:test passes (68).
  • :mod:test passes (208).
  • The Companion suites touching PLAYING pass: GameState, ConfigChanges, PackSelections, ResourceEdits, ConfigPanel, CompanionReconnect and ApplicationNavigation (107).
  • The event wiring needs an in-game check:
    • join and leave;
    • a quick rejoin;
    • switching resource packs;
    • a failed resource reload;
    • /datapack disable;
    • adding a pack folder and then closing the pack screen.

🤖 Generated with Claude Code

…lling

What the game plays is told when the player joins (LoggingIn) or leaves
(LoggingOut); the packs when a client resource reload applies, when the
server's tags arrive after a data reload, when the pack screen closes, and
after each reload or pack selection Companion asks for. Nothing is sampled
once a second any more: a rejoin is a change by construction, the capture
cannot land mid-teardown, and Companion hears a change in the same tick.

- The rolled-back reload is detected as the recovery reload applies, from
  the reload listener, instead of on ticks.
- ChangePublisher goes: PLAYING is one field of TotalDebugClient, and the
  pack stack keeps its own last-told value.
- PLAYING drops the LAN flag and the permission level, which nothing read;
  the server answers permission questions itself. Protocol 34.
- Join, leave, reload, tag and pack-screen events live together in
  ClientLifecycleEvents.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-29T07:47:26.032711Z 7ca13fe New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8efe240227

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

/** Tells Companion what the game plays, then the packs, which Companion reads for what it plays. Client thread only. */
private void tellPlaying() {
this.companionApp.sendPlaying(new PlayingMessage(this.playing));
this.packStacks.republish();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Defer the pack republish until the integrated server is gone

When leaving a singleplayer world, LoggingOut runs before the integrated server is torn down, so this immediate republish captures and sends the departed world's datapacks immediately after sending Menu. Companion associates that stack with the menu, and PackResources.data treats any non-null stack as authoritative, leaving the old world's data resources visible indefinitely because no event republishes after server shutdown. Suppress datapacks when publishing the menu or defer this republish until the integrated server is gone.

AGENTS.md reference: AGENTS.md:L7-L7

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Not reproducible on 1.21.1: Minecraft.disconnect sets this.singleplayerServer = null and only then calls ClientHooks.firePlayerLogout (the only LoggingOut site). So when left() republishes, getSingleplayerServer() is already null and the stack carries no datapacks. The same holds while disconnect waits for the server to stop. I added a comment on left() that names this ordering.

Pelotrio and others added 2 commits September 29, 2026 09:32
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Pelotrio
Pelotrio merged commit d0cea8a into 1.21.1 Sep 29, 2026
Pelotrio added a commit that referenced this pull request Sep 29, 2026
)

The game tells PLAYING again after each handshake (#86), on top of what
GameLocation.connected() already replays, so listeners reloaded their
view once more with the same result. The first point of #78.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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