Class PlayerActionHandler
- All Implemented Interfaces:
CloudRequestHandler
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
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate static final classOne validated request, independent of the payload object it was read from.(package private) static interfaceThe audit port integration binds to the remote action log; one entry per executed or refused action, none for a payload that never ran.private static final classOne validated teleport target: another online player, or a world and a position. -
Field Summary
FieldsModifier and TypeFieldDescription(package private) static final StringThe contract's second action value.(package private) static final StringThe contract's first action value.(package private) static final StringThe contract's third action value.private final PlayerActionHandler.ActionAudit(package private) static final StringThe contract result code for a cancelled action or a throwing call.(package private) static final StringThe contract result code for a subject or target that is not online.(package private) static final StringThe contract result code for coordinates whose world does not exist.(package private) static final StringThe result message used when another plugin cancels the game mode change.private static final String[]private static final doubleprivate static final double(package private) static final StringThe one message a throwing call is answered with; the same fixed text the agent router uses forinternal_error, so no exception text ever reaches the wire.(package private) static final StringThe result message used when another plugin cancels the kick.private static final Loggerprivate static final doubleprivate final Executorprivate static final Stringprivate static final intprivate static final intprivate static final Stringprivate static final int(package private) static final StringThe frozen contract result type every delivery is answered with.(package private) static final StringThe teleport target kind that names a world and a position.(package private) static final StringThe teleport target kind that names another online player.(package private) static final StringThe result message used when another plugin cancels the teleport.(package private) static final StringThe frozen contract request type this handler consumes.private static final intprivate static final int -
Constructor Summary
ConstructorsConstructorDescriptionPlayerActionHandler(Executor mainThread, PlayerActionHandler.ActionAudit audit) Creates the handler. -
Method Summary
Modifier and TypeMethodDescriptionprivate voidcompleteTeleport(CloudChannel channel, CloudRequest request, PlayerActionHandler.Action action, Boolean completed, Throwable error) Answers the teleport once its future completes.private voiddeny(CloudChannel channel, CloudRequest request, PlayerActionHandler.Action action, String code, String message) private org.bukkit.Locationdestination(CloudChannel channel, CloudRequest request, PlayerActionHandler.Action action, org.bukkit.entity.Player subject) Resolves the destination, answeringplayer_not_onlineorworld_not_foundand returning null when the target cannot be resolved.private voidfail(CloudChannel channel, CloudRequest request, PlayerActionHandler.Action action, Throwable error) Maps a throwing call to the contract'sinternal_errorwith 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).voidhandle(CloudRequest request, CloudChannel channel) Validates the payload on the dispatching thread, then performs the action on the main thread.private static org.bukkit.entity.PlayeronlinePlayer(String name) private static StringoptionalReason(PayloadReader reader) A kick reason is optional; when present it must be a string of at most 256 code points.private static PlayerActionHandler.Actionparse(CloudRequest request) Reads one branch of the discriminated union, validating exactly the keys that branch allows.private static PlayerActionHandler.TargetparseTarget(String id, com.google.gson.JsonObject object) Reads the teleport target, validating exactly the keys its kind allows.private voidperform(CloudRequest request, CloudChannel channel, PlayerActionHandler.Action action) Runs once per accepted request, on the main thread: resolve the subject, then act.private voidrecord(PlayerActionHandler.Action action, String refusal) private voidrunGameMode(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 thePlayerGameModeChangeEvent, and the platform discards that answer.private voidrunKick(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.private voidrunTeleport(CloudChannel channel, CloudRequest request, PlayerActionHandler.Action action, org.bukkit.entity.Player subject) Starts the asynchronous teleport and answers when its future completes.private voidsucceed(CloudChannel channel, CloudRequest request, PlayerActionHandler.Action action)
-
Field Details
-
TYPE
The frozen contract request type this handler consumes.- See Also:
-
RESULT_TYPE
The frozen contract result type every delivery is answered with.- See Also:
-
ACTION_KICK
The contract's first action value.- See Also:
-
ACTION_GAMEMODE
The contract's second action value.- See Also:
-
ACTION_TELEPORT
The contract's third action value.- See Also:
-
TARGET_PLAYER
The teleport target kind that names another online player.- See Also:
-
TARGET_COORDS
The teleport target kind that names a world and a position.- See Also:
-
CODE_PLAYER_NOT_ONLINE
The contract result code for a subject or target that is not online.- See Also:
-
CODE_WORLD_NOT_FOUND
The contract result code for coordinates whose world does not exist.- See Also:
-
CODE_INTERNAL_ERROR
The contract result code for a cancelled action or a throwing call.- See Also:
-
TELEPORT_CANCELLED
The result message used when another plugin cancels the teleport.- See Also:
-
GAME_MODE_CANCELLED
The result message used when another plugin cancels the game mode change.- See Also:
-
KICK_CANCELLED
The result message used when another plugin cancels the kick.- See Also:
-
INTERNAL_ERROR_MESSAGE
The one message a throwing call is answered with; the same fixed text the agent router uses forinternal_error, so no exception text ever reaches the wire.- See Also:
-
GAME_MODES
-
NAME_MIN
private static final int NAME_MIN- See Also:
-
NAME_MAX
private static final int NAME_MAX- See Also:
-
REASON_MAX
private static final int REASON_MAX- See Also:
-
WORLD_MIN
private static final int WORLD_MIN- See Also:
-
WORLD_MAX
private static final int WORLD_MAX- See Also:
-
HORIZONTAL_LIMIT
private static final double HORIZONTAL_LIMIT- See Also:
-
LOWEST_Y
private static final double LOWEST_Y- See Also:
-
HIGHEST_Y
private static final double HIGHEST_Y- See Also:
-
OFFLINE_SUFFIX
- See Also:
-
MISSING_WORLD_SUFFIX
- See Also:
-
LOGGER
-
mainThread
-
audit
-
-
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 threadaudit- receives one allowed or denied entry per executed or refused action, or null to record nothing
-
-
Method Details
-
handle
Validates the payload on the dispatching thread, then performs the action on the main thread. A payload that does not match the contract propagates asinvalid_messagebefore anything is scheduled.- Specified by:
handlein interfaceCloudRequestHandler- Parameters:
request- the parsed requestchannel- the reply channel
-
parse
Reads one branch of the discriminated union, validating exactly the keys that branch allows. -
optionalReason
A kick reason is optional; when present it must be a string of at most 256 code points. -
parseTarget
Reads the teleport target, validating exactly the keys its kind allows. -
perform
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 thePlayerKickEvent, 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 thePlayerGameModeChangeEvent, 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, answeringplayer_not_onlineorworld_not_foundand 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
-
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'sinternal_errorwith 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
-
onlinePlayer
-