Skip to content

Implement suspend command requirements and optimize packet handling#358

Merged
twisti-dev merged 14 commits into
version/26.1from
feat/async-command-requirement
May 27, 2026
Merged

Implement suspend command requirements and optimize packet handling#358
twisti-dev merged 14 commits into
version/26.1from
feat/async-command-requirement

Conversation

@twisti-dev
Copy link
Copy Markdown
Contributor

This pull request introduces a new system for suspending and conditionally blocking command packet sending to players, enabling asynchronous or conditional command requirements in the plugin. It adds an infrastructure for "suspendable" command requirements, implements packet blocking for command updates on two Minecraft versions, and provides test commands to demonstrate the new functionality. Additionally, it ensures the new listeners are registered in the plugin lifecycle.

Core infrastructure for suspendable command requirements:

  • Added SuspendRequirementServiceImpl as the implementation for SuspendRequirementService, providing coroutine-based, per-player, cacheable command requirements and managing the lifecycle of blocked command packets. It includes an event listener for command updates and connection closures, and registers a version-specific packet blocker listener.
  • Introduced CommandSendPacketBlockerListener abstract class, which tracks which players should have command packets blocked and exposes a method to remove them from the tracking set.
  • Updated NmsProvider interface to include a method for creating a CommandSendPacketBlockerListener for a set of blocked players.

Version-specific packet blocker implementations:

  • Implemented V1_21_11CommandSendPacketBlockerListenerImpl and V26_1CommandSendPacketBlockerListenerImpl, which intercept outgoing command packets and, for blocked players, send a placeholder "commands-are-loading" command tree instead. [1] [2]
  • Registered these implementations in their respective NmsProvider versions. [1] [2]

Integration and registration:

  • Registered the new event and packet listeners in the plugin's listener and packet API loader managers, ensuring proper lifecycle management. [1] [2]

Testing and demonstration:

  • Added SuspendRequirementTestCommand with subcommands to demonstrate and test the suspendable requirement system, including showing/hiding commands and a conditional command that is only available after a delay and if a condition is met.
  • Registered the new test command in the test plugin's command list.

Miscellaneous:

  • Bumped the project version to 3.16.0 in gradle.properties.

These changes collectively enable advanced, asynchronous command gating and improve the flexibility of command requirements in the plugin.

…ocking

- add CommandSendPacketBlockerListener for blocking commands to specific players
- create SuspendRequirementService for managing command execution requirements
- integrate new listener into existing event handling for command execution
- update NmsProvider to support new command blocking functionality
…uirement service

- ensure triggerRefreshForSender is called consistently for both adding and removing UUIDs
…pend requirement service

- streamline logic for adding and removing blocked command packets
- trigger refresh for sender only when a new packet is added
…ket handling

- implement SuspendRequirementTestCommand for testing suspend command requirements
- modify CommandSendPacketBlockerListener to manage received command packets
- update SuspendRequirementServiceImpl to provide command send packet blocker listener
@twisti-dev twisti-dev self-assigned this May 27, 2026
- implement withSuspendPlayerRequirement function to refresh command visibility
- cache requirement results for improved performance during command execution
@github-actions
Copy link
Copy Markdown
Contributor

⚠️ API/ABI changes detected!

This PR contains changes that modified the public API. To update the reference ABI dumps:

./gradlew updateKotlinAbi
git add **/api/**
git commit -m "Update ABI reference"
git push

After updating, the CI will pass. Make sure the changes are backward compatible.

…on logic

- add invalidate method to clear cached requirements for players
- invoke invalidate on player removal from blocked command packets
@github-actions
Copy link
Copy Markdown
Contributor

⚠️ API/ABI changes detected!

This PR contains changes that modified the public API. To update the reference ABI dumps:

./gradlew updateKotlinAbi
git add **/api/**
git commit -m "Update ABI reference"
git push

After updating, the CI will pass. Make sure the changes are backward compatible.

…istency

- update variable name in CommandSendPacketBlockerListener and its implementations
- ensure consistent naming across related classes and methods
…mmandPacket

- update variable name for clarity in CommandSendPacketBlockerListener
- adjust method names accordingly in SuspendRequirementServiceImpl
- ensure consistency in command packet handling across implementations
…escription

- update parameter description for allowIfNonPlayer to specify it bypasses player-only requirement
@twisti-dev twisti-dev marked this pull request as ready for review May 27, 2026 10:30
Copilot AI review requested due to automatic review settings May 27, 2026 10:30
Copy link
Copy Markdown

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

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: ef306f6fea

ℹ️ 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".

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds infrastructure for suspendable (coroutine-based) CommandAPI requirements on Paper, with per-player cached results refreshed asynchronously when the command tree is sent. To hide intermediate state from the client, a version-specific clientbound packet listener replaces the first ClientboundCommandsPacket for blocked players with a placeholder "commands-are-loading" tree and cancels subsequent packets until the async refresh completes.

Changes:

  • New public API withSuspendPlayerRequirement plus internal SuspendRequirementService and its SuspendRequirementServiceImpl (Caffeine caches, AsyncPlayerSendCommandsEvent / PlayerConnectionCloseEvent listeners).
  • New CommandSendPacketBlockerListener abstract base in NMS common and per-version implementations (v1_21_11, v26_1), wired through NmsProvider.createCommandSendPacketBlockerListener.
  • Listener/packet listener registration in ListenerManager and PacketApiLoader, plus a test subcommand and a version bump to 3.16.0.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
surf-api-paper/.../command/requirement/SuspendCommandRequirements.kt New public extension withSuspendPlayerRequirement with KDoc.
surf-api-paper/.../command/requirement/SuspendRequirementService.kt New @InternalSurfApi service interface and companion accessor.
surf-api-paper/.../command/SuspendRequirementServiceImpl.kt Service implementation: requirement caches, refresh coroutines, event listener.
surf-api-paper/.../listener/ListenerManager.kt Registers the new event listener on enable.
surf-api-paper/.../packet/PacketApiLoader.kt Registers the new command-send blocker packet listener on enable.
surf-api-paper-nms-common/.../NmsProvider.kt Adds createCommandSendPacketBlockerListener to provider interface.
surf-api-paper-nms-common/.../CommandSendPacketBlockerListener.kt New abstract base tracking first-packet state per player.
surf-api-paper-nms-v1-21-11/.../V1_21_11NmsProvider.kt Wires v1.21.11 blocker implementation.
surf-api-paper-nms-v1-21-11/.../V1_21_11CommandSendPacketBlockerListenerImpl.kt v1.21.11 clientbound packet replacement/cancellation.
surf-api-paper-nms-v26-1/.../V26_1NmsProvider.kt Wires v26.1 blocker implementation.
surf-api-paper-nms-v26-1/.../V26_1CommandSendPacketBlockerListenerImpl.kt v26.1 clientbound packet replacement/cancellation.
surf-api-paper/api/surf-api-paper.api Generated ABI updates for new public symbols.
surf-api-paper-plugin-test/.../SuspendRequirementTestCommand.kt Demo subcommand exercising the new requirement API.
surf-api-paper-plugin-test/.../SurfApiTestCommand.java Registers the new test subcommand.
gradle.properties Bumps project version to 3.16.0.

- remove registration of command send packet blocker listener in PacketApiLoader
- check player connection status before caching requirement
- store requirement result in cache only if player is connected
@twisti-dev twisti-dev merged commit 20e62b2 into version/26.1 May 27, 2026
6 of 7 checks passed
@twisti-dev twisti-dev deleted the feat/async-command-requirement branch May 27, 2026 12:29
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.

2 participants