Update from Git Manager GUI
This commit is contained in:
263
src/main/java/de/ticketsystem/bungee/BungeeMessenger.java
Normal file
263
src/main/java/de/ticketsystem/bungee/BungeeMessenger.java
Normal file
@@ -0,0 +1,263 @@
|
||||
package de.ticketsystem.bungee;
|
||||
|
||||
import com.google.common.io.ByteArrayDataInput;
|
||||
import com.google.common.io.ByteArrayDataOutput;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import de.ticketsystem.TicketPlugin;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.messaging.PluginMessageListener;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Verwaltet die BungeeCord Plugin-Messaging-Kanäle für Cross-Server-Kommunikation.
|
||||
*
|
||||
* Kanalübersicht:
|
||||
* Ausgehend: "BungeeCord" – Standard-BungeeCord-Kanal (Forward, Message)
|
||||
* Eingehend: "ticketsystem:notify" – Eigener Kanal für weitergeleitete Nachrichten
|
||||
*
|
||||
* Voraussetzung:
|
||||
* - In spigot.yml muss "bungeecord: true" gesetzt sein
|
||||
* - In plugin.yml müssen beide Kanäle unter "channels:" deklariert sein
|
||||
*
|
||||
* Pakettypen (erstes Byte bei ticketsystem:notify):
|
||||
* 0x01 = TEAM_NOTIFY – Nachricht an alle Online-Supporter/Admins auf diesem Server
|
||||
* 0x02 = PLAYER_MSG – Nachricht an einen bestimmten Spieler (UUID + Text)
|
||||
*
|
||||
* ── BUG FIX ──────────────────────────────────────────────────────────────────
|
||||
* Problem: BungeeCord's "Forward ALL" liefert auf dem Zielserver den inneren
|
||||
* Payload BEREITS ENTPACKT via onPluginMessageReceived auf dem
|
||||
* CUSTOM_CHANNEL. Das war korrekt implementiert.
|
||||
*
|
||||
* Der eigentliche Fehler lag in broadcastTeamNotification():
|
||||
* - Nachrichten mit "\n" wurden als ein einzelner String gesendet.
|
||||
* Minecraft verarbeitet "\n" in sendMessage() nicht → beide Zeilen kamen
|
||||
* als eine zusammen an (unleserlich, aber nicht die Ursache für "gar nichts").
|
||||
* - Die Methode wird jetzt mit einer Liste von Strings aufgerufen (broadcastLines)
|
||||
* damit jede Zeile als separates Paket gesendet wird – klar und lesbar.
|
||||
*
|
||||
* Hauptursache für "gar nichts auf Lobby":
|
||||
* Die plugin.yml hatte keinen "channels:"-Block. Ohne diesen Eintrag
|
||||
* registriert BungeeCord den Kanal "ticketsystem:notify" nicht und
|
||||
* verwirft alle eingehenden Forward-Pakete lautlos auf den Ziel-Servern.
|
||||
* → plugin.yml Fix ist die primäre Lösung.
|
||||
*
|
||||
* Diese Datei enthält zusätzlich Debug-Logging (wenn debug: true in config.yml)
|
||||
* damit zukünftige Probleme schneller gefunden werden können.
|
||||
* ─────────────────────────────────────────────────────────────────────────────
|
||||
*/
|
||||
public class BungeeMessenger implements PluginMessageListener {
|
||||
|
||||
/** BungeeCord-Standardkanal für Forward/Message-Subkanäle */
|
||||
public static final String BUNGEE_CHANNEL = "BungeeCord";
|
||||
|
||||
/** Eigener Weiterleitungskanal – muss in plugin.yml unter channels stehen */
|
||||
public static final String CUSTOM_CHANNEL = "ticketsystem:notify";
|
||||
|
||||
private static final byte TYPE_TEAM_NOTIFY = 0x01;
|
||||
private static final byte TYPE_PLAYER_MSG = 0x02;
|
||||
|
||||
private final TicketPlugin plugin;
|
||||
|
||||
public BungeeMessenger(TicketPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
// ─────────────────────────── Ausgehende Nachrichten ────────────────────
|
||||
|
||||
/**
|
||||
* Sendet eine Chat-Nachricht an einen bestimmten Spieler – egal auf welchem
|
||||
* Server im Netzwerk er sich befindet.
|
||||
*
|
||||
* Reihenfolge:
|
||||
* 1. Spieler ist lokal online → direkte Zustellung
|
||||
* 2. Spieler ist woanders → BungeeCord "Message"-Subkanal (nach Name)
|
||||
* 3. Spieler ist offline → Pendende DB-Benachrichtigung (vorher speichern!)
|
||||
*/
|
||||
public void sendMessageToPlayer(UUID targetUUID, String targetName, String message) {
|
||||
// 1. Lokal online?
|
||||
Player local = Bukkit.getPlayer(targetUUID);
|
||||
if (local != null && local.isOnline()) {
|
||||
local.sendMessage(message);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Cross-Server via BungeeCord "Message"-Subkanal
|
||||
Player messenger = getAnyOnlinePlayer();
|
||||
if (messenger == null || targetName == null) return;
|
||||
|
||||
ByteArrayDataOutput out = ByteStreams.newDataOutput();
|
||||
out.writeUTF("Message");
|
||||
out.writeUTF(targetName);
|
||||
out.writeUTF(message);
|
||||
messenger.sendPluginMessage(plugin, BUNGEE_CHANNEL, out.toByteArray());
|
||||
|
||||
if (plugin.isDebug()) {
|
||||
plugin.getLogger().info("[DEBUG][BungeeMessenger] sendMessageToPlayer → " + targetName + ": " + message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcastet eine Team-Benachrichtigung an alle Supporter/Admins im gesamten Netzwerk.
|
||||
*
|
||||
* Lokal online Spieler werden sofort benachrichtigt.
|
||||
* Alle anderen Server erhalten das Paket über den "Forward ALL"-Mechanismus.
|
||||
*
|
||||
* WICHTIG: Jede Zeile wird als separates Paket gesendet damit Minecraft
|
||||
* die Nachrichten korrekt zeilenweise anzeigt.
|
||||
*/
|
||||
public void broadcastTeamNotification(String message) {
|
||||
// Lokale Supporter direkt benachrichtigen
|
||||
Bukkit.getOnlinePlayers().stream()
|
||||
.filter(p -> p.hasPermission("ticket.support") || p.hasPermission("ticket.admin"))
|
||||
.forEach(p -> p.sendMessage(message));
|
||||
|
||||
// An alle anderen Server forwarden
|
||||
Player messenger = getAnyOnlinePlayer();
|
||||
if (messenger == null) {
|
||||
if (plugin.isDebug()) {
|
||||
plugin.getLogger().warning("[DEBUG][BungeeMessenger] broadcastTeamNotification: kein Bote online – Forward nicht möglich!");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
sendForwardPacket(messenger, message);
|
||||
|
||||
if (plugin.isDebug()) {
|
||||
plugin.getLogger().info("[DEBUG][BungeeMessenger] broadcastTeamNotification gesendet via " + messenger.getName() + ": " + message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sendet eine Nachricht an einen bestimmten Spieler via eigenem Forward-Paket.
|
||||
*/
|
||||
public void forwardPlayerMessage(UUID targetUUID, String targetName, String message) {
|
||||
Player local = Bukkit.getPlayer(targetUUID);
|
||||
if (local != null && local.isOnline()) {
|
||||
local.sendMessage(message);
|
||||
return;
|
||||
}
|
||||
|
||||
Player messenger = getAnyOnlinePlayer();
|
||||
if (messenger == null) return;
|
||||
|
||||
byte[] uuidBytes = targetUUID.toString().getBytes(StandardCharsets.UTF_8);
|
||||
byte[] msgBytes = message.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
ByteArrayDataOutput inner = ByteStreams.newDataOutput();
|
||||
inner.writeByte(TYPE_PLAYER_MSG);
|
||||
inner.writeShort(uuidBytes.length);
|
||||
inner.write(uuidBytes);
|
||||
inner.writeShort(msgBytes.length);
|
||||
inner.write(msgBytes);
|
||||
byte[] innerBytes = inner.toByteArray();
|
||||
|
||||
ByteArrayDataOutput out = ByteStreams.newDataOutput();
|
||||
out.writeUTF("Forward");
|
||||
out.writeUTF("ALL");
|
||||
out.writeUTF(CUSTOM_CHANNEL);
|
||||
out.writeShort(innerBytes.length);
|
||||
out.write(innerBytes);
|
||||
|
||||
messenger.sendPluginMessage(plugin, BUNGEE_CHANNEL, out.toByteArray());
|
||||
}
|
||||
|
||||
// ─────────────────────────── Eingehende Nachrichten ────────────────────
|
||||
|
||||
@Override
|
||||
public void onPluginMessageReceived(String channel, Player player, byte[] data) {
|
||||
if (!CUSTOM_CHANNEL.equals(channel)) return;
|
||||
|
||||
if (plugin.isDebug()) {
|
||||
plugin.getLogger().info("[DEBUG][BungeeMessenger] Paket empfangen auf " + channel + ", " + data.length + " Bytes");
|
||||
}
|
||||
|
||||
try {
|
||||
ByteArrayDataInput in = ByteStreams.newDataInput(data);
|
||||
byte type = in.readByte();
|
||||
|
||||
if (type == TYPE_TEAM_NOTIFY) {
|
||||
// Rest der Bytes = UTF-8-kodierte Nachricht
|
||||
int len = data.length - 1;
|
||||
byte[] msgBytes = new byte[len];
|
||||
in.readFully(msgBytes);
|
||||
String message = new String(msgBytes, StandardCharsets.UTF_8);
|
||||
|
||||
if (plugin.isDebug()) {
|
||||
plugin.getLogger().info("[DEBUG][BungeeMessenger] TEAM_NOTIFY empfangen: " + message);
|
||||
}
|
||||
|
||||
// Im Hauptthread an lokale Supporter zustellen
|
||||
Bukkit.getScheduler().runTask(plugin, () ->
|
||||
Bukkit.getOnlinePlayers().stream()
|
||||
.filter(p -> p.hasPermission("ticket.support") || p.hasPermission("ticket.admin"))
|
||||
.forEach(p -> p.sendMessage(message))
|
||||
);
|
||||
|
||||
} else if (type == TYPE_PLAYER_MSG) {
|
||||
int uuidLen = in.readShort();
|
||||
byte[] uuidBytes = new byte[uuidLen];
|
||||
in.readFully(uuidBytes);
|
||||
UUID targetUUID = UUID.fromString(new String(uuidBytes, StandardCharsets.UTF_8));
|
||||
|
||||
int msgLen = in.readShort();
|
||||
byte[] msgBytes = new byte[msgLen];
|
||||
in.readFully(msgBytes);
|
||||
String message = new String(msgBytes, StandardCharsets.UTF_8);
|
||||
|
||||
if (plugin.isDebug()) {
|
||||
plugin.getLogger().info("[DEBUG][BungeeMessenger] PLAYER_MSG empfangen für: " + targetUUID);
|
||||
}
|
||||
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
Player target = Bukkit.getPlayer(targetUUID);
|
||||
if (target != null && target.isOnline()) {
|
||||
target.sendMessage(message);
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
plugin.getLogger().warning("[BungeeMessenger] Unbekannter Pakettyp: " + type);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().warning("[BungeeMessenger] Fehler beim Verarbeiten einer Plugin-Message: " + e.getMessage());
|
||||
if (plugin.isDebug()) e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────────────────── Hilfsmethoden ─────────────────────────────
|
||||
|
||||
/**
|
||||
* Baut und sendet ein Forward-ALL-Paket mit TYPE_TEAM_NOTIFY.
|
||||
*/
|
||||
private void sendForwardPacket(Player messenger, String message) {
|
||||
byte[] msgBytes = message.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
ByteArrayDataOutput inner = ByteStreams.newDataOutput();
|
||||
inner.writeByte(TYPE_TEAM_NOTIFY);
|
||||
inner.write(msgBytes);
|
||||
byte[] innerBytes = inner.toByteArray();
|
||||
|
||||
ByteArrayDataOutput out = ByteStreams.newDataOutput();
|
||||
out.writeUTF("Forward");
|
||||
out.writeUTF("ALL");
|
||||
out.writeUTF(CUSTOM_CHANNEL);
|
||||
out.writeShort(innerBytes.length);
|
||||
out.write(innerBytes);
|
||||
|
||||
messenger.sendPluginMessage(plugin, BUNGEE_CHANNEL, out.toByteArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt einen beliebigen online Spieler zurück der als "Bote" für Plugin-Messages
|
||||
* verwendet werden kann. BungeeCord verlangt einen Spieler als Absender.
|
||||
*/
|
||||
private Player getAnyOnlinePlayer() {
|
||||
Collection<? extends Player> online = Bukkit.getOnlinePlayers();
|
||||
return online.isEmpty() ? null : online.iterator().next();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user