TPA System

Request-based teleportation with cooldowns, warmups, ignore lists, toggle states, and instant admin teleport. 10 commands, full movement and damage cancellation, and async Folia-safe execution.

Commands

CommandDescriptionPermission
/tpa <player>Request to teleport to another player. If they accept, you are teleported to their location.essentialsc.tpa
/tpahere <player>Request a player to teleport to you. If they accept, they are teleported to your location.essentialsc.tpahere
/tpaccept [player]Accept an incoming TPA or TPAHere request. If no player is specified, accepts the most recent request. You can have up to 5 pending requests.essentialsc.tpaccept
/tpdeny [player]Deny an incoming request. If no player is specified, denies the most recent request. The requester is notified immediately.essentialsc.tpdeny
/tpcancel [player]Cancel an outgoing request you sent. If no player is specified, cancels the most recent outgoing request. The target is not notified.essentialsc.tpcancel
/tpaignore <player>Toggle ignore for a specific player. Ignored players cannot send you TPA or TPAHere requests. Use the command again to unignore.essentialsc.tpaignore
/tpatoggleToggle all TPA requests on or off for yourself. When disabled, no one can send you requests. Use the command again to re-enable.essentialsc.tpatoggle
/tpaqueueDisplay all your incoming and outgoing requests with remaining time until expiration. Useful when you have multiple pending requests.essentialsc.tpaqueue
/tphere <player>Instantly teleport a player to your location. No request, no warmup, no cooldown. Admin command.essentialsc.tphere
/tpoffline <player>Teleport to an offline player's last logout location. Reads from the user database — no request needed. Admin command.essentialsc.tpoffline
TPA vs TPAHere vs TPHere /tpa sends a request to teleport to the target. /tpahere sends a request for the target to teleport to you. /tphere is an admin command that instantly teleports the target without any request or warmup — use it for moderation, not casual teleportation.

Configuration

All TPA settings live under the tpa: section in config.yml.

tpa:
  # Seconds a player must wait between sending TPA or TPAHere requests.
  # Set to 0 to disable. Bypassed by: essentialsc.tpa.bypasscooldown
  cooldown: 60

  # Seconds the player must stand still before the teleport executes.
  # Set to 0 for instant teleport after acceptance. Bypassed by admin commands.
  warmup: 3

  # Seconds before a pending request automatically expires.
  # Expired requests are cleaned up every 10 seconds.
  timeout: 60

  # Maximum number of incoming requests a single player can have pending.
  # If a player has 5 pending requests, new requests are rejected.
  max-pending: 5

  # Maximum number of outgoing requests a single player can have active.
  # If a player has 3 outgoing requests, they cannot send more.
  max-outgoing: 3

  # Cancel the teleport if the player moves during warmup.
  # Movement is checked at the block level (X/Y/Z block coordinates).
  deny-movement: true

  # Play portal particles around the player during warmup and on arrival.
  particles: true

  # Play sounds: pling to target on request, Enderman teleport on arrival.
  sounds: true

  # Worlds where /tpa and /tpahere are completely blocked.
  blocked-worlds:
    - world_example_blocked

Permissions

PermissionDescriptionDefault
essentialsc.tpaRequest to teleport to a playertrue
essentialsc.tpahereRequest a player to teleport to youtrue
essentialsc.tpacceptAccept teleport requeststrue
essentialsc.tpdenyDeny teleport requeststrue
essentialsc.tpcancelCancel outgoing requeststrue
essentialsc.tpaignoreIgnore/unignore playerstrue
essentialsc.tpatoggleToggle TPA on/off for yourselftrue
essentialsc.tpaqueueView request queuetrue
essentialsc.tpa.bypasscooldownBypass TPA cooldownop
essentialsc.tpa.bypasscostBypass TPA cost (reserved for future economy integration)op
essentialsc.tphereInstantly teleport a player to youop
essentialsc.tphere.bypassPrevent being teleported by /tphereop
essentialsc.tphere.bypass.overrideTeleport players who have tphere.bypassop
essentialsc.tphereall.bypassTeleport players who have TPA disabledop
essentialsc.tpofflineTeleport to an offline player's last logout locationop

Request Flow

When you run /tpa <player> or /tpahere <player>, the request goes through these checks in order:

  1. Blocked world — If you are in a world listed in tpa.blocked-worlds, the request is rejected immediately.
  2. Target blocked — If the target has disabled TPA with /tpatoggle, you are notified they are not accepting requests.
  3. Ignored — If the target has ignored you with /tpaignore, the request is rejected silently.
  4. Cooldown — If you have sent a request within the cooldown period (default 60s), you must wait. Bypassed by essentialsc.tpa.bypasscooldown.
  5. Max outgoing — You can have up to 3 active outgoing requests. If full, the request is rejected.
  6. Max pending — The target can have up to 5 incoming requests. If full, you are told they are busy.
  7. Request created — A TPARequest object is created with type (TPA or TPAHERE), timestamp, and the requester's current location (cloned for safety).
  8. Notifications sent — Both parties receive MiniMessage-formatted messages. The target hears a pling sound.
  9. Expiration timer — The request expires after the timeout (default 60s). Expired requests are cleaned up every 10 seconds and both parties are notified.

Acceptance and Teleport

When the target runs /tpaccept:

  1. Request lookup — The most recent valid request from the specified player (or the latest overall) is found and removed from both incoming and outgoing maps.
  2. Teleport direction — For /tpa, the requester teleports to the target. For /tpahere, the target teleports to the requester.
  3. Cooldown applied — The requester receives a cooldown (default 60s) preventing them from sending another request immediately.
  4. Warmup — If warmup is enabled (default 3s), the player who is teleporting must stand still. Portal particles spawn around their head every tick.
  5. Back location saved — Before teleporting, the player's current location is saved to the Back system so they can return with /back.
  6. Async teleport — The actual teleport is performed asynchronously (safe for Folia). On success, an Enderman teleport sound plays and a burst of portal particles spawns at the destination.
Warmup cancellation The warmup is cancelled if the teleporting player moves (block-level X/Y/Z change), takes damage, or disconnects. The cooldown is still applied even if the teleport is cancelled — you cannot spam requests by moving to cancel.

Ignore and Toggle States

Two separate systems control who can send you requests:

FeatureCommandEffectScope
Toggle/tpatoggleDisable all incoming TPA requests. No one can send you requests.Global (all players)
Ignore/tpaignore <player>Block requests from one specific player. Other players can still send requests.Per-player

These states are stored in-memory and reset on server restart. They are not persisted to disk. If you want permanent blocks, use your permissions plugin to deny essentialsc.tpa or essentialsc.tpahere for specific players.

Admins with essentialsc.tphereall.bypass can teleport players who have TPA disabled via /tphereall (if available) or /tphere.

Admin Teleport

/tphere <player> is the admin instant-teleport command. It bypasses the entire TPA request system:

  • No request is sent — the target is teleported immediately
  • No warmup — teleport happens instantly
  • No cooldown — neither party receives a TPA cooldown
  • Back location is saved before teleport
  • Target can prevent being tphere'd with essentialsc.tphere.bypass
  • Admins with essentialsc.tphere.bypass.override can teleport bypass-exempt players

This is intended for moderation (e.g., pulling a player to you for a conversation) and should not be used for casual teleportation.

Request Queue

/tpaqueue displays a formatted list of all your active requests:

Incoming requests (2):
  → GodlyCow — TPA (expires in 45s)
  → Steve — TPAHere (expires in 12s)

Outgoing requests (1):
  → Alex — TPA (expires in 38s)

Each request shows the other player's name, the request type (TPA or TPAHere), and the remaining time until expiration. Expired requests are filtered out automatically.

Internal Architecture

The TPA system is managed by TPAManager which uses concurrent collections for thread safety:

// Incoming requests per target player
Map> incomingRequests

// Outgoing requests per requester player
Map> outgoingRequests

// Players currently in warmup
Set teleporting

// Players who disabled TPA entirely
Set blockedPlayers

// Per-player ignore lists
Map> ignoredPlayers

// Active cooldowns (requester → expiry timestamp)
Map cooldowns

// Active warmup tasks (player → SchedulerTask)
Map warmupTasks

All collections are thread-safe (ConcurrentHashMap, Collections.newSetFromMap). A background cleanup task runs every 200 ticks (10 seconds) to remove expired requests and stale cooldowns. On player quit, all their requests, cooldowns, blocked state, and ignore lists are cleaned up automatically.

Troubleshooting

"You are on cooldown"

The player sent a TPA request within the cooldown period (default 60s). Wait or grant essentialsc.tpa.bypasscooldown.

"Target is not accepting requests"

The target has disabled TPA with /tpatoggle. They must re-enable it, or an admin can use /tphere instead.

"You are being ignored by this player"

The target has added the requester to their ignore list with /tpaignore. The target must unignore them.

"Teleport cancelled — you moved"

The player moved during the warmup. Movement is checked at the block coordinate level (not sub-block precision). Stand completely still or disable tpa.deny-movement in config.

"Teleport cancelled — you took damage"

The player received damage during warmup. This prevents teleporting mid-combat. There is no permission bypass for damage cancellation — it applies to everyone.

Requests not expiring

The cleanup task runs every 10 seconds. If a request appears stuck, the target or requester may have disconnected without triggering cleanup. This is rare and self-heals on the next cleanup cycle.

"Target is busy"

The target already has 5 pending incoming requests (the max). Ask them to accept or deny existing requests, or increase tpa.max-pending in config.

Next Steps