package dev.viper.eventengine.scheduler; import dev.viper.eventengine.EventEngine; import dev.viper.eventengine.model.EventDefinition; import dev.viper.eventengine.model.ScheduleEntry; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; import java.time.DayOfWeek; import java.time.LocalDateTime; import java.time.LocalTime; import java.util.List; import java.util.Optional; import java.util.logging.Logger; /** * Läuft jede Minute und prüft, ob ein geplantes Event feuern soll. * Unterstützt: * - Expliziten Zeitplan aus config.yml (schedule: []) * - Intervall-Modus (use-interval: true, interval-minutes: 60) */ public class EventScheduler { private final EventEngine plugin; private final Logger log; private BukkitTask minuteTask; private BukkitTask intervalTask; // Für Intervall-Modus: Zähler private int minuteCounter = 0; public EventScheduler(EventEngine plugin) { this.plugin = plugin; this.log = plugin.getLogger(); } public void start() { stop(); // Jede Minute: Zeitplan prüfen minuteTask = new BukkitRunnable() { @Override public void run() { tickSchedule(); } }.runTaskTimer(plugin, 1200L, 1200L); // 1200 Ticks = 60 Sekunden log.info("EventScheduler gestartet."); // Intervall-Modus als Zusatz if (plugin.getConfigManager().isUseInterval()) { startIntervalMode(); } } private void startIntervalMode() { int intervalMin = plugin.getConfigManager().getIntervalMinutes(); if (intervalMin <= 0) return; long ticks = intervalMin * 60L * 20L; intervalTask = new BukkitRunnable() { @Override public void run() { if (plugin.getEventManager().isRunning()) return; fireRandomOrDefault(); } }.runTaskTimer(plugin, ticks, ticks); log.info("Intervall-Modus: alle " + intervalMin + " Minuten."); } private void tickSchedule() { LocalDateTime now = LocalDateTime.now(); DayOfWeek day = now.getDayOfWeek(); LocalTime time = now.toLocalTime(); List schedule = plugin.getConfigManager().getSchedule(); for (ScheduleEntry entry : schedule) { if (!entry.matchesNow(day, time)) continue; if (plugin.getEventManager().isRunning()) { log.info("Zeitplan-Event übersprungen (läuft bereits): " + entry.getEventId()); continue; } // Ankündigung? int announceBefore = plugin.getConfigManager().getAnnounceBefore(); if (announceBefore > 0) { scheduleAnnouncement(entry, announceBefore); } fireScheduleEntry(entry); } } private void scheduleAnnouncement(ScheduleEntry entry, int secondsBefore) { String name = entry.isRandom() ? "ein zufälliges Event" : entry.getEventId(); long ticks = secondsBefore * 20L; // Ankündigung JETZT senden (Event startet in X Sekunden) // (Zeitplan feuert genau zur geplanten Minute) plugin.getServer().broadcastMessage( plugin.prefix() + "§e⏰ In §c" + secondsBefore + " Sekunden §estartet: §6" + name + "§e!"); } private void fireScheduleEntry(ScheduleEntry entry) { if (entry.isRandom()) { fireRandomOrDefault(); return; } Optional defOpt = plugin.getEventRegistry().get(entry.getEventId()); if (defOpt.isPresent()) { plugin.getEventManager().startEvent(defOpt.get(), null); } else { log.warning("Zeitplan-Event nicht gefunden: " + entry.getEventId() + " — feuere zufälliges."); fireRandomOrDefault(); } } private void fireRandomOrDefault() { if (plugin.getConfigManager().isRandomOnInterval()) { Optional random = plugin.getEventRegistry().getWeightedRandom(); random.ifPresent(def -> plugin.getEventManager().startEvent(def, null)); } else { String defaultId = plugin.getConfigManager().getDefaultEventId(); Optional def = plugin.getEventRegistry().get(defaultId); def.ifPresent(d -> plugin.getEventManager().startEvent(d, null)); } } public void stop() { if (minuteTask != null) { minuteTask.cancel(); minuteTask = null; } if (intervalTask != null) { intervalTask.cancel(); intervalTask = null; } } public void restart() { stop(); start(); } }