Compatibility
Minecraft: Java Edition
Platforms
Creators
Details
TPAPlugin
A fully optimized, feature-rich TPA (Teleport Ask) plugin for Paper, Folia Purpur & More servers with customizable GUIs, clickable messages, sound effects, proxy support, HEX color Support, and PlaceholderAPI integration.
Features
/tpa <player>— request to teleport to another player/tpahere <player>— request another player to teleport to you- Confirm GUI before sending requests (per-player toggle)
- Accept/deny GUIs with player-head previews
- Pending requests list (
/tpaaccept) - Per-player toggles: receive TPA, receive TPAHERE, auto-accept
- Cross-server TPA via Redis + Velocity/BungeeCord proxy
- Cross-server skin fetching (UUID-based)
- Folia-compatible regionized scheduling
- Configurable teleport delay, cancel-on-move, cancel-on-damage
- Sound effects per action
- World aliases for nicer location names
- PlaceholderAPI placeholders
- Modrinth update checker (notifies OPs on join)
/tpastatusadmin command showing Redis status and connected servers
Commands
| Command | Description | Permission |
|---|---|---|
/tpa <player> |
Request to teleport to a player | tpaplugin.tpa |
/tpahere <player> |
Ask a player to teleport to you | tpaplugin.tpahere |
/tpaaccept [player] |
Open accept GUI or accept a specific request | tpaplugin.tpaaccept |
/tpadeny [player] |
Deny a request | tpaplugin.tpadeny |
/tpacancel <player> |
Cancel an outgoing request | tpaplugin.tpacancel |
/tpatoggle |
Toggle receiving TPA requests | tpaplugin.tpatoggle |
/tpaheretoggle |
Toggle receiving TPAHERE requests | tpaplugin.tpaheretoggle |
/tpauto |
Toggle auto-accept | tpaplugin.tpauto |
/tpaconfirmtoggle |
Toggle the confirm menu before sending | tpaplugin.confirmtoggle |
/tpastatus |
Show plugin and Redis status | tpaplugin.status |
/tpareload |
Reload config and reconnect Redis | tpaplugin.reload |
Cross-Server Setup (Redis + Velocity)
Cross-server TPA lets players send /tpa and /tpahere requests to players on other backend servers connected through the same proxy. Both Minecraft servers communicate through Redis.
Set up Redis
You need a single Redis server that both Minecraft backends can reach. The Redis server can run on the same machine as your proxy or on a separate machine.
Configure Velocity
Open velocity.toml on your proxy and find the [servers] section:
[servers]
lobby = "127.0.0.1:25566"
survival = "127.0.0.1:25567"
try = ["lobby"]
The names on the left (lobby, survival) are the names you must use in the plugin config below.
Configure the plugin on each backend
Edit plugins/TPAPlugin/config.yml on each Minecraft server:
proxy:
enabled: true
server-blacklist: [] # Add server names here to block TPAing to them
redis:
enabled: true
host: "127.0.0.1" # Redis host (use the actual IP if remote)
port: 6379
password: "" # Leave empty if no password
server-name: "lobby" # MUST match the name in velocity.toml [servers]
The server-name must match exactly, case-sensitive, with the key in your velocity.toml [servers] block. If your Velocity has lobby = "...", set server-name: "lobby" here.
Repeat for each backend, but use the matching server name (one will be lobby, another survival, etc.).
Verify it works
- Start Redis
- Start the proxy
- Start each backend
- Join through the proxy
- Run
/tpastatus(as OP)
You should see:
Redis: Connected
Host: 127.0.0.1:6379
This server: lobby
Connected servers: survival
If Connected servers is empty, the other server isn't reaching the same Redis. Check the Redis host/port on both servers.
Permissions
| Permission | Description | Default |
|---|---|---|
tpaplugin.* |
All permissions | OP |
tpaplugin.tpa |
Send TPA requests | Everyone |
tpaplugin.tpahere |
Send TPAHere requests | Everyone |
tpaplugin.tpaaccept |
Accept requests | Everyone |
tpaplugin.tpadeny |
Deny requests | Everyone |
tpaplugin.tpacancel |
Cancel requests | Everyone |
tpaplugin.tpatoggle |
Toggle TPA | Everyone |
tpaplugin.tpaheretoggle |
Toggle TPAHere | Everyone |
tpaplugin.tpauto |
Auto-accept | Everyone |
tpaplugin.confirmtoggle |
Toggle TPA Confirm Menu | Everyone |
tpaplugin.status |
View plugin/Redis status | OP |
tpaplugin.reload |
Reload plugin | OP |
📊 PlaceholderAPI Placeholders
| Placeholder | Description | Output |
|---|---|---|
%tpa_tpastatus% |
Shows if TPA is enabled | ON/OFF |
%tpa_tpaherestatus% |
Shows if TPA here is enabled | ON/OFF |
%tpa_tpautostatus% |
Shows if auto-accept is enabled | ON/OFF |
%tpa_confirmmenustatus% |
Shows if TPA here is enabled | ON/OFF |
%tpa_pendingrequests% |
Number of pending requests | Number |
⚙️ Configuration
config.yml
teleport-delay: 5
request-expire-time: 60
cancel-on-move: true
cancel-on-damage: true
proxy:
enabled: false
server-blacklist: []
redis:
enabled: false
host: "localhost"
port: 6379
password: ""
server-name: "server-1"
world-aliases:
world: "Overworld"
afk3: "AFK AREA"
world_nether: "Nether"
server-aliases:
lobby: "Lobby"
survival: "Survival"
# ===============================
# Messages
# ===============================
messages:
prefix: '&8[&9✦&bᴛᴘᴀ&5✦&8] &r'
tpa-sent: '&bᴛᴇʟᴇᴘᴏʀᴛ ʀᴇǫᴜᴇѕᴛ ꜱᴇɴᴛ ᴛᴏ &9{player}&b.'
tpa-received: '&9{player} &bʜᴀѕ ꜱᴇɴᴛ ʏᴏᴜ ᴀ ᴛᴇʟᴇᴘᴏʀᴛ ʀᴇǫᴜᴇѕᴛ.'
tpahere-sent: '&bᴛᴇʟᴇᴘᴏʀᴛ-ʜᴇʀᴇ ʀᴇǫᴜᴇѕᴛ ꜱᴇɴᴛ ᴛᴏ &9{player}&b.'
tpahere-received: '&9{player} &bᴡᴀɴᴛѕ ʏᴏᴜ ᴛᴏ ᴛᴇʟᴇᴘᴏʀᴛ ᴛᴏ ᴛʜᴇᴍ.'
request-accepted-receiver: '&bʏᴏᴜ ᴀᴄᴄᴇᴘᴛᴇᴅ &9{player}&b''ѕ ᴛᴇʟᴇᴘᴏʀᴛ ʀᴇǫᴜᴇѕᴛ.'
request-accepted-sender: '&9{player} &bʜᴀѕ &aᴀᴄᴄᴇᴘᴛᴇᴅ &bʏᴏᴜʀ ᴛᴇʟᴇᴘᴏʀᴛ ʀᴇǫᴜᴇѕᴛ.'
request-denied-receiver: '&cʏᴏᴜ ᴅᴇɴɪᴇᴅ &9{player}&c''ѕ ᴛᴇʟᴇᴘᴏʀᴛ ʀᴇǫᴜᴇѕᴛ.'
request-denied-sender: '&9{player} &cʜᴀѕ ᴅᴇɴɪᴇᴅ &cʏᴏᴜʀ ᴛᴇʟᴇᴘᴏʀᴛ ʀᴇǫᴜᴇѕᴛ.'
request-cancelled: '&cʏᴏᴜ ᴄᴀɴᴄᴇʟʟᴇᴅ ʏᴏᴜʀ ᴛᴇʟᴇᴘᴏʀᴛ ʀᴇǫᴜᴇѕᴛ ᴛᴏ &9{player}&c.'
request-expired: '&cʏᴏᴜʀ ᴛᴇʟᴇᴘᴏʀᴛ ʀᴇǫᴜᴇѕᴛ ᴛᴏ &9{player} &cʜᴀѕ ᴇxᴘɪʀᴇᴅ.'
no-pending-requests: '&cʏᴏᴜ ʜᴀᴠᴇ ɴᴏ ᴘᴇɴᴅɪɴɢ ᴛᴇʟᴇᴘᴏʀᴛ ʀᴇǫᴜᴇѕᴛѕ.'
teleporting-in: '&bᴛᴇʟᴇᴘᴏʀᴛɪɴɢ ɪɴ &9{seconds}&b ꜱᴇᴄᴏɴᴅѕ...'
teleported: '&bʏᴏᴜ ʜᴀᴠᴇ ʙᴇᴇɴ &9ꜱᴜᴄᴄᴇꜱꜱꜰᴜʟʟʏ ᴛᴇʟᴇᴘᴏʀᴛᴇᴅ&b!'
teleport-cancelled-move: '&cᴛᴇʟᴇᴘᴏʀᴛ ᴄᴀɴᴄᴇʟʟᴇᴅ &8(&7ʏᴏᴜ ᴍᴏᴠᴇᴅ&8)'
teleport-cancelled-damage: '&cᴛᴇʟᴇᴘᴏʀᴛ ᴄᴀɴᴄᴇʟʟᴇᴅ &8(&7ʏᴏᴜ ᴛᴏᴏᴋ ᴅᴀᴍᴀɢᴇ&8)'
player-not-found: '&cᴘʟᴀʏᴇʀ ɴᴏᴛ ꜰᴏᴜɴᴅ.'
cannot-tpa-yourself: '&cʏᴏᴜ ᴄᴀɴɴᴏᴛ ᴛᴇʟᴇᴘᴏʀᴛ ᴛᴏ ʏᴏᴜʀꜱᴇʟꜰ.'
player-offline: '&cᴛʜᴀᴛ ᴘʟᴀʏᴇʀ ɪѕ ᴄᴜʀʀᴇɴᴛʟʏ ᴏꜰꜰʟɪɴᴇ.'
tpa-disabled: '&9{player} &cʜᴀѕ ᴛᴇʟᴇᴘᴏʀᴛ ʀᴇǫᴜᴇѕᴛѕ ᴅɪѕᴀʙʟᴇᴅ.'
tpahere-disabled: '&9{player} &cʜᴀѕ ᴛᴇʟᴇᴘᴏʀᴛ-ʜᴇʀᴇ ʀᴇǫᴜᴇѕᴛѕ ᴅɪѕᴀʙʟᴇᴅ.'
tpa-toggled-on: '&bᴛᴇʟᴇᴘᴏʀᴛ ʀᴇǫᴜᴇѕᴛѕ ᴀʀᴇ ɴᴏᴡ &9ᴇɴᴀʙʟᴇᴅ&b.'
tpa-toggled-off: '&cᴛᴇʟᴇᴘᴏʀᴛ ʀᴇǫᴜᴇѕᴛѕ ᴀʀᴇ ɴᴏᴡ &7ᴅɪѕᴀʙʟᴇᴅ&c.'
tpahere-toggled-on: '&bᴛᴇʟᴇᴘᴏʀᴛ-ʜᴇʀᴇ ʀᴇǫᴜᴇѕᴛѕ ᴀʀᴇ ɴᴏᴡ &9ᴇɴᴀʙʟᴇᴅ&b.'
tpahere-toggled-off: '&cᴛᴇʟᴇᴘᴏʀᴛ-ʜᴇʀᴇ ʀᴇǫᴜᴇѕᴛѕ ᴀʀᴇ ɴᴏᴡ &7ᴅɪѕᴀʙʟᴇᴅ&c.'
tpauto-enabled: '&bᴀᴜᴛᴏ-ᴀᴄᴄᴇᴘᴛ ɪѕ ɴᴏᴡ &9ᴇɴᴀʙʟᴇᴅ&b.'
tpauto-disabled: '&cᴀᴜᴛᴏ-ᴀᴄᴄᴇᴘᴛ ɪѕ ɴᴏᴡ &7ᴅɪѕᴀʙʟᴇᴅ&c.'
already-have-request: '&cʏᴏᴜ ᴀʟʀᴇᴀᴅʏ ʜᴀᴠᴇ ᴀ ᴘᴇɴᴅɪɴɢ ʀᴇǫᴜᴇѕᴛ ᴡɪᴛʜ ᴛʜɪѕ ᴘʟᴀʏᴇʀ.'
config-reloaded: '&bᴄᴏɴꜰɪɢᴜʀᴀᴛɪᴏɴ ʀᴇʟᴏᴀᴅᴇᴅ &9ꜱᴜᴄᴄᴇꜱꜱꜰᴜʟʟʏ&b.'
no-permission: '&cʏᴏᴜ ᴅᴏ ɴᴏᴛ ʜᴀᴠᴇ ᴘᴇʀᴍɪꜱꜱɪᴏɴ ᴛᴏ ᴜꜱᴇ ᴛʜɪꜱ ᴄᴏᴍᴍᴀɴᴅ.'
blacklisted-server: '&cʏᴏᴜ ᴄᴀɴɴᴏᴛ ᴛᴇʟᴇᴘᴏʀᴛ ᴛᴏ ᴘʟᴀʏᴇʀѕ ᴏɴ ᴛʜᴀᴛ ꜱᴇʀᴠᴇʀ.'
tpa-confirm-enabled: '&bᴛᴘᴀ ᴄᴏɴꜰɪʀᴍ ᴍᴇɴᴜ ɪѕ ɴᴏᴡ &aᴇɴᴀʙʟᴇᴅ&b.'
tpa-confirm-disabled: '&bᴛᴘᴀ ᴄᴏɴꜰɪʀᴍ ᴍᴇɴᴜ ɪѕ ɴᴏᴡ &cᴅɪѕᴀʙʟᴇᴅ&b.'
# ===============================
# Clickable Messages
# ===============================
click:
accept:
text: '&a[✔ ᴀᴄᴄᴇᴘᴛ]'
hover: '&7ᴄʟɪᴄᴋ ᴛᴏ ᴀᴄᴄᴇᴘᴛ ᴛʜᴇ ᴛᴇʟᴇᴘᴏʀᴛ ʀᴇǫᴜᴇѕᴛ'
command: /tpaaccept {player}
deny:
text: '&c[✖ ᴅᴇɴʏ]'
hover: '&7ᴄʟɪᴄᴋ ᴛᴏ ᴅᴇɴʏ ᴛʜᴇ ᴛᴇʟᴇᴘᴏʀᴛ ʀᴇǫᴜᴇѕᴛ'
command: /tpadeny {player}
# ===============================
# Sounds
# ===============================
sounds:
tpa_request_sent: ENTITY_EXPERIENCE_ORB_PICKUP
tpa_request_received: ENTITY_PLAYER_LEVELUP
tpa_accept: ENTITY_ENDERMAN_TELEPORT
tpa_deny: ENTITY_VILLAGER_NO
tpa_expired: ENTITY_ITEM_BREAK
GUI/tpa.yml
title: '&8ᴛᴇʟᴇᴘᴏʀᴛ ʀᴇǫᴜᴇѕᴛ'
size: 27
items:
accept:
slot: 15
material: LIME_STAINED_GLASS_PANE
name: '&a&lᴀᴄᴄᴇᴘᴛ'
deny:
slot: 11
material: RED_STAINED_GLASS_PANE
name: '&c&lᴅᴇɴʏ'
player-head:
slot: 13
name: '&e{player}'
lore:
- '{request_type}'
- '&7ꜰʟɪɢʜᴛ: {flight_status}'
- ''
- '&7ᴇxᴘɪʀᴇѕ ɪɴ: &e{time}ѕ'
- '&7ʟᴏᴄᴀᴛɪᴏɴ: &f{world}'
GUI/tpahere.yml
title: '&8ᴛᴇʟᴇᴘᴏʀᴛ ʜᴇʀᴇ ʀᴇǫᴜᴇѕᴛ'
size: 27
items:
accept:
slot: 15
material: LIME_STAINED_GLASS_PANE
name: '&a&lᴀᴄᴄᴇᴘᴛ'
deny:
slot: 11
material: RED_STAINED_GLASS_PANE
name: '&c&lᴅᴇɴʏ'
player-head:
slot: 13
name: '&e{player}'
lore:
- '{request_type}'
- '&7ꜰʟɪɢʜᴛ: {flight_status}'
- ''
- '&7ᴇxᴘɪʀᴇѕ ɪɴ: &e{time}ѕ'
- '&7ʟᴏᴄᴀᴛɪᴏɴ: &f{world}'
GUI/tpaaccept.yml
title: '&8ᴘᴇɴᴅɪɴɢ ʀᴇǫᴜᴇѕᴛѕ'
size: 54
request-item:
name: '&e{player}'
lore:
- '{request_type}'
- '&7ꜰʟɪɢʜᴛ: {flight_status}'
- '&7ʟᴏᴄᴀᴛɪᴏɴ: &f{world}'
- '&7ᴛɪᴍᴇ ʟᴇꜰᴛ: &e{time}ѕ'
- ''
- '&aʟᴇꜰᴛ-ᴄʟɪᴄᴋ &7ᴛᴏ ᴀᴄᴄᴇᴘᴛ'
- '&cʀɪɢʜᴛ-ᴄʟɪᴄᴋ &7ᴛᴏ ᴅᴇɴʏ'
GUI/tpa-confirm.yml
tpa-confirm-menu:
enabled-by-default: true
title: '&8ᴛᴘᴀ ᴄᴏɴꜰɪʀᴍ'
size: 27
player-head:
slot: 13
name: '&b{player}'
lore:
- '&7ꜰʟɪɢʜᴛ: {flight_status}'
- '&7ʟᴏᴄᴀᴛɪᴏɴ: &f{world}'
confirm:
slot: 15
material: LIME_STAINED_GLASS_PANE
name: '&aᴄᴏɴꜰɪʀᴍ'
deny:
slot: 11
material: RED_STAINED_GLASS_PANE
name: '&cᴄᴀɴᴄᴇʟ'~~~~
🌐 Proxy Support
Enabling Proxy Mode
- Set
proxy.enabled: trueinconfig.yml - Configure
server-blacklistto prevent teleports to specific servers - Ensure plugin is installed on all servers in your network
Server Blacklist
Players cannot teleport to/from servers in the blacklist:
proxy:
enabled: true
server-blacklist:
- lobby
- hub
- minigames
⚡ Performance Optimizations
- Concurrent Hash Maps for thread-safe data storage
- Asynchronous file I/O for player data
- Efficient request expiration with scheduled tasks
- Memory-optimized GUI rendering
- Minimal packet sending for better network performance
- Folia-compatible scheduling for multi-threaded chunk loading
🤝 Support
For issues, suggestions, or contributions:
- Contact SOULESS STUDIOS


