275 lines
12 KiB
Java
275 lines
12 KiB
Java
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; }
|
||
} |