Files
EventEngine/src/main/java/dev/viper/eventengine/manager/EventManager.java
2026-04-13 14:12:41 +02:00

275 lines
12 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package dev.viper.eventengine.manager;
import dev.viper.eventengine.EventEngine;
import dev.viper.eventengine.events.builtin.EventHandlerRegistry;
import dev.viper.eventengine.events.builtin.IEventHandler;
import dev.viper.eventengine.model.ActiveEvent;
import dev.viper.eventengine.model.EventDefinition;
import org.bukkit.Bukkit;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.*;
import java.util.logging.Logger;
/**
* Steuert den Lebenszyklus von Events:
* start → announce → countdown → run → end → reward
*/
public class EventManager {
private final EventEngine plugin;
private final Logger log;
private final EventHandlerRegistry handlerRegistry;
private ActiveEvent currentEvent = null;
private final Deque<EventDefinition> queue = new ArrayDeque<>();
public EventManager(EventEngine plugin) {
this.plugin = plugin;
this.log = plugin.getLogger();
this.handlerRegistry = new EventHandlerRegistry(plugin);
}
public boolean startEvent(EventDefinition def, Player initiator) {
if (currentEvent != null && currentEvent.getState() != ActiveEvent.State.ENDED) {
if (initiator != null)
initiator.sendMessage(plugin.prefix() + "§cEin Event läuft bereits: §e"
+ currentEvent.getDefinition().getDisplayName());
return false;
}
// Ankündigung
broadcast(def.getAnnouncement());
if (def.getDurationSeconds() > 0)
broadcast(plugin.prefix() + "§7Dauer: §e" + formatTime(def.getDurationSeconds()));
if (plugin.getConfigManager().isLogEvents()) {
String by = initiator != null ? initiator.getName() : "Zeitplan";
log.info("Event gestartet von " + by + ": " + def.getDisplayName());
}
// 3..2..1..Go Countdown, danach eigentlicher Start
int countdown = plugin.getConfigManager().getCountdownSeconds();
if (countdown > 0) {
currentEvent = new ActiveEvent(def);
currentEvent.setState(ActiveEvent.State.WAITING);
runCountdown(def, initiator, countdown);
} else {
launchEvent(def, initiator);
}
return true;
}
/** Countdown-Loop: 3..2..1..Go */
private void runCountdown(EventDefinition def, Player initiator, int seconds) {
final ActiveEvent snap = currentEvent;
new BukkitRunnable() {
int remaining = seconds;
@Override
public void run() {
if (snap != currentEvent) { cancel(); return; } // abgebrochen
if (remaining > 0) {
// Titel + Sound für alle Online-Spieler
String color = remaining <= 3 ? "§c" : "§e";
for (Player p : Bukkit.getOnlinePlayers()) {
p.sendTitle(color + remaining, "§7" + def.getDisplayName() + " §7startet gleich!", 0, 25, 5);
p.playSound(p.getLocation(), Sound.BLOCK_NOTE_BLOCK_HAT, 1f, 1f);
}
broadcast(plugin.prefix() + "§e⏳ " + def.getDisplayName() + " §7startet in §c" + remaining + " §7Sekunde" + (remaining == 1 ? "" : "n") + "...");
remaining--;
} else {
cancel();
for (Player p : Bukkit.getOnlinePlayers()) {
p.sendTitle("§a§lGO!", "§7" + def.getDisplayName(), 0, 30, 10);
p.playSound(p.getLocation(), Sound.ENTITY_FIREWORK_ROCKET_LARGE_BLAST, 1f, 1.2f);
}
broadcast(plugin.prefix() + "§a§l🚀 GO! §r§e" + def.getDisplayName() + " §7hat begonnen!");
launchEvent(def, initiator);
}
}
}.runTaskTimer(plugin, 0L, 20L);
}
/** Eigentlicher Event-Start nach dem Countdown */
private void launchEvent(EventDefinition def, Player initiator) {
if (currentEvent == null || currentEvent.getState() == ActiveEvent.State.ENDED) {
currentEvent = new ActiveEvent(def);
}
currentEvent.setState(ActiveEvent.State.RUNNING);
runCommands(def.getStartCommands(), null);
handlerRegistry.get(def.getType()).ifPresent(h -> h.onStart(currentEvent));
plugin.getScoreboardManager().start(currentEvent);
if (def.getDurationSeconds() > 0) {
final ActiveEvent snap = currentEvent;
if (def.getDurationSeconds() > 70)
new BukkitRunnable() { @Override public void run() {
if (currentEvent == snap && currentEvent.getState() == ActiveEvent.State.RUNNING)
broadcast(plugin.prefix() + "§e⏰ Noch §c60 Sekunden §ebis das Event endet!");
}}.runTaskLater(plugin, (def.getDurationSeconds() - 60) * 20L);
if (def.getDurationSeconds() > 15)
new BukkitRunnable() { @Override public void run() {
if (currentEvent == snap && currentEvent.getState() == ActiveEvent.State.RUNNING)
broadcast(plugin.prefix() + "§c⏰ Noch 10 Sekunden!");
}}.runTaskLater(plugin, (def.getDurationSeconds() - 10) * 20L);
int taskId = (int) new BukkitRunnable() { @Override public void run() {
if (currentEvent == snap && currentEvent.getState() == ActiveEvent.State.RUNNING)
endEvent("Zeit abgelaufen");
}}.runTaskLater(plugin, def.getDurationSeconds() * 20L).getTaskId();
currentEvent.setTaskId(taskId);
}
}
public boolean endEvent(String reason) {
if (currentEvent == null || currentEvent.getState() == ActiveEvent.State.ENDED) return false;
EventDefinition def = currentEvent.getDefinition();
currentEvent.setState(ActiveEvent.State.ENDED);
if (currentEvent.getTaskId() != -1)
Bukkit.getScheduler().cancelTask(currentEvent.getTaskId());
handlerRegistry.get(def.getType()).ifPresent(h -> h.onEnd(currentEvent));
plugin.getScoreboardManager().stop();
broadcast(plugin.prefix() + "§6✦ §e" + def.getDisplayName()
+ " §7ist beendet! §7(" + reason + ")");
showLeaderboard();
runCommands(def.getEndCommands(), null);
distributeRewards(def);
if (plugin.getConfigManager().isLogEvents())
log.info("Event beendet: " + def.getDisplayName() + " [" + reason + "]");
currentEvent = null;
if (!queue.isEmpty()) {
EventDefinition next = queue.poll();
Bukkit.getScheduler().runTaskLater(plugin, () -> startEvent(next, null), 100L);
}
return true;
}
public boolean endEventWithWinner(Player winner, String reason) {
if (currentEvent == null || currentEvent.getState() == ActiveEvent.State.ENDED) return false;
if (winner != null) {
currentEvent.setWinner(winner.getUniqueId());
// Ziel-Nachricht mit Zeit
long elapsed = currentEvent.getElapsedSeconds();
broadcast(plugin.prefix() + "§6🏁 §f" + winner.getName()
+ " §ehat das Ziel erreicht und gewinnt! §8(Zeit: §f" + formatTime((int) elapsed) + "§8)");
// Title für Gewinner
winner.sendTitle("§6§l🏁 ZIEL!", "§e" + currentEvent.getDefinition().getDisplayName(), 0, 60, 20);
winner.playSound(winner.getLocation(), Sound.UI_TOAST_CHALLENGE_COMPLETE, 1f, 1f);
// Title für alle anderen
for (UUID uuid : currentEvent.getParticipants()) {
Player p = Bukkit.getPlayer(uuid);
if (p != null && !p.equals(winner)) {
p.sendTitle("§c§lZU SPÄT!", "§7" + winner.getName() + " §7war schneller.", 0, 40, 15);
}
}
distributeWinnerRewards(currentEvent.getDefinition(), winner);
}
return endEvent(reason);
}
public boolean join(Player player) {
if (currentEvent == null || currentEvent.getState() == ActiveEvent.State.ENDED) {
player.sendMessage(plugin.prefix() + "§cKein Event aktiv."); return false;
}
if (currentEvent.isParticipant(player)) {
player.sendMessage(plugin.prefix() + "§cDu nimmst bereits teil."); return false;
}
EventDefinition def = currentEvent.getDefinition();
if (currentEvent.getParticipantCount() >= def.getMaxPlayers()) {
player.sendMessage(plugin.prefix() + "§cDas Event ist voll!"); return false;
}
currentEvent.addParticipant(player);
broadcast(plugin.prefix() + "§a" + player.getName() + " §7nimmt teil! §8("
+ currentEvent.getParticipantCount() + "/" + def.getMaxPlayers() + ")");
handlerRegistry.get(def.getType()).ifPresent(h -> h.onPlayerJoin(currentEvent, player));
plugin.getScoreboardManager().onJoin(player, currentEvent);
return true;
}
public void leave(Player player) {
if (currentEvent == null) { player.sendMessage(plugin.prefix() + "§cKein Event aktiv."); return; }
if (!currentEvent.isParticipant(player)) { player.sendMessage(plugin.prefix() + "§cDu nimmst nicht teil."); return; }
currentEvent.removeParticipant(player);
handlerRegistry.get(currentEvent.getDefinition().getType())
.ifPresent(h -> h.onPlayerLeave(currentEvent, player));
plugin.getScoreboardManager().onLeave(player);
player.sendMessage(plugin.prefix() + "§7Du hast das Event verlassen.");
}
private void showLeaderboard() {
if (currentEvent == null) return;
List<Map.Entry<UUID, Integer>> lb = currentEvent.getLeaderboard();
if (lb.isEmpty()) return;
broadcast("§8§m══════════════════════════════");
broadcast("§6 🏆 Event Leaderboard §8 §e" + currentEvent.getDefinition().getDisplayName());
int rank = 1;
for (Map.Entry<UUID, Integer> e : lb) {
if (rank > 5) break;
Player p = Bukkit.getPlayer(e.getKey());
String name = p != null ? p.getName() : "Unbekannt";
String medal = switch (rank) { case 1 -> "§6🥇"; case 2 -> "§7🥈"; case 3 -> "§c🥉"; default -> "§7 " + rank + "."; };
broadcast(" " + medal + " §f" + name + " §8 §e" + e.getValue() + " Punkte");
rank++;
}
broadcast("§8§m══════════════════════════════");
}
private void distributeRewards(EventDefinition def) {
if (def.getRewards().isEmpty() || currentEvent == null) return;
for (UUID uuid : currentEvent.getParticipants()) {
Player p = Bukkit.getPlayer(uuid);
if (p == null) continue;
for (String cmd : def.getRewards())
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), cmd.replace("%player%", p.getName()));
}
}
public void distributeWinnerRewards(EventDefinition def, Player winner) {
if (def.getWinnerRewards().isEmpty() || winner == null) return;
runCommands(def.getWinnerRewards(), winner);
}
private void runCommands(List<String> cmds, Player player) {
for (String cmd : cmds) {
String filled = player != null ? cmd.replace("%player%", player.getName()) : cmd;
try { Bukkit.dispatchCommand(Bukkit.getConsoleSender(), filled); }
catch (Exception ex) { log.warning("Befehl fehlgeschlagen: " + filled); }
}
}
private void broadcast(String msg) { Bukkit.broadcastMessage(msg); }
public static String formatTime(int seconds) {
if (seconds <= 0) return "";
int m = seconds / 60, s = seconds % 60;
if (m == 0) return s + "s";
if (s == 0) return m + "m";
return m + "m " + s + "s";
}
public void enqueue(EventDefinition def) { queue.add(def); }
public void clearQueue() { queue.clear(); }
public int queueSize() { return queue.size(); }
public ActiveEvent getCurrentEvent() { return currentEvent; }
public boolean isRunning() { return currentEvent != null && currentEvent.getState() == ActiveEvent.State.RUNNING; }
public EventHandlerRegistry getHandlerRegistry() { return handlerRegistry; }
}