60 Commits
1.0.0 ... 1.0.4

Author SHA1 Message Date
Git Manager GUI
9e74ab28fb Upload folder via GUI - src 2026-05-24 01:16:54 +02:00
Git Manager GUI
3b7a1556d1 Upload via Git Manager GUI 2026-05-24 01:16:49 +02:00
Git Manager GUI
f5b8717ad4 Upload folder via GUI - src 2026-05-23 20:08:41 +02:00
Git Manager GUI
23e77d7204 Upload folder via GUI - lib 2026-05-23 20:08:39 +02:00
Git Manager GUI
27b5ca3c13 Upload via Git Manager GUI 2026-05-23 20:08:36 +02:00
37a82ebd47 Delete src/main/resources/plugin.yml via Git Manager GUI 2026-05-23 18:08:14 +00:00
c52ef617e9 Delete src/main/java/de/teleportsuite/models/Warp.java via Git Manager GUI 2026-05-23 18:08:14 +00:00
b7ec18cf21 Delete src/main/java/de/teleportsuite/models/Portal.java via Git Manager GUI 2026-05-23 18:08:13 +00:00
15f09af83a Delete src/main/java/de/teleportsuite/managers/TeleportManager.java via Git Manager GUI 2026-05-23 18:08:13 +00:00
326ddaa9af Delete src/main/java/de/teleportsuite/managers/SpawnManager.java via Git Manager GUI 2026-05-23 18:08:12 +00:00
ee1d705447 Delete src/main/java/de/teleportsuite/managers/HomeManager.java via Git Manager GUI 2026-05-23 18:08:12 +00:00
87fd77666a Delete src/main/java/de/teleportsuite/listeners/PortalListener.java via Git Manager GUI 2026-05-23 18:08:12 +00:00
c1154f93ae Delete src/main/java/de/teleportsuite/listeners/PlayerMoveListener.java via Git Manager GUI 2026-05-23 18:08:11 +00:00
342fa394ca Delete src/main/java/de/teleportsuite/listeners/PlayerDeathListener.java via Git Manager GUI 2026-05-23 18:08:11 +00:00
b73a5950c7 Delete src/main/java/de/teleportsuite/commands/WarpsCommand.java via Git Manager GUI 2026-05-23 18:08:10 +00:00
918ad4e6bf Delete src/main/java/de/teleportsuite/commands/TpaCommand.java via Git Manager GUI 2026-05-23 18:08:10 +00:00
0e5bc86455 Delete src/main/java/de/teleportsuite/commands/TpPosCommand.java via Git Manager GUI 2026-05-23 18:08:10 +00:00
57d0ad1a6c Delete src/main/java/de/teleportsuite/commands/TpDenyCommand.java via Git Manager GUI 2026-05-23 18:08:09 +00:00
d2ce86a5d5 Delete src/main/java/de/teleportsuite/commands/TpAllCommand.java via Git Manager GUI 2026-05-23 18:08:09 +00:00
7bb29b396b Delete src/main/java/de/teleportsuite/commands/SpawnCommand.java via Git Manager GUI 2026-05-23 18:08:08 +00:00
dd1bb37886 Delete src/main/java/de/teleportsuite/commands/SetSpawnCommand.java via Git Manager GUI 2026-05-23 18:08:08 +00:00
32df7f142a Delete src/main/java/de/teleportsuite/commands/SetPortalCommand.java via Git Manager GUI 2026-05-23 18:08:08 +00:00
e48e687520 Delete src/main/java/de/teleportsuite/commands/SetFirstSpawnCommand.java via Git Manager GUI 2026-05-23 18:08:07 +00:00
1d7c9e854b Delete src/main/java/de/teleportsuite/commands/PortalsCommand.java via Git Manager GUI 2026-05-23 18:08:07 +00:00
093d31725a Delete src/main/java/de/teleportsuite/commands/HomeCommand.java via Git Manager GUI 2026-05-23 18:08:06 +00:00
8edc4885db Delete src/main/java/de/teleportsuite/commands/DelWarpCommand.java via Git Manager GUI 2026-05-23 18:08:06 +00:00
4edbcc2386 Delete src/main/java/de/teleportsuite/commands/DeathBackCommand.java via Git Manager GUI 2026-05-23 18:08:06 +00:00
51db120a1e Delete src/main/java/de/teleportsuite/commands/BackCommand.java via Git Manager GUI 2026-05-23 18:08:05 +00:00
95763ea9a6 Delete src/main/java/de/teleportsuite/TeleportSuite.java via Git Manager GUI 2026-05-23 18:08:05 +00:00
2dc8511844 Delete src/main/resources/config.yml via Git Manager GUI 2026-05-23 18:08:03 +00:00
048c3eda30 Delete src/main/java/de/teleportsuite/models/TeleportLocation.java via Git Manager GUI 2026-05-23 18:08:02 +00:00
2394ebe031 Delete src/main/java/de/teleportsuite/models/Home.java via Git Manager GUI 2026-05-23 18:08:02 +00:00
7808ecef97 Delete src/main/java/de/teleportsuite/managers/WarpManager.java via Git Manager GUI 2026-05-23 18:08:01 +00:00
a4e884420b Delete src/main/java/de/teleportsuite/managers/SavePointManager.java via Git Manager GUI 2026-05-23 18:08:01 +00:00
4402439ad4 Delete src/main/java/de/teleportsuite/managers/PortalManager.java via Git Manager GUI 2026-05-23 18:08:01 +00:00
11a49e9c58 Delete src/main/java/de/teleportsuite/listeners/PlayerRespawnListener.java via Git Manager GUI 2026-05-23 18:08:00 +00:00
5afde181d8 Delete src/main/java/de/teleportsuite/listeners/PlayerJoinListener.java via Git Manager GUI 2026-05-23 18:08:00 +00:00
6f50a03c70 Delete src/main/java/de/teleportsuite/database/DatabaseManager.java via Git Manager GUI 2026-05-23 18:07:59 +00:00
e690f23c4e Delete src/main/java/de/teleportsuite/commands/WarpCommand.java via Git Manager GUI 2026-05-23 18:07:59 +00:00
bf231a39ad Delete src/main/java/de/teleportsuite/commands/TpWorldCommand.java via Git Manager GUI 2026-05-23 18:07:59 +00:00
3864f40bac Delete src/main/java/de/teleportsuite/commands/TpHereCommand.java via Git Manager GUI 2026-05-23 18:07:58 +00:00
d169f008f5 Delete src/main/java/de/teleportsuite/commands/TpCommand.java via Git Manager GUI 2026-05-23 18:07:58 +00:00
06414edeb4 Delete src/main/java/de/teleportsuite/commands/TpAcceptCommand.java via Git Manager GUI 2026-05-23 18:07:57 +00:00
76f143d44e Delete src/main/java/de/teleportsuite/commands/SetWarpCommand.java via Git Manager GUI 2026-05-23 18:07:57 +00:00
deea73b19d Delete src/main/java/de/teleportsuite/commands/SetSavePointCommand.java via Git Manager GUI 2026-05-23 18:07:57 +00:00
7c9e599150 Delete src/main/java/de/teleportsuite/commands/SetHomeCommand.java via Git Manager GUI 2026-05-23 18:07:56 +00:00
c951969812 Delete src/main/java/de/teleportsuite/commands/SavePointCommand.java via Git Manager GUI 2026-05-23 18:07:56 +00:00
b680355fe9 Delete src/main/java/de/teleportsuite/commands/HomesCommand.java via Git Manager GUI 2026-05-23 18:07:55 +00:00
46c8a6b3e1 Delete src/main/java/de/teleportsuite/commands/EntityTransportCommand.java via Git Manager GUI 2026-05-23 18:07:55 +00:00
b9f1e224e3 Delete src/main/java/de/teleportsuite/commands/DelPortalCommand.java via Git Manager GUI 2026-05-23 18:07:55 +00:00
2584abbd95 Delete src/main/java/de/teleportsuite/commands/DelHomeCommand.java via Git Manager GUI 2026-05-23 18:07:54 +00:00
f7979b5359 Delete src/main/java/de/teleportsuite/bungeemessaging/BungeeMessenger.java via Git Manager GUI 2026-05-23 18:07:54 +00:00
d272e709e1 Delete src/main/java/de/teleportsuite/ConfigManager.java via Git Manager GUI 2026-05-23 18:07:53 +00:00
2609f783b2 Delete pom.xml via Git Manager GUI 2026-05-23 18:07:49 +00:00
a534e6445b Delete lib/BungeeCord.jar via Git Manager GUI 2026-05-23 18:07:45 +00:00
b7dd32493b README.md aktualisiert 2026-05-23 18:06:21 +00:00
Git Manager GUI
71534e7e06 Upload folder via GUI - src 2026-05-23 15:56:58 +02:00
Git Manager GUI
d703187fae Upload via Git Manager GUI 2026-05-23 15:56:53 +02:00
Git Manager GUI
90cca7c559 Upload folder via GUI - src 2026-05-22 22:11:35 +02:00
7c8bf27628 README.md aktualisiert 2026-05-22 19:07:12 +00:00
17 changed files with 1130 additions and 248 deletions

275
README.md
View File

@@ -2,41 +2,127 @@
TeleportSuite ist ein umfassendes Teleport-Plugin für Paper/Spigot mit Homes, Warps, Portalen, Spawn-System, Savepoints, Back/Deathback, Teleportanfragen und BungeeCord-Unterstützung.
---
## Features
- Homes mit konfigurierbaren Limits
- Homes mit konfigurierbaren Limits pro Rang
- Warps mit optionalen Berechtigungen
- Portale für Server- oder Weltwechsel
- Spawn, FirstSpawn und Deathback
- Teleportanfragen mit Accept/Deny
- Teleportanfragen (TPA) mit Accept/Deny
- Back- und Cooldown-/Warmup-System
- Teleport zu Koordinaten, Welten und Spielern
- Entity-Transport
- SQLite- und MySQL-Unterstützung
- BungeeCord-Unterstützung für verteilte Servernetzwerke
---
## Voraussetzungen
- Paper oder Spigot ab Minecraft 1.20
- Java 21 oder neuer
- Optional: MySQL, falls du nicht SQLite verwenden möchtest
- Optional: MySQL, falls mehrere Server auf dieselbe Datenbank zugreifen sollen
- Optional: BungeeCord-Proxy, falls du mehrere Server vernetzt hast
---
## Installation
1. Die fertige JAR-Datei in den Ordner plugins deines Servers kopieren.
2. Den Server einmal starten, damit die Konfigurationsdatei und die Datenbank angelegt werden.
3. Den Server stoppen und die Datei config.yml nach Bedarf anpassen.
4. Den Server neu starten.
### Einzelner Server (kein BungeeCord)
## Konfiguration
1. Die JAR-Datei in den `plugins`-Ordner deines Servers kopieren.
2. Server starten → Plugin legt `config.yml` und Datenbank automatisch an.
3. Server stoppen und `config.yml` nach Bedarf anpassen.
4. Server neu starten.
Die Datei config.yml wird beim ersten Start im Plugin-Ordner angelegt.
---
### Datenbank
### BungeeCord-Netzwerk ⚠️
> Wenn du mehrere Server mit BungeeCord verbunden hast und Spieler **serverübergreifend** teleportieren sollen, musst du das Plugin auf **jedem Spigot-Server UND auf dem BungeeCord-Proxy** installieren.
**Schritt-für-Schritt:**
**1. JAR auf jeden Spigot-Server kopieren**
Kopiere die `TeleportSuite.jar` in den `plugins`-Ordner von **jedem einzelnen** Spigot-Server in deinem Netzwerk (z.B. Lobby, Survival, Creative, ...).
**2. JAR auf den BungeeCord-Proxy kopieren**
Kopiere dieselbe `TeleportSuite.jar` auch in den `plugins`-Ordner deines **BungeeCord-Proxys**. Das Plugin erkennt automatisch ob es auf Spigot oder BungeeCord läuft.
**3. Jeden Server einmal starten**
Starte jeden Server einmal kurz, damit die `config.yml` angelegt wird. Dann stoppe ihn wieder.
**4. config.yml auf jedem Spigot-Server anpassen**
Öffne die `plugins/TeleportSuite/config.yml` auf **jedem Spigot-Server** und passe folgende Einstellungen an:
```yaml
bungee:
enabled: true # ← MUSS auf true stehen, sonst kein Cross-Server-Teleport!
server-name: "survival" # ← Den Namen dieses Servers eintragen (siehe unten)
```
> **Woher bekomme ich den `server-name`?**
> Öffne die `config.yml` deines **BungeeCord-Proxys** (nicht des Spigot-Servers!).
> Dort findest du einen Abschnitt wie diesen:
> ```yaml
> servers:
> lobby:
> address: localhost:25566
> survival:
> address: localhost:25567
> creative:
> address: localhost:25568
> ```
> Der `server-name` in der TeleportSuite-Config muss **exakt** dem Namen aus dieser Liste entsprechen.
> Beispiel: Auf dem Survival-Server trägst du `server-name: "survival"` ein.
> Auf dem Lobby-Server trägst du `server-name: "lobby"` ein. Und so weiter.
**5. Datenbank einrichten (empfohlen: MySQL)**
Damit alle Server auf dieselben Homes, Warps usw. zugreifen, solltest du MySQL verwenden und auf jedem Spigot-Server dieselben Zugangsdaten eintragen:
```yaml
database:
type: sqlite
type: mysql
mysql:
host: localhost # Adresse deines MySQL-Servers
port: 3306
database: teleportsuite
username: root
password: deinPasswort
```
**6. Alle Server neu starten**
Starte jetzt alle Spigot-Server und den BungeeCord-Proxy neu. Wenn alles korrekt konfiguriert ist, siehst du beim Start des jeweiligen Spigot-Servers in der Konsole:
```
[TeleportSuite] BungeeCord-Unterstuetzung aktiviert. Server: survival
```
Falls du stattdessen diese Warnung siehst:
```
[TeleportSuite] BungeeCord deaktiviert (bungee.enabled=false).
```
→ Dann hast du in der `config.yml` dieses Servers `enabled: false` stehen gelassen. Auf `true` ändern und neu starten.
---
## Konfiguration
Die vollständige `config.yml` mit allen Optionen:
```yaml
database:
type: sqlite # sqlite oder mysql
mysql:
host: localhost
port: 3306
@@ -46,144 +132,101 @@ database:
pool-size: 10
sqlite:
file: teleportsuite.db
```
- `sqlite` ist die Standard-Einstellung und benötigt keine zusätzliche Serverdatenbank.
- `mysql` ist sinnvoll, wenn mehrere Server auf dieselben Teleport-Daten zugreifen sollen.
### BungeeCord
```yaml
bungee:
enabled: false
server-name: "survival"
```
enabled: true
server-name: "survival" # Name dieses Servers in der BungeeCord config.yml
- Aktiviere `enabled: true`, wenn das Plugin im BungeeCord-Setup genutzt werden soll.
- `server-name` muss dem Namen des Servers im Netzwerk entsprechen.
### Teleport
```yaml
teleport:
delay: 3
cooldown: 5
warmup-cancel-on-move: true
request-timeout: 60
```
delay: 3 # Wartezeit in Sekunden vor dem Teleport (0 = sofort)
cooldown: 5 # Cooldown in Sekunden zwischen Teleports
warmup-cancel-on-move: true # Teleport abbrechen wenn Spieler sich bewegt
request-timeout: 60 # Sekunden bis eine TPA-Anfrage automatisch verfällt
- `delay` ist die Wartezeit vor einem Teleport.
- `cooldown` verhindert zu häufige Teleports.
- `warmup-cancel-on-move` bricht den Teleport ab, wenn sich der Spieler bewegt.
- `request-timeout` legt fest, wie lange eine TPA-Anfrage gültig bleibt.
### Homes
```yaml
homes:
max-homes-default: 3
max-homes-vip: 10
max-homes-premium: 25
```
### Warps
```yaml
warps:
allow-player-warps: false
warp-permission-prefix: "teleportsuite.warp."
```
### Portale
```yaml
portals:
check-interval: 5
particle-effect: true
```
### Spawn
```yaml
spawn:
first-join-teleport: true
death-respawn-to-spawn: false
```
### Nachrichten
Alle Nachrichten unterstützen `&`-Farbcodes und Platzhalter wie `{player}`, `{name}`, `{seconds}` und `{max}`.
---
## Commands
| Command | Beschreibung | Permission |
| --- | --- | --- |
| /tp <player> | Teleportiere zu einem Spieler | teleportsuite.tp |
| /tphere <player> | Teleportiere einen Spieler zu dir | teleportsuite.tphere |
| /tpa <player> | Sende eine Teleportanfrage | teleportsuite.tpa |
| /tpaccept | Akzeptiere eine Teleportanfrage | teleportsuite.tpaccept |
| /tpdeny | Lehne eine Teleportanfrage ab | teleportsuite.tpdeny |
| /back | Teleportiere zur letzten Position | teleportsuite.back |
| /deathback | Teleportiere zum letzten Todesort | teleportsuite.deathback |
| /sethome [name] | Setze ein Home | teleportsuite.sethome |
| /home [name] | Teleportiere zu einem Home | teleportsuite.home |
| /delhome <name> | Lösche ein Home | teleportsuite.delhome |
| /homes | Liste alle Homes auf | teleportsuite.home |
| /setwarp <name> | Setze einen Warp | teleportsuite.setwarp |
| /warp <name> | Teleportiere zu einem Warp | teleportsuite.warp |
| /delwarp <name> | Lösche einen Warp | teleportsuite.delwarp |
| /warps | Liste alle Warps auf | teleportsuite.warp |
| /setportal <name> <target-server/world> | Erstelle ein Portal | teleportsuite.setportal |
| /delportal <name> | Lösche ein Portal | teleportsuite.delportal |
| /portals | Liste alle Portale auf | teleportsuite.portals |
| /setsavepoint [name] | Setze einen Savepoint | teleportsuite.savepoint |
| /savepoint [name] | Teleportiere zu einem Savepoint | teleportsuite.savepoint |
| /setspawn | Setze den Spawn | teleportsuite.setspawn |
| /spawn | Teleportiere zum Spawn | teleportsuite.spawn |
| /setfirstspawn | Setze den FirstSpawn | teleportsuite.setfirstspawn |
| /tppos <x> <y> <z> [world] | Teleportiere zu Koordinaten | teleportsuite.tppos |
| /tpall | Teleportiere alle Spieler zu dir | teleportsuite.tpall |
| /tpworld <world> | Teleportiere in eine Welt | teleportsuite.tpworld |
| /entitytransport <entity-id> <player/world> | Transportiere ein Entity | teleportsuite.entitytransport |
|---|---|---|
| `/tp <spieler>` | Teleportiere zu einem Spieler | `teleportsuite.tp` |
| `/tphere <spieler>` | Teleportiere einen Spieler zu dir | `teleportsuite.tphere` |
| `/tpa <spieler>` | Sende eine Teleportanfrage | `teleportsuite.tpa` |
| `/tpaccept` | Akzeptiere eine Teleportanfrage | `teleportsuite.tpaccept` |
| `/tpdeny` | Lehne eine Teleportanfrage ab | `teleportsuite.tpdeny` |
| `/back` | Teleportiere zur letzten Position | `teleportsuite.back` |
| `/deathback` | Teleportiere zum letzten Todesort | `teleportsuite.deathback` |
| `/sethome [name]` | Setze ein Home | `teleportsuite.sethome` |
| `/home [name]` | Teleportiere zu einem Home | `teleportsuite.home` |
| `/delhome <name>` | Lösche ein Home | `teleportsuite.delhome` |
| `/homes` | Liste alle Homes auf | `teleportsuite.home` |
| `/setwarp <name>` | Setze einen Warp | `teleportsuite.setwarp` |
| `/warp <name>` | Teleportiere zu einem Warp | `teleportsuite.warp` |
| `/delwarp <name>` | Lösche einen Warp | `teleportsuite.delwarp` |
| `/warps` | Liste alle Warps auf | `teleportsuite.warp` |
| `/setportal <name> <server/welt>` | Erstelle ein Portal | `teleportsuite.setportal` |
| `/delportal <name>` | Lösche ein Portal | `teleportsuite.delportal` |
| `/portals` | Liste alle Portale auf | `teleportsuite.portals` |
| `/setsavepoint [name]` | Setze einen Savepoint | `teleportsuite.savepoint` |
| `/savepoint [name]` | Teleportiere zu einem Savepoint | `teleportsuite.savepoint` |
| `/setspawn` | Setze den Spawn | `teleportsuite.setspawn` |
| `/spawn` | Teleportiere zum Spawn | `teleportsuite.spawn` |
| `/setfirstspawn` | Setze den FirstSpawn (für neue Spieler) | `teleportsuite.setfirstspawn` |
| `/tppos <x> <y> <z> [welt]` | Teleportiere zu Koordinaten | `teleportsuite.tppos` |
| `/tpall` | Teleportiere alle Spieler zu dir | `teleportsuite.tpall` |
| `/tpworld <welt>` | Teleportiere in eine Welt | `teleportsuite.tpworld` |
| `/entitytransport <id> <spieler/welt>` | Transportiere ein Entity | `teleportsuite.entitytransport` |
---
## Permissions
### Sammelrechte
| Permission | Beschreibung |
|---|---|
| `teleportsuite.*` | Alle Rechte des Plugins |
| `teleportsuite.home.unlimited` | Unbegrenzte Homes (Standard: nur OPs) |
| `teleportsuite.nodelay` | Kein Teleport-Warmup |
| `teleportsuite.nocooldown` | Kein Teleport-Cooldown |
| `teleportsuite.admin` | Andere Spieler teleportieren (`/tp <von> <zu>`) |
- `teleportsuite.*` - Alle Rechte des Plugins
- `teleportsuite.home.unlimited` - Unbegrenzte Homes, standardmäßig nur für OPs
Alle weiteren Einzelrechte entsprechen dem jeweiligen Command-Namen, z.B. `teleportsuite.tp`, `teleportsuite.home`, `teleportsuite.warp` usw.
### Wichtige Einzelrechte
---
- `teleportsuite.tp`
- `teleportsuite.tphere`
- `teleportsuite.tpa`
- `teleportsuite.tpaccept`
- `teleportsuite.tpdeny`
- `teleportsuite.back`
- `teleportsuite.deathback`
- `teleportsuite.sethome`
- `teleportsuite.home`
- `teleportsuite.delhome`
- `teleportsuite.setwarp`
- `teleportsuite.warp`
- `teleportsuite.delwarp`
- `teleportsuite.setportal`
- `teleportsuite.delportal`
- `teleportsuite.portals`
- `teleportsuite.savepoint`
- `teleportsuite.setspawn`
- `teleportsuite.spawn`
- `teleportsuite.setfirstspawn`
- `teleportsuite.tppos`
- `teleportsuite.tpall`
- `teleportsuite.tpworld`
- `teleportsuite.entitytransport`
## Häufige Probleme
**„Spieler XY nicht gefunden" beim serverübergreifenden `/tp`**
`bungee.enabled` in der `config.yml` steht auf `false`. Auf `true` setzen und neu starten.
**Spieler landet am Spawn statt beim Zielspieler**
`server-name` in der `config.yml` stimmt nicht mit dem Namen in der BungeeCord `config.yml` überein.
**TPA-Nachrichten kommen nicht an**
→ Das Plugin läuft nicht auf dem BungeeCord-Proxy. Die JAR muss auch in den `plugins`-Ordner des Proxys.
**Homes/Warps sind auf anderen Servern nicht verfügbar**
→ Alle Server müssen dieselbe MySQL-Datenbank verwenden. SQLite funktioniert nur lokal auf einem Server.
---
## Support
Wenn du Probleme, Wünsche oder Fehlerberichte hast, eröffne ein Issue auf GitHub und füge wenn möglich den vollständigen Server-Log sowie deine `config.yml` bei.
## Lizenz
Falls du eine Lizenz verwenden möchtest, ergänze sie bitte in diesem Abschnitt oder als separate LICENSE-Datei im Repository.
Probleme, Wünsche oder Fehlerberichte bitte als Issue auf GitHub melden. Füge wenn möglich den vollständigen Server-Log sowie deine `config.yml` bei.

View File

@@ -7,7 +7,7 @@
<groupId>de.teleportsuite</groupId>
<artifactId>TeleportSuite</artifactId>
<version>1.0.0</version>
<version>1.0.3</version>
<packaging>jar</packaging>
<properties>

View File

@@ -42,9 +42,19 @@ public class TeleportSuite extends JavaPlugin {
savePointManager = new SavePointManager(this);
if (configManager.isBungeeEnabled()) {
String serverName = configManager.getServerName();
if (serverName == null || serverName.isBlank() || serverName.equals("survival")) {
getLogger().warning("==================================================");
getLogger().warning("BUNGEE: bungee.server-name in config.yml ist noch");
getLogger().warning("auf dem Default-Wert 'survival'. Bitte auf den");
getLogger().warning("tatsaechlichen BungeeCord-Servernamen aendern!");
getLogger().warning("==================================================");
}
bungeeMessenger = new BungeeMessenger(this);
bungeeMessenger.register();
getLogger().info("BungeeCord-Unterstuetzung aktiviert.");
getLogger().info("BungeeCord-Unterstuetzung aktiviert. Server: " + serverName);
} else {
getLogger().warning("BungeeCord deaktiviert (bungee.enabled=false). Cross-Server-Teleport nicht verfuegbar.");
}
getServer().getPluginManager().registerEvents(new PlayerJoinListener(this), this);

View File

@@ -0,0 +1,38 @@
package de.teleportsuite.bungee;
import de.teleportsuite.bungee.listener.PlayerConnectionListener;
import de.teleportsuite.bungee.manager.TeleportMessageListener;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.api.plugin.PluginManager;
public class TeleportSuiteBungee extends Plugin {
public static final String CHANNEL_TO_BUNGEE = "teleportsuite:tobungee";
public static final String CHANNEL_TO_SPIGOT = "teleportsuite:tospigot";
private static TeleportSuiteBungee instance;
@Override
public void onEnable() {
instance = this;
PluginManager pm = getProxy().getPluginManager();
getProxy().registerChannel(CHANNEL_TO_BUNGEE);
getProxy().registerChannel(CHANNEL_TO_SPIGOT);
pm.registerListener(this, new TeleportMessageListener(this));
pm.registerListener(this, new PlayerConnectionListener(this));
getLogger().info("TeleportSuite-Bungee aktiviert.");
}
@Override
public void onDisable() {
getProxy().getScheduler().cancel(this);
getLogger().info("TeleportSuite-Bungee deaktiviert.");
}
public static TeleportSuiteBungee getInstance() {
return instance;
}
}

View File

@@ -0,0 +1,58 @@
package de.teleportsuite.bungee.listener;
import de.teleportsuite.bungee.TeleportSuiteBungee;
import de.teleportsuite.bungee.manager.PendingTpa;
import de.teleportsuite.bungee.manager.TeleportMessageListener;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
import java.io.*;
/**
* Cleans up pending TPA requests when a player disconnects.
*/
public class PlayerConnectionListener implements Listener {
private final TeleportSuiteBungee plugin;
public PlayerConnectionListener(TeleportSuiteBungee plugin) {
this.plugin = plugin;
}
@EventHandler
public void onDisconnect(PlayerDisconnectEvent event) {
String name = event.getPlayer().getName();
// Player was a requester
PendingTpa tpa = TeleportMessageListener.getPendingTpa().remove(name);
if (tpa != null) {
notifyOther(tpa.getToName(), name);
return;
}
// Player was a target — find the requester
TeleportMessageListener.getPendingTpa().entrySet().removeIf(entry -> {
if (entry.getValue().getToName().equalsIgnoreCase(name)) {
notifyOther(entry.getValue().getFromName(), name);
return true;
}
return false;
});
}
private void notifyOther(String otherName, String disconnectedName) {
ProxiedPlayer other = plugin.getProxy().getPlayer(otherName);
if (other == null || other.getServer() == null) return;
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(bos)) {
out.writeUTF("SEND_MSG");
out.writeUTF(otherName);
out.writeUTF("§cDeine TPA-Anfrage wurde abgebrochen, da §6" + disconnectedName + " §cdas Netzwerk verlassen hat.");
other.getServer().sendData(TeleportSuiteBungee.CHANNEL_TO_SPIGOT, bos.toByteArray());
} catch (IOException e) {
plugin.getLogger().warning("Disconnect-Benachrichtigung fehlgeschlagen: " + e.getMessage());
}
}
}

View File

@@ -0,0 +1,23 @@
package de.teleportsuite.bungee.manager;
/**
* Represents a pending cross-server TPA request.
*/
public class PendingTpa {
public enum Type { TPTO, TPHERE }
private final String fromName;
private final String toName;
private final Type type;
public PendingTpa(String fromName, String toName, Type type) {
this.fromName = fromName;
this.toName = toName;
this.type = type;
}
public String getFromName() { return fromName; }
public String getToName() { return toName; }
public Type getType() { return type; }
}

View File

@@ -0,0 +1,413 @@
package de.teleportsuite.bungee.manager;
import de.teleportsuite.bungee.TeleportSuiteBungee;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.connection.Server;
import net.md_5.bungee.api.event.PluginMessageEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* Receives plugin messages from Spigot servers on CHANNEL_TO_BUNGEE,
* performs the cross-server operation (connect + forward), and sends
* results back on CHANNEL_TO_SPIGOT.
*
* Payload identifiers (first UTF written by Spigot):
*
* TP_PLAYER teleport sender to a named target player
* TP_POS teleport player to fixed coordinates on a server
* TP_HERE pull a remote player to the sender's location
* TP_ALL pull all network players to sender
* TPA_REQUEST forward "you have a TPA request" to target
* TPA_ACCEPT accept pending TPA; trigger the actual teleport
* TPA_DENY deny pending TPA; notify requester
* TPA_CANCEL requester cancels their own pending request
* TPA_EXPIRED timeout: notify both parties
* SEND_MSG route a chat message to a player on any server
*/
public class TeleportMessageListener implements Listener {
// fromName → pending request
private static final Map<String, PendingTpa> pendingTpa = new HashMap<>();
private final TeleportSuiteBungee plugin;
public TeleportMessageListener(TeleportSuiteBungee plugin) {
this.plugin = plugin;
}
public static Map<String, PendingTpa> getPendingTpa() {
return pendingTpa;
}
// -------------------------------------------------------------------------
// Incoming messages from Spigot
// -------------------------------------------------------------------------
@EventHandler
public void onPluginMessage(PluginMessageEvent event) throws IOException {
if (event.isCancelled()) return;
if (!(event.getSender() instanceof Server)) return;
if (!event.getTag().equals(TeleportSuiteBungee.CHANNEL_TO_BUNGEE)) return;
DataInputStream in = new DataInputStream(new ByteArrayInputStream(event.getData()));
String task = in.readUTF();
switch (task) {
// ------------------------------------------------------------------
// /tp <target> → teleport sender directly to target player
// ------------------------------------------------------------------
case "TP_PLAYER": {
String senderName = in.readUTF();
String targetName = in.readUTF();
ProxiedPlayer sender = plugin.getProxy().getPlayer(senderName);
ProxiedPlayer target = plugin.getProxy().getPlayer(targetName);
if (sender == null) return;
if (target == null) {
sendMsg(sender, "§cSpieler §6" + targetName + " §cnicht gefunden.");
return;
}
teleportPlayerToPlayer(sender, target, 50);
break;
}
// ------------------------------------------------------------------
// /tp <from> <to> → teleport another player to a target player
// ------------------------------------------------------------------
case "TP_PLAYER_TO_PLAYER": {
String requesterName = in.readUTF();
String fromName = in.readUTF();
String targetName = in.readUTF();
ProxiedPlayer requester = plugin.getProxy().getPlayer(requesterName);
ProxiedPlayer from = plugin.getProxy().getPlayer(fromName);
ProxiedPlayer target = plugin.getProxy().getPlayer(targetName);
if (requester == null) return;
if (from == null || target == null) {
sendMsg(requester, "§cEin Spieler wurde nicht gefunden.");
return;
}
teleportPlayerToPlayer(from, target, 50);
break;
}
// ------------------------------------------------------------------
// /tphere <target> → pull target to sender's location
// ------------------------------------------------------------------
case "TP_HERE": {
String senderName = in.readUTF();
String targetName = in.readUTF();
ProxiedPlayer sender = plugin.getProxy().getPlayer(senderName);
ProxiedPlayer target = plugin.getProxy().getPlayer(targetName);
if (sender == null) return;
if (target == null) {
sendMsg(sender, "§cSpieler §6" + targetName + " §cnicht gefunden.");
return;
}
teleportPlayerToPlayer(target, sender, 50);
break;
}
// ------------------------------------------------------------------
// /tpall → pull every player on the network to sender
// ------------------------------------------------------------------
case "TP_ALL": {
String senderName = in.readUTF();
ProxiedPlayer sender = plugin.getProxy().getPlayer(senderName);
if (sender == null) return;
for (ProxiedPlayer p : plugin.getProxy().getPlayers()) {
if (!p.getName().equals(senderName)) {
teleportPlayerToPlayer(p, sender, 50);
}
}
break;
}
// ------------------------------------------------------------------
// /home, /warp, /spawn, /back, /savepoint, /portal, /tppos …
// Spigot already knows the coordinates; we just switch the server
// and tell that server where to put the player.
// ------------------------------------------------------------------
case "TP_POS": {
String playerName = in.readUTF();
String server = in.readUTF();
String world = in.readUTF();
double x = in.readDouble(), y = in.readDouble(), z = in.readDouble();
float yaw = in.readFloat(), pitch = in.readFloat();
ProxiedPlayer player = plugin.getProxy().getPlayer(playerName);
if (player == null) return;
teleportPlayerToPosition(player, server, world, x, y, z, yaw, pitch, 100);
break;
}
// ------------------------------------------------------------------
// TPA: requester asks target for a teleport
// ------------------------------------------------------------------
case "TPA_REQUEST": {
String fromName = in.readUTF();
String toName = in.readUTF();
String type = in.readUTF(); // TPTO or TPHERE
String msgToTarget = in.readUTF();
String msgToRequester = in.readUTF();
ProxiedPlayer from = plugin.getProxy().getPlayer(fromName);
ProxiedPlayer to = plugin.getProxy().getPlayer(toName);
if (from == null) return;
if (to == null) {
sendMsg(from, "§cSpieler §6" + toName + " §cnicht gefunden.");
return;
}
// Check for existing pending request
if (pendingTpa.containsKey(fromName)) {
sendMsg(from, "§cDu hast bereits eine offene Anfrage.");
return;
}
pendingTpa.put(fromName, new PendingTpa(fromName, toName, PendingTpa.Type.valueOf(type)));
// Notify both players — via their respective servers
sendMsgToServer(from.getServer().getInfo(), fromName, msgToRequester);
sendMsgToServer(to.getServer().getInfo(), toName, msgToTarget);
break;
}
// ------------------------------------------------------------------
// TPA: target accepts → trigger the actual teleport
// ------------------------------------------------------------------
case "TPA_ACCEPT": {
String toName = in.readUTF(); // player who accepted
String fromName = in.readUTF(); // original requester (may be "nu" = any)
String errMsg = in.readUTF();
PendingTpa tpa = resolvePending(fromName, toName);
if (tpa == null) {
ProxiedPlayer to = plugin.getProxy().getPlayer(toName);
if (to != null) sendMsg(to, errMsg);
return;
}
pendingTpa.remove(tpa.getFromName());
ProxiedPlayer from = plugin.getProxy().getPlayer(tpa.getFromName());
ProxiedPlayer to = plugin.getProxy().getPlayer(tpa.getToName());
if (from == null || to == null) return;
if (tpa.getType() == PendingTpa.Type.TPTO) {
teleportPlayerToPlayer(from, to, 50);
} else {
teleportPlayerToPlayer(to, from, 50);
}
break;
}
// ------------------------------------------------------------------
// TPA: target denies → notify requester
// ------------------------------------------------------------------
case "TPA_DENY": {
String toName = in.readUTF();
String fromName = in.readUTF();
String msg = in.readUTF();
PendingTpa tpa = resolvePending(fromName, toName);
if (tpa == null) return;
pendingTpa.remove(tpa.getFromName());
ProxiedPlayer from = plugin.getProxy().getPlayer(tpa.getFromName());
ProxiedPlayer to = plugin.getProxy().getPlayer(tpa.getToName());
if (from != null) sendMsg(from, msg);
if (to != null) sendMsg(to, msg);
break;
}
// ------------------------------------------------------------------
// TPA: requester cancels their own request
// ------------------------------------------------------------------
case "TPA_CANCEL": {
String fromName = in.readUTF();
String msgFrom = in.readUTF();
String msgTo = in.readUTF();
PendingTpa tpa = pendingTpa.remove(fromName);
if (tpa == null) return;
ProxiedPlayer from = plugin.getProxy().getPlayer(fromName);
ProxiedPlayer to = plugin.getProxy().getPlayer(tpa.getToName());
if (from != null) sendMsg(from, msgFrom);
if (to != null) sendMsg(to, msgTo);
break;
}
// ------------------------------------------------------------------
// TPA: timeout — remove pending and notify both sides
// ------------------------------------------------------------------
case "TPA_EXPIRED": {
String fromName = in.readUTF();
String toName = in.readUTF();
String msgFrom = in.readUTF();
String msgTo = in.readUTF();
pendingTpa.remove(fromName);
ProxiedPlayer from = plugin.getProxy().getPlayer(fromName);
ProxiedPlayer to = plugin.getProxy().getPlayer(toName);
if (from != null) sendMsg(from, msgFrom);
if (to != null) sendMsg(to, msgTo);
break;
}
// ------------------------------------------------------------------
// Generic cross-server message routing
// ------------------------------------------------------------------
case "SEND_MSG": {
String targetName = in.readUTF();
String message = in.readUTF();
ProxiedPlayer target = plugin.getProxy().getPlayer(targetName);
if (target != null) sendMsg(target, message);
break;
}
default:
plugin.getLogger().warning("Unbekannter Task: " + task);
}
}
// -------------------------------------------------------------------------
// Core teleport helpers — the BTM way
// -------------------------------------------------------------------------
/**
* Moves {@code sender} to {@code target}'s current server (if needed),
* then after a short delay tells the target server to do the final
* player.teleport(target) call via TP_PLAYERTOPLAYER.
*
* This is done entirely on the Bungee side:
* 1. sender.connect(target.server) — BungeeCord switches the server
* 2. delay ms later: server.sendData(TP_PLAYERTOPLAYER, ...)
* → Spigot polls until both players are on the same server and teleports
*/
private void teleportPlayerToPlayer(ProxiedPlayer sender, ProxiedPlayer target, int delayMs) {
plugin.getProxy().getScheduler().schedule(plugin, () -> {
if (sender == null || target == null) return;
if (sender.getServer() == null || target.getServer() == null) return;
// Switch server if needed
if (!sender.getServer().getInfo().getName()
.equals(target.getServer().getInfo().getName())) {
sender.connect(target.getServer().getInfo());
}
// Tell the target server to teleport sender → target
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(bos)) {
out.writeUTF("TP_PLAYERTOPLAYER");
out.writeUTF(sender.getName());
out.writeUTF(target.getName());
target.getServer().sendData(TeleportSuiteBungee.CHANNEL_TO_SPIGOT, bos.toByteArray());
} catch (IOException e) {
plugin.getLogger().warning("TP_PLAYERTOPLAYER Fehler: " + e.getMessage());
}
}, delayMs, TimeUnit.MILLISECONDS);
}
/**
* Moves {@code player} to {@code server}, then after a delay sends
* TP_PLAYERTOPOSITION so Spigot teleports them to exact coordinates.
*/
private void teleportPlayerToPosition(ProxiedPlayer player, String server,
String world, double x, double y, double z,
float yaw, float pitch, int delayMs) {
if (!plugin.getProxy().getServers().containsKey(server)) {
sendMsg(player, "§cServer §6" + server + " §cnicht gefunden.");
return;
}
// Switch server if needed
if (!player.getServer().getInfo().getName().equals(server)) {
player.connect(plugin.getProxy().getServerInfo(server));
}
// After delay, tell the (now correct) server where to put the player
plugin.getProxy().getScheduler().schedule(plugin, () -> {
if (player.getServer() == null) return;
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(bos)) {
out.writeUTF("TP_PLAYERTOPOSITION");
out.writeUTF(player.getName());
out.writeUTF(world);
out.writeDouble(x);
out.writeDouble(y);
out.writeDouble(z);
out.writeFloat(yaw);
out.writeFloat(pitch);
player.getServer().sendData(TeleportSuiteBungee.CHANNEL_TO_SPIGOT, bos.toByteArray());
} catch (IOException e) {
plugin.getLogger().warning("TP_PLAYERTOPOSITION Fehler: " + e.getMessage());
}
}, delayMs, TimeUnit.MILLISECONDS);
}
// -------------------------------------------------------------------------
// Helpers
// -------------------------------------------------------------------------
/** Resolves which pending TPA entry matches an accept/deny. */
private PendingTpa resolvePending(String fromName, String toName) {
// Exact match
if (!fromName.equals("nu") && pendingTpa.containsKey(fromName)) {
return pendingTpa.get(fromName);
}
// Find by target name only
for (PendingTpa tpa : pendingTpa.values()) {
if (tpa.getToName().equalsIgnoreCase(toName)) {
return tpa;
}
}
return null;
}
/** Sends a formatted chat message directly to a ProxiedPlayer. */
private void sendMsg(ProxiedPlayer player, String message) {
player.sendMessage(net.md_5.bungee.api.ChatColor.translateAlternateColorCodes('&', message));
}
/**
* Routes a chat message to a named player via their Spigot server.
* The Spigot side handles the actual sendMessage() call.
*/
private void sendMsgToServer(net.md_5.bungee.api.config.ServerInfo server,
String playerName, String message) {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(bos)) {
out.writeUTF("SEND_MSG");
out.writeUTF(playerName);
out.writeUTF(message);
server.sendData(TeleportSuiteBungee.CHANNEL_TO_SPIGOT, bos.toByteArray());
} catch (IOException e) {
plugin.getLogger().warning("SEND_MSG Fehler: " + e.getMessage());
}
}
}

View File

@@ -1,105 +1,285 @@
package de.teleportsuite.bungeemessaging;
import de.teleportsuite.TeleportSuite;
import de.teleportsuite.models.TeleportLocation;
import org.bukkit.entity.Player;
import org.bukkit.plugin.messaging.PluginMessageListener;
import java.io.*;
/**
* Handles BungeeCord Plugin Messaging.
* Sends players to other servers and transmits target coordinates
* so a receiving TeleportSuite instance can teleport them on arrival.
* Spigot-seitiger Kanal zum TeleportSuite-Bungee-Plugin.
*
* Channel "teleportsuite:tp" payload format (DataOutputStream):
* String targetPlayer
* String world
* Double x, y, z
* Float yaw, pitch
* Prinzip (identisch zu BTM):
* Spigot schickt Anfragen auf CHANNEL_TO_BUNGEE.
* BungeeCord erledigt connect() + routing und schickt Befehle auf CHANNEL_TO_SPIGOT.
* Spigot führt den finalen player.teleport() aus.
*
* Payloads Spigot → Bungee (CHANNEL_TO_BUNGEE):
* TP_PLAYER senderName, targetName
* TP_PLAYER_TO_PLAYER requesterName, fromName, toName
* TP_HERE senderName, targetName
* TP_ALL senderName
* TP_POS playerName, server, world, x, y, z, yaw, pitch
* TPA_REQUEST fromName, toName, type, msgToTarget, msgToRequester
* TPA_ACCEPT toName, fromName, errMsg
* TPA_DENY toName, fromName, msg
* TPA_CANCEL fromName, msgFrom, msgTo
* TPA_EXPIRED fromName, toName, msgFrom, msgTo
* SEND_MSG targetName, message
*
* Payloads Bungee → Spigot (CHANNEL_TO_SPIGOT):
* TP_PLAYERTOPLAYER senderName, targetName
* TP_PLAYERTOPOSITION playerName, world, x, y, z, yaw, pitch
* SEND_MSG playerName, message
*/
public class BungeeMessenger implements PluginMessageListener {
private static final String BUNGEE_CHANNEL = "BungeeCord";
private static final String TS_CHANNEL = "teleportsuite:tp";
public static final String CHANNEL_TO_BUNGEE = "teleportsuite:tobungee";
public static final String CHANNEL_TO_SPIGOT = "teleportsuite:tospigot";
private final TeleportSuite plugin;
public BungeeMessenger(TeleportSuite plugin) { this.plugin = plugin; }
public BungeeMessenger(TeleportSuite plugin) {
this.plugin = plugin;
}
public void register() {
plugin.getServer().getMessenger().registerOutgoingPluginChannel(plugin, BUNGEE_CHANNEL);
plugin.getServer().getMessenger().registerOutgoingPluginChannel(plugin, TS_CHANNEL);
plugin.getServer().getMessenger().registerIncomingPluginChannel(plugin, TS_CHANNEL, this);
plugin.getServer().getMessenger().registerOutgoingPluginChannel(plugin, CHANNEL_TO_BUNGEE);
plugin.getServer().getMessenger().registerIncomingPluginChannel(plugin, CHANNEL_TO_SPIGOT, this);
}
public void unregister() {
plugin.getServer().getMessenger().unregisterOutgoingPluginChannel(plugin);
plugin.getServer().getMessenger().unregisterIncomingPluginChannel(plugin);
plugin.getServer().getMessenger().unregisterOutgoingPluginChannel(plugin, CHANNEL_TO_BUNGEE);
plugin.getServer().getMessenger().unregisterIncomingPluginChannel(plugin, CHANNEL_TO_SPIGOT, this);
}
// -------------------------------------------------------------------------
// Outgoing helpers (Spigot → Bungee)
// -------------------------------------------------------------------------
/** /tp <target> Absender teleportiert sich zum Zielspieler */
public void teleportToPlayer(Player sender, String targetName) {
send(sender, out -> {
out.writeUTF("TP_PLAYER");
out.writeUTF(sender.getName());
out.writeUTF(targetName);
});
}
/** /tp <from> <to> Admin teleportiert einen Spieler zu einem anderen */
public void teleportPlayerToPlayer(Player requester, String fromName, String targetName) {
send(requester, out -> {
out.writeUTF("TP_PLAYER_TO_PLAYER");
out.writeUTF(requester.getName());
out.writeUTF(fromName);
out.writeUTF(targetName);
});
}
/** /tphere <target> Zielspieler wird zu Absender geholt */
public void teleportHere(Player sender, String targetName) {
send(sender, out -> {
out.writeUTF("TP_HERE");
out.writeUTF(sender.getName());
out.writeUTF(targetName);
});
}
/** /tpall Alle Netzwerkspieler zum Absender teleportieren */
public void teleportAll(Player sender) {
send(sender, out -> {
out.writeUTF("TP_ALL");
out.writeUTF(sender.getName());
});
}
/**
* Connect a player to another BungeeCord server.
* Also sends a plugin message so the target server knows where to teleport the player.
* Home / Warp / Spawn / Back / SavePoint / Portal / TpPos:
* Koordinaten sind bekannt → Bungee wechselt den Server und Spigot
* setzt den Spieler direkt an die exakten Koordinaten.
*/
public void connectToServer(Player player, String server, String world, double x, double y, double z, float yaw, float pitch) {
// 1) Notify the target server about the pending teleport
sendTeleportPayload(player, player.getName(), server, world, x, y, z, yaw, pitch);
// 2) Switch server via BungeeCord
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(bos)) {
out.writeUTF("Connect");
public void teleportToPosition(Player player, String server, String world,
double x, double y, double z, float yaw, float pitch) {
send(player, out -> {
out.writeUTF("TP_POS");
out.writeUTF(player.getName());
out.writeUTF(server);
player.sendPluginMessage(plugin, BUNGEE_CHANNEL, bos.toByteArray());
} catch (IOException e) {
plugin.getLogger().warning("BungeeCord Connect Fehler: " + e.getMessage());
}
out.writeUTF(world);
out.writeDouble(x);
out.writeDouble(y);
out.writeDouble(z);
out.writeFloat(yaw);
out.writeFloat(pitch);
});
}
private void sendTeleportPayload(Player sender, String targetPlayer, String server, String world,
double x, double y, double z, float yaw, float pitch) {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(bos)) {
out.writeUTF("Forward");
out.writeUTF(server);
out.writeUTF(TS_CHANNEL);
// Sub-payload
ByteArrayOutputStream sub = new ByteArrayOutputStream();
DataOutputStream subOut = new DataOutputStream(sub);
subOut.writeUTF(targetPlayer);
subOut.writeUTF(world);
subOut.writeDouble(x);
subOut.writeDouble(y);
subOut.writeDouble(z);
subOut.writeFloat(yaw);
subOut.writeFloat(pitch);
byte[] subBytes = sub.toByteArray();
out.writeShort(subBytes.length);
out.write(subBytes);
sender.sendPluginMessage(plugin, BUNGEE_CHANNEL, bos.toByteArray());
} catch (IOException e) {
plugin.getLogger().warning("TS Forward Fehler: " + e.getMessage());
}
// TPA
public void sendTpaRequest(Player from, String toName,
String type, String msgToTarget, String msgToRequester) {
send(from, out -> {
out.writeUTF("TPA_REQUEST");
out.writeUTF(from.getName());
out.writeUTF(toName);
out.writeUTF(type);
out.writeUTF(msgToTarget);
out.writeUTF(msgToRequester);
});
}
public void sendTpaAccept(Player acceptor, String fromName, String errMsg) {
send(acceptor, out -> {
out.writeUTF("TPA_ACCEPT");
out.writeUTF(acceptor.getName());
out.writeUTF(fromName == null ? "nu" : fromName);
out.writeUTF(errMsg);
});
}
public void sendTpaDeny(Player denier, String fromName, String msg) {
send(denier, out -> {
out.writeUTF("TPA_DENY");
out.writeUTF(denier.getName());
out.writeUTF(fromName == null ? "nu" : fromName);
out.writeUTF(msg);
});
}
public void sendTpaCancel(Player canceller, String msgFrom, String msgTo) {
send(canceller, out -> {
out.writeUTF("TPA_CANCEL");
out.writeUTF(canceller.getName());
out.writeUTF(msgFrom);
out.writeUTF(msgTo);
});
}
public void sendTpaExpired(Player from, String toName, String msgFrom, String msgTo) {
send(from, out -> {
out.writeUTF("TPA_EXPIRED");
out.writeUTF(from.getName());
out.writeUTF(toName);
out.writeUTF(msgFrom);
out.writeUTF(msgTo);
});
}
// -------------------------------------------------------------------------
// Incoming handler (Bungee → Spigot)
// -------------------------------------------------------------------------
@Override
public void onPluginMessageReceived(String channel, Player player, byte[] message) {
if (!channel.equals(TS_CHANNEL)) return;
try (DataInputStream in = new DataInputStream(new ByteArrayInputStream(message))) {
String targetName = in.readUTF();
String world = in.readUTF();
double x = in.readDouble(), y = in.readDouble(), z = in.readDouble();
float yaw = in.readFloat(), pitch = in.readFloat();
public void onPluginMessageReceived(String channel, Player unused, byte[] bytes) {
if (!channel.equals(CHANNEL_TO_SPIGOT)) return;
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> {
Player target = plugin.getServer().getPlayer(targetName);
if (target == null || !target.isOnline()) return;
de.teleportsuite.models.TeleportLocation loc =
new de.teleportsuite.models.TeleportLocation(world, x, y, z, yaw, pitch,
plugin.getConfigManager().getServerName());
plugin.getTeleportManager().teleport(target, loc, false);
}, 20L);
try (DataInputStream in = new DataInputStream(new ByteArrayInputStream(bytes))) {
String task = in.readUTF();
switch (task) {
// Bungee hat sender bereits auf diesen Server gewechselt.
// Sobald beide Spieler lokal online sind, teleportieren.
case "TP_PLAYERTOPLAYER": {
String senderName = in.readUTF();
String targetName = in.readUTF();
schedulePlayerToPlayerTeleportWithBack(senderName, targetName);
break;
}
// Bungee hat player bereits auf diesen Server gewechselt.
// Nach kurzem Delay an exakte Koordinaten teleportieren.
case "TP_PLAYERTOPOSITION": {
String playerName = in.readUTF();
String world = in.readUTF();
double x = in.readDouble(), y = in.readDouble(), z = in.readDouble();
float yaw = in.readFloat(), pitch = in.readFloat();
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> {
org.bukkit.entity.Player p = plugin.getServer().getPlayerExact(playerName);
if (p == null || !p.isOnline()) return;
// Save back location BEFORE teleporting (teleport() with saveBack=false
// skips this, so we do it manually here for cross-server teleports)
plugin.getDatabaseManager().saveLastLocation(p.getUniqueId(),
new TeleportLocation(p.getLocation(), plugin.getConfigManager().getServerName()));
TeleportLocation dest = new TeleportLocation(
world, x, y, z, yaw, pitch,
plugin.getConfigManager().getServerName());
plugin.getTeleportManager().teleport(p, dest, false);
}, 10L);
break;
}
// Direkte Chat-Nachricht an einen lokalen Spieler
case "SEND_MSG": {
String playerName = in.readUTF();
String message = in.readUTF();
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> {
org.bukkit.entity.Player p = plugin.getServer().getPlayerExact(playerName);
if (p != null && p.isOnline()) p.sendMessage(message);
}, 1L);
break;
}
default:
plugin.getLogger().warning("Unbekannter Bungee-Task: " + task);
}
} catch (IOException e) {
plugin.getLogger().warning("Fehler beim Lesen der TS-Nachricht: " + e.getMessage());
plugin.getLogger().warning("Fehler beim Lesen der Bungee-Nachricht: " + e.getMessage());
}
}
// -------------------------------------------------------------------------
// Internal helpers
// -------------------------------------------------------------------------
/**
* Wartet bis sender UND target lokal online sind (max. 100 × 10 Ticks = 50 s),
* speichert Back-Location und führt dann player.teleport() aus.
*/
private void schedulePlayerToPlayerTeleportWithBack(String senderName, String targetName) {
final int[] attempts = {0};
final int[] taskId = {-1};
taskId[0] = plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, () -> {
attempts[0]++;
org.bukkit.entity.Player sender = plugin.getServer().getPlayerExact(senderName);
org.bukkit.entity.Player target = plugin.getServer().getPlayerExact(targetName);
if (sender != null && sender.isOnline() && target != null && target.isOnline()) {
// Save back location before teleport so /back works cross-server
plugin.getDatabaseManager().saveLastLocation(sender.getUniqueId(),
new TeleportLocation(sender.getLocation(),
plugin.getConfigManager().getServerName()));
plugin.getTeleportManager().teleport(
sender,
new TeleportLocation(target.getLocation(),
plugin.getConfigManager().getServerName()),
false);
plugin.getServer().getScheduler().cancelTask(taskId[0]);
return;
}
if (attempts[0] >= 100) {
plugin.getServer().getScheduler().cancelTask(taskId[0]);
}
}, 5L, 10L);
}
@FunctionalInterface
private interface IOWriter {
void write(DataOutputStream out) throws IOException;
}
/** Schreibt ein Payload und schickt es über den Bungee-Kanal. */
private void send(Player anchor, IOWriter writer) {
if (anchor == null || !anchor.isOnline()) return;
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(bos)) {
writer.write(out);
anchor.sendPluginMessage(plugin, CHANNEL_TO_BUNGEE, bos.toByteArray());
} catch (IOException e) {
plugin.getLogger().warning("Bungee-Send Fehler: " + e.getMessage());
}
}
}

View File

@@ -1,22 +1,27 @@
package de.teleportsuite.commands;
import de.teleportsuite.TeleportSuite;
import de.teleportsuite.models.TeleportLocation;
import org.bukkit.Bukkit;
import org.bukkit.command.*;
import org.bukkit.entity.Player;
public class TpAllCommand implements CommandExecutor {
private final TeleportSuite plugin;
public TpAllCommand(TeleportSuite p) { this.plugin = p; }
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (!(sender instanceof Player)) { sender.sendMessage("§cNur für Spieler!"); return true; }
Player p = (Player) sender;
if (!p.hasPermission("teleportsuite.tpall")) { p.sendMessage(plugin.getConfigManager().getMessage("no-permission")); return true; }
TeleportLocation dest = new TeleportLocation(p.getLocation(), plugin.getConfigManager().getServerName());
for (Player online : Bukkit.getOnlinePlayers()) {
if (!online.equals(p)) plugin.getTeleportManager().teleport(online, dest);
if (plugin.getConfigManager().isBungeeEnabled() && plugin.getBungeeMessenger() != null) {
plugin.getBungeeMessenger().teleportAll(p);
} else {
TeleportLocation dest = new TeleportLocation(p.getLocation(), plugin.getConfigManager().getServerName());
for (Player online : plugin.getServer().getOnlinePlayers()) {
if (!online.equals(p)) plugin.getTeleportManager().teleport(online, dest);
}
}
p.sendMessage("§aAlle Spieler wurden zu dir teleportiert.");
return true;
}
}

View File

@@ -19,14 +19,24 @@ public class TpCommand implements CommandExecutor {
if (args.length == 1) {
Player target = Bukkit.getPlayer(args[0]);
if (target == null) { p.sendMessage(plugin.getConfigManager().getMessage("player-not-found","player",args[0])); return true; }
plugin.getTeleportManager().teleport(p, new TeleportLocation(target.getLocation(), plugin.getConfigManager().getServerName()));
if (target != null) {
plugin.getTeleportManager().teleport(p, new TeleportLocation(target.getLocation(), plugin.getConfigManager().getServerName()));
} else if (plugin.getConfigManager().isBungeeEnabled() && plugin.getBungeeMessenger() != null) {
plugin.getBungeeMessenger().teleportToPlayer(p, args[0]);
} else {
p.sendMessage(plugin.getConfigManager().getMessage("player-not-found", "player", args[0]));
}
} else {
if (!p.hasPermission("teleportsuite.admin")) { p.sendMessage(plugin.getConfigManager().getMessage("no-permission")); return true; }
Player from = Bukkit.getPlayer(args[0]);
Player to = Bukkit.getPlayer(args[1]);
if (from == null || to == null) { p.sendMessage("§cEin Spieler nicht gefunden."); return true; }
if (!p.hasPermission("teleportsuite.admin")) { p.sendMessage(plugin.getConfigManager().getMessage("no-permission")); return true; }
plugin.getTeleportManager().teleport(from, new TeleportLocation(to.getLocation(), plugin.getConfigManager().getServerName()));
if (from != null && to != null) {
plugin.getTeleportManager().teleport(from, new TeleportLocation(to.getLocation(), plugin.getConfigManager().getServerName()));
} else if (plugin.getConfigManager().isBungeeEnabled() && plugin.getBungeeMessenger() != null) {
plugin.getBungeeMessenger().teleportPlayerToPlayer(p, args[0], args[1]);
} else {
p.sendMessage("§cEin Spieler nicht gefunden.");
}
}
return true;
}

View File

@@ -17,8 +17,13 @@ public class TpHereCommand implements CommandExecutor {
if (!p.hasPermission("teleportsuite.tphere")) { p.sendMessage(plugin.getConfigManager().getMessage("no-permission")); return true; }
if (args.length < 1) { p.sendMessage("§cVerwendung: /tphere <spieler>"); return true; }
Player target = Bukkit.getPlayer(args[0]);
if (target == null) { p.sendMessage(plugin.getConfigManager().getMessage("player-not-found","player",args[0])); return true; }
plugin.getTeleportManager().teleport(target, new TeleportLocation(p.getLocation(), plugin.getConfigManager().getServerName()));
if (target != null) {
plugin.getTeleportManager().teleport(target, new TeleportLocation(p.getLocation(), plugin.getConfigManager().getServerName()));
} else if (plugin.getConfigManager().isBungeeEnabled() && plugin.getBungeeMessenger() != null) {
plugin.getBungeeMessenger().teleportHere(p, args[0]);
} else {
p.sendMessage(plugin.getConfigManager().getMessage("player-not-found", "player", args[0]));
}
return true;
}
}

View File

@@ -15,10 +15,18 @@ public class TpaCommand implements CommandExecutor {
Player p = (Player) sender;
if (!p.hasPermission("teleportsuite.tpa")) { p.sendMessage(plugin.getConfigManager().getMessage("no-permission")); return true; }
if (args.length < 1) { p.sendMessage("§cVerwendung: /tpa <spieler>"); return true; }
if (p.getName().equalsIgnoreCase(args[0])) { p.sendMessage("§cDu kannst dir nicht selbst eine Anfrage senden."); return true; }
Player target = Bukkit.getPlayer(args[0]);
if (target == null) { p.sendMessage(plugin.getConfigManager().getMessage("player-not-found","player",args[0])); return true; }
if (target.equals(p)) { p.sendMessage("§cDu kannst dir nicht selbst eine Anfrage senden."); return true; }
plugin.getTeleportManager().sendTpaRequest(p, target);
if (target != null) {
// Same server
plugin.getTeleportManager().sendTpaRequest(p, target);
} else if (plugin.getConfigManager().isBungeeEnabled() && plugin.getBungeeMessenger() != null) {
// Cross-server — Bungee manages the pending state
plugin.getTeleportManager().sendCrossServerTpaRequest(p, args[0]);
} else {
p.sendMessage(plugin.getConfigManager().getMessage("player-not-found", "player", args[0]));
}
return true;
}
}

View File

@@ -2,7 +2,9 @@ package de.teleportsuite.listeners;
import de.teleportsuite.TeleportSuite;
import de.teleportsuite.models.TeleportLocation;
import org.bukkit.Location;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerRespawnEvent;
@@ -10,12 +12,33 @@ public class PlayerRespawnListener implements Listener {
private final TeleportSuite plugin;
public PlayerRespawnListener(TeleportSuite plugin) { this.plugin = plugin; }
@EventHandler
@EventHandler(priority = EventPriority.HIGH)
public void onRespawn(PlayerRespawnEvent event) {
if (!plugin.getConfigManager().deathRespawnToSpawn()) return;
TeleportLocation spawn = plugin.getDatabaseManager().getSpawn("spawn");
if (spawn == null) return;
var loc = spawn.toBukkitLocation();
if (loc != null) event.setRespawnLocation(loc);
if (spawn == null) {
plugin.getLogger().warning("death-respawn-to-spawn ist aktiv, aber kein Spawn gesetzt!");
return;
}
// Spawn ist auf einem anderen Server → nach dem Respawn teleportieren
String localServer = plugin.getConfigManager().getServerName();
if (!spawn.isLocalServer(localServer)) {
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> {
if (event.getPlayer().isOnline()) {
plugin.getTeleportManager().teleport(event.getPlayer(), spawn, false);
}
}, 5L);
return;
}
// Spawn ist lokal → direkt als Respawn-Location setzen
Location loc = spawn.toBukkitLocation();
if (loc == null || loc.getWorld() == null) {
plugin.getLogger().warning("Spawn-Welt \"" + spawn.getWorld() + "\" nicht gefunden!");
return;
}
event.setRespawnLocation(loc);
}
}

View File

@@ -1,6 +1,7 @@
package de.teleportsuite.managers;
import de.teleportsuite.TeleportSuite;
import de.teleportsuite.bungeemessaging.BungeeMessenger;
import de.teleportsuite.models.TeleportLocation;
import org.bukkit.Bukkit;
import org.bukkit.Location;
@@ -10,18 +11,22 @@ import java.util.*;
public class TeleportManager {
private final TeleportSuite plugin;
// Pending TPA requests: requester -> target
// Same-server pending TPA: requesterUUID → targetUUID
private final Map<UUID, UUID> tpaRequests = new HashMap<>();
private final Map<UUID, Long> requestTimestamps = new HashMap<>();
// Cooldowns
private final Map<UUID, Long> cooldowns = new HashMap<>();
// Warmup tasks
private final Map<UUID, Integer> warmupTasks = new HashMap<>();
// Saved "before teleport" locations (for /back)
// Back-locations (saved before every teleport)
private final Map<UUID, TeleportLocation> pendingBackLocations = new HashMap<>();
public TeleportManager(TeleportSuite plugin) { this.plugin = plugin; }
// -------------------------------------------------------------------------
// Main teleport entry point
// -------------------------------------------------------------------------
public void teleport(Player player, TeleportLocation destination) {
teleport(player, destination, true);
}
@@ -30,31 +35,36 @@ public class TeleportManager {
int delay = plugin.getConfigManager().getTeleportDelay();
if (player.hasPermission("teleportsuite.nodelay")) delay = 0;
// Check cooldown
if (!player.hasPermission("teleportsuite.nocooldown")) {
long cooldownMs = plugin.getConfigManager().getTeleportCooldown() * 1000L;
long lastTp = cooldowns.getOrDefault(player.getUniqueId(), 0L);
if (System.currentTimeMillis() - lastTp < cooldownMs) {
long remaining = (cooldownMs - (System.currentTimeMillis() - lastTp)) / 1000;
player.sendMessage(plugin.getConfigManager().getMessage("teleport-cooldown", "seconds", String.valueOf(remaining)));
player.sendMessage(plugin.getConfigManager().getMessage(
"teleport-cooldown", "seconds", String.valueOf(remaining)));
return;
}
}
if (saveBack) pendingBackLocations.put(player.getUniqueId(), new TeleportLocation(player.getLocation(), plugin.getConfigManager().getServerName()));
if (saveBack) {
pendingBackLocations.put(player.getUniqueId(),
new TeleportLocation(player.getLocation(), plugin.getConfigManager().getServerName()));
}
if (delay <= 0) {
executeTeleport(player, destination);
return;
}
player.sendMessage(plugin.getConfigManager().getMessage("teleport-warmup", "seconds", String.valueOf(delay)));
player.sendMessage(plugin.getConfigManager().getMessage(
"teleport-warmup", "seconds", String.valueOf(delay)));
Location startLoc = player.getLocation().clone();
int taskId = Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, () -> {
if (plugin.getConfigManager().cancelOnMove()) {
Location now = player.getLocation();
if (Math.abs(now.getX()-startLoc.getX()) > 0.5 || Math.abs(now.getZ()-startLoc.getZ()) > 0.5) {
if (Math.abs(now.getX() - startLoc.getX()) > 0.5
|| Math.abs(now.getZ() - startLoc.getZ()) > 0.5) {
player.sendMessage(plugin.getConfigManager().getMessage("teleport-cancelled"));
warmupTasks.remove(player.getUniqueId());
return;
@@ -70,10 +80,17 @@ public class TeleportManager {
private void executeTeleport(Player player, TeleportLocation dest) {
String localServer = plugin.getConfigManager().getServerName();
// Save last location + apply cooldown always (also for cross-server)
plugin.getDatabaseManager().saveLastLocation(player.getUniqueId(),
new TeleportLocation(player.getLocation(), localServer));
cooldowns.put(player.getUniqueId(), System.currentTimeMillis());
if (!dest.isLocalServer(localServer)) {
// BungeeCord-Teleport
if (plugin.getBungeeMessenger() != null) {
plugin.getBungeeMessenger().connectToServer(player, dest.getServer(), dest.getWorld(),
// Cross-server: delegate completely to the Bungee plugin.
// It will call sender.connect() and then send TP_PLAYERTOPOSITION.
BungeeMessenger bm = plugin.getBungeeMessenger();
if (bm != null) {
bm.teleportToPosition(player, dest.getServer(), dest.getWorld(),
dest.getX(), dest.getY(), dest.getZ(), dest.getYaw(), dest.getPitch());
player.sendMessage(plugin.getConfigManager().getMessage("teleport-success"));
}
@@ -82,16 +99,14 @@ public class TeleportManager {
Location loc = dest.toBukkitLocation();
if (loc == null || loc.getWorld() == null) {
player.sendMessage("§cZielwelt nicht gefunden!");
player.sendMessage("§cFehler: Zielwelt §6" + dest.getWorld() + "§c nicht gefunden!"
+ " Ist der Spawn auf diesem Server gesetzt?");
plugin.getLogger().warning("Teleport fehlgeschlagen: Welt '" + dest.getWorld()
+ "' fuer Spieler " + player.getName() + " nicht geladen.");
return;
}
// Save last location to database
plugin.getDatabaseManager().saveLastLocation(player.getUniqueId(),
new TeleportLocation(player.getLocation(), localServer));
player.teleport(loc);
cooldowns.put(player.getUniqueId(), System.currentTimeMillis());
player.sendMessage(plugin.getConfigManager().getMessage("teleport-success"));
}
@@ -104,7 +119,10 @@ public class TeleportManager {
return pendingBackLocations.get(uuid);
}
// TPA
// -------------------------------------------------------------------------
// Same-server TPA
// -------------------------------------------------------------------------
public void sendTpaRequest(Player from, Player to) {
tpaRequests.put(from.getUniqueId(), to.getUniqueId());
requestTimestamps.put(from.getUniqueId(), System.currentTimeMillis());
@@ -117,48 +135,89 @@ public class TeleportManager {
if (tpaRequests.containsKey(from.getUniqueId())) {
tpaRequests.remove(from.getUniqueId());
requestTimestamps.remove(from.getUniqueId());
if (from.isOnline()) from.sendMessage(plugin.getConfigManager().getMessage("tpa-expired"));
if (from.isOnline()) {
from.sendMessage(plugin.getConfigManager().getMessage("tpa-expired"));
}
}
}, timeout * 20L);
}
// -------------------------------------------------------------------------
// Cross-server TPA — all state lives on the Bungee plugin now;
// Spigot just sends the right payload and handles local accept/deny.
// -------------------------------------------------------------------------
/**
* Called by TpaCommand when the target player is NOT on this server.
* Bungee will manage the pending state and route all messages.
*/
public void sendCrossServerTpaRequest(Player from, String targetName) {
BungeeMessenger bm = plugin.getBungeeMessenger();
if (bm == null) {
from.sendMessage(plugin.getConfigManager().getMessage("player-not-found", "player", targetName));
return;
}
bm.sendTpaRequest(
from, targetName, "TPTO",
plugin.getConfigManager().getMessage("tpa-received", "player", from.getName()),
plugin.getConfigManager().getMessage("tpa-sent", "player", targetName));
}
/** Called by TpAcceptCommand — handles both same-server and cross-server. */
public boolean acceptTpa(Player target) {
UUID requester = null;
// Same-server accept
UUID requesterUUID = null;
for (Map.Entry<UUID, UUID> entry : tpaRequests.entrySet()) {
if (entry.getValue().equals(target.getUniqueId())) {
requester = entry.getKey();
requesterUUID = entry.getKey();
break;
}
}
if (requester == null) return false;
Player from = Bukkit.getPlayer(requester);
tpaRequests.remove(requester);
requestTimestamps.remove(requester);
if (from != null && from.isOnline()) {
from.sendMessage(plugin.getConfigManager().getMessage("tpa-accepted", "player", target.getName()));
teleport(from, new TeleportLocation(target.getLocation(), plugin.getConfigManager().getServerName()));
if (requesterUUID != null) {
Player from = Bukkit.getPlayer(requesterUUID);
tpaRequests.remove(requesterUUID);
requestTimestamps.remove(requesterUUID);
if (from != null && from.isOnline()) {
from.sendMessage(plugin.getConfigManager().getMessage("tpa-accepted", "player", target.getName()));
teleport(from, new TeleportLocation(target.getLocation(),
plugin.getConfigManager().getServerName()));
}
return true;
}
// Cross-server accept — tell Bungee, it has the pending state
BungeeMessenger bm = plugin.getBungeeMessenger();
if (bm == null) return false;
bm.sendTpaAccept(target, null,
plugin.getConfigManager().getMessage("tpa-request-not-found"));
return true;
}
/** Called by TpDenyCommand — handles both same-server and cross-server. */
public boolean denyTpa(Player target) {
UUID requester = null;
// Same-server deny
UUID requesterUUID = null;
for (Map.Entry<UUID, UUID> entry : tpaRequests.entrySet()) {
if (entry.getValue().equals(target.getUniqueId())) {
requester = entry.getKey();
requesterUUID = entry.getKey();
break;
}
}
if (requester == null) return false;
if (requesterUUID != null) {
Player from = Bukkit.getPlayer(requesterUUID);
tpaRequests.remove(requesterUUID);
requestTimestamps.remove(requesterUUID);
if (from != null && from.isOnline()) {
from.sendMessage(plugin.getConfigManager().getMessage("tpa-denied", "player", target.getName()));
}
return true;
}
Player from = Bukkit.getPlayer(requester);
tpaRequests.remove(requester);
requestTimestamps.remove(requester);
if (from != null && from.isOnline())
from.sendMessage(plugin.getConfigManager().getMessage("tpa-denied", "player", target.getName()));
// Cross-server deny
BungeeMessenger bm = plugin.getBungeeMessenger();
if (bm == null) return false;
bm.sendTpaDeny(target, null,
plugin.getConfigManager().getMessage("tpa-denied", "player", target.getName()));
return true;
}
}

View File

@@ -0,0 +1,5 @@
name: TeleportSuite-Bungee
main: de.teleportsuite.bungee.TeleportSuiteBungee
version: 1.0
author: TeleportSuite
description: BungeeCord-Companion fuer TeleportSuite

View File

@@ -15,9 +15,10 @@ database:
file: teleportsuite.db
# BungeeCord Einstellungen
# WICHTIG: server-name muss dem Namen dieses Servers in der BungeeCord config.yml entsprechen!
bungee:
enabled: false
server-name: "survival" # Name dieses Servers im BungeeCord-Netz
enabled: true
server-name: "survival" # Name dieses Servers im BungeeCord-Netz (z.B. "lobby", "survival", "creative")
# Teleport Einstellungen
teleport:
@@ -70,6 +71,7 @@ messages:
death-no-location: "&cKein Todesort gespeichert."
no-permission: "&cDazu hast du keine Berechtigung."
player-not-found: "&cSpieler &6{player}&c nicht gefunden."
tpa-request-not-found: "&cKeine offene Teleportanfrage gefunden."
portal-created: "&aPortal &6{name}&a erstellt!"
portal-deleted: "&cPortal &6{name}&c gelöscht."
savepoint-set: "&aSavepoint &6{name}&a gesetzt!"

View File

@@ -1,5 +1,5 @@
name: TeleportSuite
version: 1.0.0
version: 1.0.3
main: de.teleportsuite.TeleportSuite
api-version: 1.20
description: BungeeCord-fähiges Teleport-Komplettpaket