Skip to content

Paper 26.2 line: in-game fixes, agent snapshot bridge, spawn immunity and MySQL reconnect - #104

Merged
biels merged 7 commits into
masterfrom
worktree/graceful-game-end
Sep 6, 2026
Merged

Paper 26.2 line: in-game fixes, agent snapshot bridge, spawn immunity and MySQL reconnect#104
biels merged 7 commits into
masterfrom
worktree/graceful-game-end

Conversation

@biels

@biels biels commented Sep 6, 2026

Copy link
Copy Markdown
Owner

Summary

Brings the line the Paper 26.2 server is built from onto master. Until now it lived only on one machine. It continues worktree/paper-26.2-migration at 718fbcc and adds:

  • RainbowClay agent snapshot bridge (61eae52, 5556eb4): a loopback HTTP endpoint that publishes the match snapshot a bot needs to play, including the bot's own potion effect durations.
  • In-game stability and balance fixes (0e15c1a): graceful game finalization and resilient match persistence, bounded asynchronous timestamp writes, runtime-world cleanup, Quakecraft and RainbowClay exception fixes, Torres, Arena 4, InkWars and Parkour gameplay fixes. This is the content of In-game stability and balance fixes #103 rebased onto the agent bridge.
  • /minicatstart (10c01c3): a command path to the same handler as the blaze-rod start button, so canBeStartedBy and host privileges apply unchanged.
  • Spawn immunity clears regardless of movement direction (e6a968f): the signed-delta test left players immune for a whole life when they only moved in -X/-Z; in Quakecraft it also broke the railgun victim chain. Affects all games.
  • RainbowClay snapshot period and TTL widened (0a349fe) to 40 ticks / 15000 ms so a model turn fits inside a snapshot's life.
  • MySQL reconnect (ab68dea): an idle connection closed by the server was never replaced, getAvgGameLength answered 0, and the progress announcer printed Long.MAX_VALUE / 10 as a percentage. Each link in that chain is fixed.

Deployment state

The live server runs the 2026-08-10 build, which is 0e15c1a plus the content of 10c01c3 and 0a349fe. e6a968f and ab68dea are built and verified locally but not deployed yet. Builds are reproducible: ab68dea builds to sha256 3d27b9a0….

Relation to open PRs

CI

The Java CI job fails on every branch of this repository for one reason: BielAPI:BielAPI:0.0.10-SNAPSHOT is resolved from the local Maven cache and is not available to the runner. It is not a compile failure.

biels added 7 commits August 5, 2026 07:51
Component J4. The snapshot described the bot's position, health and inventory
but not the effects acting on it, so the bot could not see the spawn window it
was standing in.

That window changes what the correct opening is. Spawn grants Strength 3 for 5s,
Resistance 1 for ~19s, Absorption 5, Haste for 30s and Slowness 1 for the first
3s. An engagement inside the strength window is favourable in a way it will not
be forty seconds later, and the reflex tier cannot know that without remaining
durations.

Published for the self player only, alongside inventory, since effects on other
players are not something the bot is entitled to read. Durations are milliseconds
rather than ticks so nothing downstream has to know Minecraft's tick rate, and an
infinite effect reports -1. Levels are one-based as the game displays them rather
than Bukkit's zero-based amplifier.

This also makes the effectActive atom admissible, which it was not before.
Routes to Joc.iniciarCommand, the same handler behind the blaze-rod
"Inicia la partida" button, so canBeStartedBy and host privileges apply
unchanged. An agent driving a real client cannot reliably trigger an
inventory button, so a command gives it the same authority by a path
that works.
The test compared signed deltas, so a player who only moved in -X/-Z, or
only ever turned one way, never cleared immunity. It is set on every
respawn, which left players unkillable for a whole life depending on
which way they happened to face; in Quakecraft it also broke the railgun
victim chain, which skips immune players. Affects all games.
100 ticks / 7500 ms capped the usable decision budget at 6750 ms, since a
bot refuses a snapshot with less than its budget of life left - a live
match discarded every reply the model produced. Now 40 ticks / 15000 ms.
Safe because the snapshot carries only slow state: rosters, objective
positions, phase. Fast state reaches the bot through its own client.
…7580%

A connection left idle past wait_timeout (eight hours) is closed by the
server but stays non-null in the field, and repairConnection only reopened
a null one. So once the connection aged out it was never replaced and every
query threw for the rest of the process's life.

getAvgGameLength answered that failure with 0, and Joc.getGameProgressETA
divides elapsed time by it. Zero makes the quotient Infinity, and
Math.round(Infinity) is Long.MAX_VALUE, which the announcer divides by 10
and prints: the reported figure is exactly Long.MAX_VALUE / 10.

One change per link in that chain. repairConnection now asks the connection
whether it is valid and replaces it when it is not. getAvgGameLength treats
an unusable database, and a game with no finished matches, as unknown - half
an hour - rather than instant. Both getGameProgressETA implementations
refuse to divide by a zero reference.

Parkour has 354 finished matches averaging 132s, so the live reading came
from the dead connection, not from missing history.
@biels
biels merged commit a157ccc into master Sep 6, 2026
1 check failed
@biels
biels deleted the worktree/graceful-game-end branch September 6, 2026 20:14
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