Class PlayerActionHandler

java.lang.Object
com.ultikits.ultitools.utils.PlayerActionHandler
All Implemented Interfaces:
CloudRequestHandler

final class PlayerActionHandler extends Object implements CloudRequestHandler
Handles the structured player.action request — kick, game mode and teleport — as Bukkit API calls on the main thread. No console command is ever assembled, so a player name, a world name and a kick reason are always data and never command text or formatting (user decision 13).

Every delivery is answered with player.action.result: ok with an empty data object, or the contract's player_not_online, world_not_found or internal_error. A payload that does not match the frozen schema is rejected before anything is scheduled, so an invalid frame never reaches a player.

None of the three Bukkit calls reports whether it took effect: a game mode change and a kick are both cancellable by other plugins, and the platform discards that answer. Each action is therefore answered ok only after its post-condition was observed — the game mode now equals the requested one, or the player is no longer online — and as a cancelled action otherwise. A throwing call is answered internal_error with one fixed message; the exception class and stack stay in the local log, never on the wire.

Teleports use Entity.teleportAsync(Location) and are answered when the returned future completes; that answer may therefore come from a thread other than the main thread, which CloudChannel permits. Every executed or refused action is reported once through the audit port, which integration binds to the remote action log under the players:actions capability. The capability switch itself is enforced by the router.

Package-private framework plumbing; not for module use.

Since:
6.3.1
  • Field Details

  • Constructor Details

    • PlayerActionHandler

      PlayerActionHandler(Executor mainThread, PlayerActionHandler.ActionAudit audit)
      Creates the handler.
      Parameters:
      mainThread - runs every Bukkit call this handler makes; in production this is the server's main thread, never the caller's thread
      audit - receives one allowed or denied entry per executed or refused action, or null to record nothing
  • Method Details

    • handle

      public void handle(CloudRequest request, CloudChannel channel)
      Validates the payload on the dispatching thread, then performs the action on the main thread. A payload that does not match the contract propagates as invalid_message before anything is scheduled.
      Specified by:
      handle in interface CloudRequestHandler
      Parameters:
      request - the parsed request
      channel - the reply channel
    • parse

      private static PlayerActionHandler.Action parse(CloudRequest request)
      Reads one branch of the discriminated union, validating exactly the keys that branch allows.
    • optionalReason

      private static String optionalReason(PayloadReader reader)
      A kick reason is optional; when present it must be a string of at most 256 code points.
    • parseTarget

      private static PlayerActionHandler.Target parseTarget(String id, com.google.gson.JsonObject object)
      Reads the teleport target, validating exactly the keys its kind allows.
    • perform

      private void perform(CloudRequest request, CloudChannel channel, PlayerActionHandler.Action action)
      Runs once per accepted request, on the main thread: resolve the subject, then act.
    • runKick

      private void runKick(CloudChannel channel, CloudRequest request, PlayerActionHandler.Action action, org.bukkit.entity.Player subject)
      Kicks with the reason as one plain-text component, or with the server's own default message when the panel sent no reason. The kick is reported as done only when the player is no longer online: another plugin may cancel the PlayerKickEvent, and the platform returns no answer either way.
    • runGameMode

      private void runGameMode(CloudChannel channel, CloudRequest request, PlayerActionHandler.Action action, org.bukkit.entity.Player subject)
      Applies the requested game mode and reports it as done only when the player's mode now equals the requested one: another plugin may cancel the PlayerGameModeChangeEvent, and the platform discards that answer.
    • runTeleport

      private void runTeleport(CloudChannel channel, CloudRequest request, PlayerActionHandler.Action action, org.bukkit.entity.Player subject)
      Starts the asynchronous teleport and answers when its future completes. The answer may come from a thread other than the main thread; every Bukkit call was made before it.
    • destination

      private org.bukkit.Location destination(CloudChannel channel, CloudRequest request, PlayerActionHandler.Action action, org.bukkit.entity.Player subject)
      Resolves the destination, answering player_not_online or world_not_found and returning null when the target cannot be resolved. Coordinates keep the subject's own yaw and pitch.
    • completeTeleport

      private void completeTeleport(CloudChannel channel, CloudRequest request, PlayerActionHandler.Action action, Boolean completed, Throwable error)
      Answers the teleport once its future completes. A refusing channel is logged rather than answered a second time, so one request never produces two results.
    • succeed

      private void succeed(CloudChannel channel, CloudRequest request, PlayerActionHandler.Action action)
    • deny

      private void deny(CloudChannel channel, CloudRequest request, PlayerActionHandler.Action action, String code, String message)
    • fail

      private void fail(CloudChannel channel, CloudRequest request, PlayerActionHandler.Action action, Throwable error)
      Maps a throwing call to the contract's internal_error with one fixed message: the exception class and stack stay in the local log and never reach the wire, as in the agent router (22-08).
    • record

      private void record(PlayerActionHandler.Action action, String refusal)
    • onlinePlayer

      private static org.bukkit.entity.Player onlinePlayer(String name)