Skip to content

Fix list_players and get_player_position hanging forever#3

Open
ChadRM wants to merge 1 commit into
Metrakit:mainfrom
ChadRM:fix/list-players-get-player-position-hang
Open

Fix list_players and get_player_position hanging forever#3
ChadRM wants to merge 1 commit into
Metrakit:mainfrom
ChadRM:fix/list-players-get-player-position-hang

Conversation

@ChadRM

@ChadRM ChadRM commented Jul 2, 2026

Copy link
Copy Markdown

Summary

Fixes the hang reported in #2 for list_players and get_player_position.

Both handlers called Universe.get().getPlayers() / PlayerRef.getTransform() directly on the Jetty request thread instead of hopping onto the world thread via world.execute(), unlike every other stateful feature (get_world_info, give_item, set_block, etc). They also used stale types (List<PlayerRef> instead of Collection<PlayerRef>, and fully-qualified Vector3d/Vector3f types that no longer exist) that don't match the current HytaleServer API:

  • Universe.getPlayers() returns Collection<PlayerRef>, not List<PlayerRef>
  • Transform.getPosition() returns org.joml.Vector3d, not com.hypixel.hytale.math.vector.Vector3d
  • Transform.getRotation() returns com.hypixel.hytale.math.vector.Rotation3f, not Vector3f

Because the outer catch only caught Exception, the resulting NoSuchMethodError/NoClassDefFoundError from this API mismatch was silently swallowed by whatever thread ran the sync tool handler, without ever completing the MCP SDK's response future. That left HttpServletStreamableServerTransportProvider.doPost's Mono.block() blocked forever, with zero server-side log output — indistinguishable from a network-level hang.

Root cause (confirmed via thread dump)

A jstack thread dump taken mid-hang showed every stuck request parked at:

at reactor.core.publisher.Mono.block(Mono.java:1779)
at io.modelcontextprotocol.server.transport.HttpServletStreamableServerTransportProvider.doPost(HttpServletStreamableServerTransportProvider.java:487)
at com.top_serveurs.hytale.plugins.mcp.McpServlet.handleStreamable(McpServlet.java:125)

Compiling the plugin against the actual live HytaleServer.jar (rather than whatever version it was originally built against) reproduced the API mismatch directly as compile errors, confirming the root cause.

Test plan

  • mvn test — all 9 existing tests pass
  • mvn package — builds cleanly against the live server's actual HytaleServer.jar and nitrado-webserver.jar
  • Deployed to a live server and verified end-to-end:
    • list_players with 0 players connected: {"count":0,"players":[]} (previously hung forever)
    • list_players with 1 player connected: returns correct player list
    • get_player_position for a connected player: returns correct live x/y/z/yaw/pitch

🤖 Generated with Claude Code

Both handlers called Universe.get().getPlayers()/PlayerRef.getTransform()
directly on the Jetty request thread instead of hopping onto the world
thread via world.execute(), unlike every other stateful feature
(get_world_info, give_item, set_block, etc). They also used stale types
(List<PlayerRef> instead of Collection<PlayerRef>, and fully-qualified
Vector3d/Vector3f which no longer exist) that no longer match the live
HytaleServer API (getPlayers() returns Collection; Transform.getPosition()
returns org.joml.Vector3d; Transform.getRotation() returns Rotation3f).

Because the outer catch only caught Exception, the resulting
NoSuchMethodError/NoClassDefFoundError was swallowed by whatever thread
ran the sync tool handler without ever completing the MCP SDK's response
future, so HttpServletStreamableServerTransportProvider.doPost's
Mono.block() hung forever with no server-side log output at all.

Verified against a live server: both tools now return correctly instead
of timing out, with a connected player and with zero players.

Co-Authored-By: Claude Sonnet 5 <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