221 lines
8.2 KiB
Java
221 lines
8.2 KiB
Java
package de.nexuslobby.modules.hologram;
|
|
|
|
import de.nexuslobby.NexusLobby;
|
|
import de.nexuslobby.api.Module;
|
|
import org.bukkit.Bukkit;
|
|
import org.bukkit.Location;
|
|
import org.bukkit.World;
|
|
import org.bukkit.configuration.file.FileConfiguration;
|
|
import org.bukkit.configuration.file.YamlConfiguration;
|
|
import org.bukkit.entity.Entity;
|
|
import org.bukkit.entity.Interaction;
|
|
import org.bukkit.entity.Player;
|
|
import org.bukkit.entity.TextDisplay;
|
|
import org.bukkit.event.EventHandler;
|
|
import org.bukkit.event.Listener;
|
|
import org.bukkit.event.player.PlayerChangedWorldEvent;
|
|
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
|
import org.bukkit.event.player.PlayerJoinEvent;
|
|
import org.bukkit.event.player.PlayerQuitEvent;
|
|
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
public class HologramModule implements Module, Listener {
|
|
|
|
private final Map<String, NexusHologram> holograms = new ConcurrentHashMap<>();
|
|
private File file;
|
|
private FileConfiguration config;
|
|
|
|
@Override
|
|
public String getName() { return "Holograms"; }
|
|
|
|
@Override
|
|
public void onEnable() {
|
|
loadConfig();
|
|
loadHolograms();
|
|
Bukkit.getPluginManager().registerEvents(this, NexusLobby.getInstance());
|
|
|
|
// Render-Task: Prüft alle 5 Ticks Sichtbarkeit und Placeholder-Updates
|
|
Bukkit.getScheduler().runTaskTimer(NexusLobby.getInstance(), () -> {
|
|
for (Player player : Bukkit.getOnlinePlayers()) {
|
|
holograms.values().forEach(h -> h.renderForPlayer(player));
|
|
}
|
|
}, 20L, 5L);
|
|
}
|
|
|
|
private void loadConfig() {
|
|
file = new File(NexusLobby.getInstance().getDataFolder(), "holograms.yml");
|
|
config = YamlConfiguration.loadConfiguration(file);
|
|
}
|
|
|
|
private void loadHolograms() {
|
|
// Vorherige Instanzen säubern
|
|
holograms.values().forEach(NexusHologram::removeAll);
|
|
holograms.clear();
|
|
|
|
for (String id : config.getKeys(false)) {
|
|
String worldName = config.getString(id + ".world");
|
|
if (worldName == null) continue;
|
|
|
|
World world = Bukkit.getWorld(worldName);
|
|
if (world == null) continue;
|
|
|
|
Location loc = new Location(world,
|
|
config.getDouble(id + ".x"),
|
|
config.getDouble(id + ".y"),
|
|
config.getDouble(id + ".z"));
|
|
|
|
List<String> pages;
|
|
if (config.isList(id + ".text")) {
|
|
pages = config.getStringList(id + ".text");
|
|
} else {
|
|
pages = new ArrayList<>();
|
|
pages.add(config.getString(id + ".text", "No Text"));
|
|
}
|
|
|
|
holograms.put(id, new NexusHologram(id, loc, pages));
|
|
}
|
|
}
|
|
|
|
@EventHandler
|
|
public void onInteract(PlayerInteractEntityEvent event) {
|
|
// Nur auf Interaction-Entities reagieren (Hologramm-Hitboxen)
|
|
if (!(event.getRightClicked() instanceof Interaction)) return;
|
|
|
|
for (NexusHologram holo : holograms.values()) {
|
|
if (holo.isInteractionEntity(event.getRightClicked().getUniqueId())) {
|
|
holo.nextPage(event.getPlayer());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
@EventHandler
|
|
public void onQuit(PlayerQuitEvent event) {
|
|
holograms.values().forEach(h -> h.removeForPlayer(event.getPlayer()));
|
|
}
|
|
|
|
@EventHandler
|
|
public void onWorldChange(PlayerChangedWorldEvent event) {
|
|
holograms.values().forEach(h -> h.removeForPlayer(event.getPlayer()));
|
|
}
|
|
|
|
@EventHandler
|
|
public void onJoin(PlayerJoinEvent event) {
|
|
// Cleanup alter Entity-Reste, die eventuell noch in der Welt schweben
|
|
Bukkit.getScheduler().runTaskLater(NexusLobby.getInstance(), () -> {
|
|
Player p = event.getPlayer();
|
|
for (Entity entity : p.getWorld().getEntities()) {
|
|
if (entity.getCustomName() != null && entity.getCustomName().startsWith("nexus_h_")) {
|
|
// Wenn das Hologramm nicht exakt für diesen Spieler benannt ist -> verstecken
|
|
if (!entity.getCustomName().endsWith("_" + p.getName())) {
|
|
p.hideEntity(NexusLobby.getInstance(), entity);
|
|
}
|
|
}
|
|
}
|
|
}, 10L);
|
|
}
|
|
|
|
public void createHologram(String id, Location loc, List<String> pages) {
|
|
// Falls ID bereits existiert, altes Hologramm sauber entfernen
|
|
if (holograms.containsKey(id)) {
|
|
removeHologram(id);
|
|
}
|
|
|
|
config.set(id + ".world", loc.getWorld().getName());
|
|
config.set(id + ".x", loc.getX());
|
|
config.set(id + ".y", loc.getY());
|
|
config.set(id + ".z", loc.getZ());
|
|
config.set(id + ".text", pages);
|
|
saveHoloConfig();
|
|
|
|
NexusHologram holo = new NexusHologram(id, loc, pages);
|
|
holograms.put(id, holo);
|
|
}
|
|
|
|
public void removeHologram(String id) {
|
|
NexusHologram holo = holograms.remove(id);
|
|
if (holo != null) {
|
|
// Erst für alle Spieler visuell entfernen
|
|
for (Player player : Bukkit.getOnlinePlayers()) {
|
|
holo.removeForPlayer(player);
|
|
}
|
|
// Dann Entities serverseitig löschen
|
|
holo.removeAll();
|
|
}
|
|
config.set(id, null);
|
|
saveHoloConfig();
|
|
}
|
|
|
|
/**
|
|
* Lädt die holograms.yml neu und rendert alle Hologramme für Online-Spieler neu.
|
|
* Wird von HoloCommand (/holo reload) aufgerufen.
|
|
*/
|
|
public void reloadHolograms() {
|
|
// Alle aktiven Hologramme für alle Spieler entfernen
|
|
for (Player player : Bukkit.getOnlinePlayers()) {
|
|
holograms.values().forEach(h -> h.removeForPlayer(player));
|
|
}
|
|
// Config neu einlesen und Hologramme neu laden
|
|
loadConfig();
|
|
loadHolograms();
|
|
}
|
|
|
|
private void saveHoloConfig() {
|
|
try {
|
|
// Sicherstellen, dass Placeholder-Strings (z.B. %bungeetotal%) korrekt
|
|
// gequotet gespeichert werden, damit SnakeYAML sie nicht als YAML-Direktive
|
|
// missinterpretiert. Dazu speichern wir die text-Listen explizit als
|
|
// String-Werte mit einfachen Anführungszeichen via eigener Serialisierung.
|
|
StringBuilder yaml = new StringBuilder();
|
|
for (String id : config.getKeys(false)) {
|
|
yaml.append(id).append(":\n");
|
|
yaml.append(" world: ").append(quoteIfNeeded(config.getString(id + ".world", ""))).append("\n");
|
|
yaml.append(" x: ").append(config.getDouble(id + ".x")).append("\n");
|
|
yaml.append(" y: ").append(config.getDouble(id + ".y")).append("\n");
|
|
yaml.append(" z: ").append(config.getDouble(id + ".z")).append("\n");
|
|
yaml.append(" text:\n");
|
|
for (String line : config.getStringList(id + ".text")) {
|
|
yaml.append(" - ").append(quoteIfNeeded(line)).append("\n");
|
|
}
|
|
}
|
|
java.nio.file.Files.writeString(file.toPath(), yaml.toString());
|
|
} catch (IOException e) {
|
|
NexusLobby.getInstance().getLogger().severe("Konnte holograms.yml nicht speichern!");
|
|
NexusLobby.getInstance().getLogger().severe("Fehler beim Speichern der Hologramme: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Umschließt Strings mit einfachen Anführungszeichen, wenn sie YAML-Sonderzeichen
|
|
* wie '%', ':', '#' enthalten, um Parsing-Fehler zu vermeiden.
|
|
*/
|
|
private String quoteIfNeeded(String value) {
|
|
if (value == null) return "''";
|
|
if (value.contains("%") || value.contains(":") || value.contains("#") || value.contains("'")) {
|
|
return "'" + value.replace("'", "''") + "'";
|
|
}
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* WICHTIG: Diese Methode wird vom LobbyTabCompleter benötigt!
|
|
* @return Set aller registrierten Hologramm-IDs
|
|
*/
|
|
public Set<String> getHologramIds() {
|
|
return holograms.keySet();
|
|
}
|
|
|
|
@Override
|
|
public void onDisable() {
|
|
org.bukkit.event.HandlerList.unregisterAll(this);
|
|
holograms.values().forEach(NexusHologram::removeAll);
|
|
holograms.clear();
|
|
}
|
|
} |