Skip to content

Perf/optimize packet listener#252

Merged
twisti-dev merged 3 commits intoversion/1.21.11from
perf/optimize-packet-listener
Mar 17, 2026
Merged

Perf/optimize packet listener#252
twisti-dev merged 3 commits intoversion/1.21.11from
perf/optimize-packet-listener

Conversation

@twisti-dev
Copy link
Contributor

This pull request introduces significant improvements and refactoring to the packet listener infrastructure in the Bukkit API, focusing on safer handling of early connection phases, improved listener registration, and modernization of concurrency primitives. The changes enhance robustness, flexibility, and maintainability for handling Minecraft packets in various connection states.

API and Listener Handling Improvements

  • Introduced the handleEarlyClientboundPacket method to NmsClientboundPacketListener, mirroring the serverbound variant, and updated both to throw an exception if called before a Player is available, requiring explicit override for pre-login handling. This ensures listeners are aware of early-phase packet handling and must opt-in if needed. [1] [2] [3]
  • Annotated key interfaces (NmsClientboundPacketListener, NmsServerboundPacketListener, NmsPacketListener) with @NullMarked and improved API status annotations for better null-safety and documentation. [1] [2] [3]

Exception Handling and Logging

  • Updated the NMS bridge implementation (SurfBukkitNmsBridgeImpl) to wrap early packet handler invocations in try-catch blocks, logging severe errors and ensuring packet flow continuity by returning PacketListenerResult.CONTINUE on exceptions. [1] [2]

Listener Registration and Invocation Refactor

  • Refactored SurfBukkitPacketListenerApiImpl to use ConcurrentHashMap and CopyOnWriteArraySet for thread-safe listener management, replaced reflective method invocation with normalized MethodHandle invokers, and unified support for both ServerPlayer and Bukkit Player parameters in listener methods. This includes improved error handling and parameter validation during registration. [1] [2]
  • Removed legacy callListener logic in favor of a more robust ListenerInvoker and ListenerResultConverter system, streamlining the invocation process and supporting flexible return types (void, PacketListenerResult, or Packet).

Miscellaneous

  • Added cleanup for PlayerChannelInjector on plugin disable and refactored imports for clarity and correctness in related files. [1] [2]
  • Bumped project version from 1.21.11-2.68.0 to 1.21.11-2.69.0.

@twisti-dev twisti-dev self-assigned this Mar 17, 2026
Copilot AI review requested due to automatic review settings March 17, 2026 17:22
@twisti-dev twisti-dev merged commit 429d552 into version/1.21.11 Mar 17, 2026
5 checks passed
@twisti-dev twisti-dev deleted the perf/optimize-packet-listener branch March 17, 2026 17:22
Copy link
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

This PR refactors and hardens the Bukkit packet listener pipeline to better support early-connection packet handling, improve thread-safety/performance of listener dispatch, and tighten API null-safety contracts.

Changes:

  • Refactored channel injection to store a per-channel PacketHandler via Netty AttributeKey, and ensured injector cleanup on plugin disable.
  • Reworked SurfBukkitPacketListenerApiImpl listener registration/invocation to use concurrent collections and normalized MethodHandle invokers.
  • Added early-phase clientbound handling API (handleEarlyClientboundPacket), added @NullMarked/status annotations, and added exception guards around early handler invocations.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
surf-api-bukkit/surf-api-bukkit-server/.../packet/listener/PlayerChannelInjector.kt Replaces cache-based injection with per-channel attribute-based handler management; adds safer login-phase setup and unified packet handling path.
surf-api-bukkit/surf-api-bukkit-server/.../packet/PacketApiLoader.kt Ensures PlayerChannelInjector is unregistered during plugin disable to prevent lingering hooks.
surf-api-bukkit/surf-api-bukkit-server/.../SurfBukkitPacketListenerApiImpl.kt Refactors listener storage/invocation with ConcurrentHashMap + CopyOnWriteArraySet and MethodHandle normalization.
surf-api-bukkit/surf-api-bukkit-server/.../SurfBukkitNmsBridgeImpl.kt Wraps early packet listener calls with try/catch and continues on failure to protect the packet pipeline.
surf-api-bukkit/surf-api-bukkit-api/.../NmsServerboundPacketListener.java Marks nullness defaults and makes early serverbound handling explicit by throwing if no Player exists unless overridden.
surf-api-bukkit/surf-api-bukkit-api/.../NmsClientboundPacketListener.java Introduces handleEarlyClientboundPacket with explicit opt-in semantics for pre-Player phases.
surf-api-bukkit/surf-api-bukkit-api/.../NmsPacketListener.java Adds internal/status annotations and @NullMarked to improve null-safety signaling.
surf-api-bukkit/surf-api-bukkit-api/api/surf-api-bukkit-api.api Updates API surface snapshot to include the new early clientbound handler.
gradle.properties Bumps project version to 1.21.11-2.69.0.

}

Packet::class.java.isAssignableFrom(returnType) -> ListenerResultConverter<Packet<*>?> { result, original ->
result
private val injectedChannels = Caffeine.newBuilder()
.weakKeys()
.build<Channel, Boolean>()
private val packetHandlerKey = AttributeKey.newInstance<PacketHandler>("surf_api_packet_handler")
}

private fun createResultConverter(returnType: Class<*>): ListenerResultConverter<*> = when {
returnType == Void.TYPE -> ListenerResultConverter<Unit> { _, p -> p }
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