Fix stale-message risk in async chat handling and shared-state bug in IslandChatCommand#61
Merged
Merged
Conversation
Closed
Copilot
AI
changed the title
[WIP] Fix repeating message in oneblock chat
Fix stale-message risk in async chat handling and shared-state bug in IslandChatCommand
Jul 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Island/team chat could repeat a previously sent message instead of the current one — reported specifically with OneBlock's
/ob chat, where every message after the first kept echoing the first message's text.Root cause
The classic trigger for this bug is deferring
AsyncPlayerChatEvent#getMessage()to a scheduled task (e.g.Bukkit.getScheduler().runTask(...)) instead of reading it synchronously in the handler. By the time the deferred task runs, the message content can no longer be trusted to reflect the current chat event.ChatListener.onChat()already captures the message value up front before dispatching work to the main thread viacallSyncMethod, which is the correct pattern — but this path had no test coverage, since existing tests only exercised the synchronous (isAsynchronous() == false) branch.Changes
onChatthrough the actual async branch with a stubbed scheduler, sending two consecutive messages ("aaaa" then "test") and asserting each is delivered with its own content rather than the previous one, for both island chat and team chat.IslandChatCommand: the resolvedIslandwas cached on an instance field set incanExecute()and read inexecute(). Since command instances are shared singletons across all players (not per-invocation), this risks one player's island leaking into another player'sexecute()call. Sibling commands (IslandTeamChatCommand,IslandTeamMuteCommand) avoid this by recomputing what they need directly insideexecute();IslandChatCommandnow follows the same pattern: