Class PlayerEventManager

java.lang.Object
com.ultikits.ultitools.manager.PlayerEventManager
All Implemented Interfaces:
org.bukkit.event.Listener

@Internal public class PlayerEventManager extends Object implements org.bukkit.event.Listener
Player event manager. Handles WebSocket messages for player-related events.
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    private boolean
    Whether this instance has already hooked itself into the Bukkit event system.
    Must be volatile.
  • Constructor Summary

    Constructors
    Constructor
    Description
     
  • Method Summary

    Modifier and Type
    Method
    Description
    private String
    Gets the server ID.
    void
    Deprecated, for removal: This API element is subject to removal in a future version.
    There is no replacement: the framework never calls it, and its own UltiCloud session (protocol 2.0.0) reports player events itself.
    (package private) boolean
    Lets tests assert the idempotency guard's state.
    void
    onPlayerChangedWorld(org.bukkit.event.player.PlayerChangedWorldEvent event)
    Deprecated, for removal: This API element is subject to removal in a future version.
    There is no replacement: the framework's own UltiCloud session (protocol 2.0.0) reports player events itself.
    void
    onPlayerChat(org.bukkit.event.player.PlayerChatEvent event)
    Deprecated, for removal: This API element is subject to removal in a future version.
    There is no replacement: the framework's own UltiCloud session (protocol 2.0.0) reports player events itself.
    void
    onPlayerCommandPreprocess(org.bukkit.event.player.PlayerCommandPreprocessEvent event)
    Deprecated, for removal: This API element is subject to removal in a future version.
    There is no replacement: the framework's own UltiCloud session (protocol 2.0.0) reports player events itself.
    void
    onPlayerDeath(org.bukkit.event.entity.PlayerDeathEvent event)
    Deprecated, for removal: This API element is subject to removal in a future version.
    There is no replacement: the framework's own UltiCloud session (protocol 2.0.0) reports player events itself.
    void
    onPlayerJoin(org.bukkit.event.player.PlayerJoinEvent event)
    Deprecated, for removal: This API element is subject to removal in a future version.
    There is no replacement: the framework's own UltiCloud session (protocol 2.0.0) reports player events itself.
    void
    onPlayerKick(org.bukkit.event.player.PlayerKickEvent event)
    Deprecated, for removal: This API element is subject to removal in a future version.
    There is no replacement: the framework's own UltiCloud session (protocol 2.0.0) reports player events itself.
    void
    onPlayerQuit(org.bukkit.event.player.PlayerQuitEvent event)
    Deprecated, for removal: This API element is subject to removal in a future version.
    There is no replacement: the framework's own UltiCloud session (protocol 2.0.0) reports player events itself.
    private static String
    redact(String text)
    Redacts registered commands' arguments from text bound for UltiCloud.
    private void
    Idempotently registers the event listener: returns immediately if already registered.
    private void
    sendPlayerEvent(UltiPanelWebSocketClient client, com.google.gson.JsonObject data)
    Sends a player event to UltiPanel.
    void
    Unregisters the event listener and detaches the association with the client.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • webSocketClient

      private volatile UltiPanelWebSocketClient webSocketClient
      Must be volatile. Written on the WebSocket's onOpen thread (initialize(com.ultikits.ultitools.websocket.UltiPanelWebSocketClient)), read on the Bukkit main thread (the seven event handlers). Adding synchronized only to the writer does not establish publication -- the reader never acquires the same monitor, so there is no happens-before edge between the two sides.

      This was accidentally masked before the idempotency guard was added: back then every initialize call also called registerEvents, and Bukkit's own listener registration writes a volatile field on HandlerList, which event dispatch then reads -- so this field's write got piggybacked out for free. Once the guard started skipping registration, that piggyback chain broke: after a reconnect, the handler could keep looking at the old, already-disconnected client, and player events would be silently dropped. See the PR #264 review.

    • listenerRegistered

      private volatile boolean listenerRegistered
      Whether this instance has already hooked itself into the Bukkit event system.

      In 6.3.0 initialize(UltiPanelWebSocketClient) was called by the v1 manager wiring (removed in 6.3.1), which was itself hung on the WebSocket's onConnectHandler -- it ran on every single onOpen. Without this guard, N disconnect-reconnect cycles would register N copies of the listener, and the same player event would be sent out N times. See issue #180.

  • Constructor Details

    • PlayerEventManager

      public PlayerEventManager()
  • Method Details

    • initialize

      @Deprecated(since="6.3.1", forRemoval=true) public void initialize(UltiPanelWebSocketClient client)
      Deprecated, for removal: This API element is subject to removal in a future version.
      There is no replacement: the framework never calls it, and its own UltiCloud session (protocol 2.0.0) reports player events itself. Removed in 6.4.0.
      Initializes the player event manager.

      The whole method is mutually exclusive with shutdown(). Synchronizing only registerEvents on its own is not enough: a window would be left between "assign the client" and "register the listener", and if a logout happens to land exactly in that window, the listener shutdown() just detached would get reinstalled by the registerEvents that follows right behind it -- leaving listenerRegistered true even after disableCloud(). See the PR #264 review.

      Parameters:
      client - the WebSocket client
      Scheduled removal version:
      6.4.0
    • registerEvents

      private void registerEvents()
      Idempotently registers the event listener: returns immediately if already registered.

      The caller must already hold this object's monitor lock (currently the only caller is initialize(com.ultikits.ultitools.websocket.UltiPanelWebSocketClient)).

    • shutdown

      public void shutdown()
      Unregisters the event listener and detaches the association with the client.

      Called by PluginInitiationUtils.disableCloud() -- i.e. after /ulticloud logout. Distinct from a "disconnect-and-reconnect": in that case initialize gets called back afterward, so unregistering would just mean re-registering again; this method handles the case where the cloud feature was explicitly turned off, and the listener should genuinely be detached.

    • isListenerRegistered

      boolean isListenerRegistered()
      Lets tests assert the idempotency guard's state.
    • onPlayerJoin

      @Deprecated(since="6.3.1", forRemoval=true) public void onPlayerJoin(org.bukkit.event.player.PlayerJoinEvent event)
      Deprecated, for removal: This API element is subject to removal in a future version.
      There is no replacement: the framework's own UltiCloud session (protocol 2.0.0) reports player events itself. Removed in 6.4.0.
      Handles the player-join event.
      Scheduled removal version:
      6.4.0
    • onPlayerQuit

      @Deprecated(since="6.3.1", forRemoval=true) public void onPlayerQuit(org.bukkit.event.player.PlayerQuitEvent event)
      Deprecated, for removal: This API element is subject to removal in a future version.
      There is no replacement: the framework's own UltiCloud session (protocol 2.0.0) reports player events itself. Removed in 6.4.0.
      Handles the player-quit event.
      Scheduled removal version:
      6.4.0
    • onPlayerChat

      @Deprecated(since="6.3.1", forRemoval=true) public void onPlayerChat(org.bukkit.event.player.PlayerChatEvent event)
      Deprecated, for removal: This API element is subject to removal in a future version.
      There is no replacement: the framework's own UltiCloud session (protocol 2.0.0) reports player events itself. Removed in 6.4.0.
      Handles the player-chat event.

      The message is passed through SensitiveCommandRegistry.redactText(java.lang.String) before it is sent, both in the event and in the debug log line, since a player may paste a command into chat. The chat itself, as other players and the local console see it, is not changed.

      Scheduled removal version:
      6.4.0
    • onPlayerDeath

      @Deprecated(since="6.3.1", forRemoval=true) public void onPlayerDeath(org.bukkit.event.entity.PlayerDeathEvent event)
      Deprecated, for removal: This API element is subject to removal in a future version.
      There is no replacement: the framework's own UltiCloud session (protocol 2.0.0) reports player events itself. Removed in 6.4.0.
      Handles the player-death event.

      Moved here from the former EnhancedPlayerEventListener (#387). That class carried @EventListener but was never registered, so this handler and the three below had never fired. Registering that class alongside this one was not an option: both emitted the same player_event message type, so join/quit/chat would have been sent twice.

      Scheduled removal version:
      6.4.0
    • onPlayerKick

      @Deprecated(since="6.3.1", forRemoval=true) public void onPlayerKick(org.bukkit.event.player.PlayerKickEvent event)
      Deprecated, for removal: This API element is subject to removal in a future version.
      There is no replacement: the framework's own UltiCloud session (protocol 2.0.0) reports player events itself. Removed in 6.4.0.
      Handles the player-kick event.
      Scheduled removal version:
      6.4.0
    • onPlayerCommandPreprocess

      @Deprecated(since="6.3.1", forRemoval=true) public void onPlayerCommandPreprocess(org.bukkit.event.player.PlayerCommandPreprocessEvent event)
      Deprecated, for removal: This API element is subject to removal in a future version.
      There is no replacement: the framework's own UltiCloud session (protocol 2.0.0) reports player events itself. Removed in 6.4.0.
      Handles the player-command event.

      The event carries only the command's normalised name (SensitiveCommandRegistry.commandName(java.lang.String): first token, leading / and namespace stripped, lower-cased), never its arguments, for every command whether or not it is registered as sensitive.

      Scheduled removal version:
      6.4.0
    • onPlayerChangedWorld

      @Deprecated(since="6.3.1", forRemoval=true) public void onPlayerChangedWorld(org.bukkit.event.player.PlayerChangedWorldEvent event)
      Deprecated, for removal: This API element is subject to removal in a future version.
      There is no replacement: the framework's own UltiCloud session (protocol 2.0.0) reports player events itself. Removed in 6.4.0.
      Handles the player-world-change event.
      Scheduled removal version:
      6.4.0
    • redact

      private static String redact(String text)
      Redacts registered commands' arguments from text bound for UltiCloud. Without a framework instance nothing can have been registered, so the text is returned unchanged.
    • sendPlayerEvent

      private void sendPlayerEvent(UltiPanelWebSocketClient client, com.google.gson.JsonObject data)
      Sends a player event to UltiPanel.

      The client is passed in by the caller rather than re-reading webSocketClient here: each of the seven event handlers reads that volatile field into a local variable once and threads it through from there. Otherwise "check the connection" and "actually send" could read two different values -- if shutdown() happens to land in between, this would be an NPE.

      Parameters:
      client - the client the event handler read on entry
      data - the event data
    • getServerId

      private String getServerId(UltiPanelWebSocketClient client)
      Gets the server ID.

      Takes the server ID the caller gave the client at construction (in 6.3.0 the v1 wiring, removed in 6.3.1, passed CommonUtils.getUltiToolsUUID()), consistent with every sibling manager. Before #180, this returned a hardcoded placeholder string, meaning every server worldwide sent out its player_event claiming the same identity, and the panel side had no way to route them.

      Returns:
      the server ID