package com.mrkayjaydee.playhours.events; import com.mrkayjaydee.playhours.config.MOTDConfig; import com.mrkayjaydee.playhours.core.ForceMode; import com.mrkayjaydee.playhours.core.ScheduleService; import com.mrkayjaydee.playhours.events.ScheduleFormatter.FormattedSchedule; import com.mrkayjaydee.playhours.text.Messages; import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.List; import java.util.Optional; /** * Builds MOTD components based on configuration. * Supports multiple MOTD strategies: rotating, custom lines, custom format, and automatic. */ public final class MOTDBuilder { private MOTDBuilder() {} private static int currentRotationIndex = 0; private static long lastRotationTime = 0; private static List lastRotationTemplates = null; /** * Builds the MOTD component based on configuration and current schedule state. * Priority: rotation → custom lines → custom format → automatic * * @param scheduleService the schedule service * @param now the current time * @return the MOTD component */ public static Component build(ScheduleService scheduleService, ZonedDateTime now) { // Check for rotation first if (MOTDConfig.ROTATION_ENABLED.get()) { List templates = MOTDConfig.ROTATION_TEMPLATES.get(); if (templates != null && !templates.isEmpty()) { return buildRotating(scheduleService, now, templates); } } // Check for custom lines List customLines = MOTDConfig.CUSTOM_LINES.get(); if (customLines != null && !customLines.isEmpty()) { return buildCustomLines(scheduleService, now, customLines); } // Check for custom format String customFormat = MOTDConfig.CUSTOM_FORMAT.get(); if (customFormat != null && !customFormat.trim().isEmpty()) { return buildCustomFormat(scheduleService, now, customFormat); } // Build automatic MOTD return buildAutomatic(scheduleService, now); } /** * Builds a rotating MOTD that cycles through configured templates. */ private static Component buildRotating(ScheduleService scheduleService, ZonedDateTime now, List templates) { if (templates.isEmpty()) { return buildCustomLines(scheduleService, now, MOTDConfig.CUSTOM_LINES.get()); } // Check if template list changed if (lastRotationTemplates != templates) { lastRotationTemplates = templates; currentRotationIndex = 0; lastRotationTime = System.currentTimeMillis(); } // Calculate time elapsed since last rotation long currentTime = System.currentTimeMillis(); long rotationIntervalMillis = MOTDConfig.ROTATION_INTERVAL_SECONDS.get() * 1000L; long timeSinceLastRotation = currentTime - lastRotationTime; // Check if we should advance to next template if (timeSinceLastRotation >= rotationIntervalMillis) { // Move to next template currentRotationIndex = (currentRotationIndex + 1) % templates.size(); lastRotationTime = currentTime; } String template = templates.get(currentRotationIndex); return MOTDFormatter.formatLine(scheduleService, now, template); } /** * Builds MOTD from custom line configuration. */ private static Component buildCustomLines(ScheduleService scheduleService, ZonedDateTime now, List customLines) { MutableComponent result = Component.empty(); for (int i = 0; i < customLines.size(); i++) { String line = customLines.get(i); Component formatted = MOTDFormatter.formatLine(scheduleService, now, line); result.append(formatted); if (i < customLines.size() - 1) { result.append(Component.literal("\n")); } } return result; } /** * Builds MOTD from custom format string. */ private static Component buildCustomFormat(ScheduleService scheduleService, ZonedDateTime now, String format) { return MOTDFormatter.formatLine(scheduleService, now, format); } /** * Builds automatic MOTD based on configuration flags. */ private static Component buildAutomatic(ScheduleService scheduleService, ZonedDateTime now) { List parts = new ArrayList<>(); // Get schedule information boolean isOpen = scheduleService.isOpen(now); ForceMode forceMode = scheduleService.getForceMode(); Optional nextClose = scheduleService.nextClose(now); FormattedSchedule nextOpen = ScheduleFormatter.formatNextOpen(scheduleService.nextOpen(now)); // Show force mode if enabled if (MOTDConfig.SHOW_FORCE_MODE.get() && forceMode != ForceMode.NORMAL) { String forceModeText = forceMode == ForceMode.FORCE_OPEN ? Messages.get("msg.motd_force_open") : Messages.get("msg.motd_force_closed"); parts.add(MOTDFormatter.colorize(forceModeText, ChatFormatting.GOLD)); } // Show status if enabled if (MOTDConfig.SHOW_STATUS.get()) { String statusKey = isOpen ? "msg.motd_status_open" : "msg.motd_status_closed"; String statusText = Messages.get(statusKey); ChatFormatting statusColor = isOpen ? MOTDColorParser.parseColor(MOTDConfig.OPEN_COLOR.get()) : MOTDColorParser.parseColor(MOTDConfig.CLOSED_COLOR.get()); parts.add(MOTDFormatter.colorize(statusText, statusColor)); } // Show countdown if enabled and applicable if (MOTDConfig.SHOW_COUNTDOWN.get() && isOpen && nextClose.isPresent()) { addCountdownIfApplicable(parts, nextClose.get(), now); } // Show next close if enabled and open if (MOTDConfig.SHOW_NEXT_CLOSE.get() && isOpen && nextClose.isPresent()) { addNextClose(parts, nextClose.get()); } // Show next open if enabled and closed if (MOTDConfig.SHOW_NEXT_OPEN.get() && !isOpen) { addNextOpen(parts, nextOpen); } // Combine parts if (parts.isEmpty()) { return Component.literal(""); } return combineParts(parts); } private static void addCountdownIfApplicable(List parts, ZonedDateTime nextClose, ZonedDateTime now) { long minutesUntilClose = java.time.temporal.ChronoUnit.MINUTES.between(now, nextClose); int countdownThreshold = MOTDConfig.COUNTDOWN_THRESHOLD_MINUTES.get(); if (countdownThreshold > 0 && minutesUntilClose <= countdownThreshold && minutesUntilClose > 0) { String countdownText = Messages.get("msg.motd_countdown") .replace("%minutes%", String.valueOf(minutesUntilClose)); parts.add(MOTDFormatter.colorize(countdownText, ChatFormatting.YELLOW)); } } private static void addNextClose(List parts, ZonedDateTime nextClose) { String closeTime = com.mrkayjaydee.playhours.core.TimeRange.formatTime(nextClose.toLocalTime(), Messages.getJavaLocale()); String closeText = Messages.get("msg.motd_next_close") .replace("%closetime%", closeTime); ChatFormatting infoColor = MOTDColorParser.parseColor(MOTDConfig.INFO_COLOR.get()); parts.add(MOTDFormatter.colorize(closeText, infoColor)); } private static void addNextOpen(List parts, FormattedSchedule nextOpen) { String openText = Messages.get("msg.motd_next_open") .replace("%openday%", nextOpen.day) .replace("%opentime%", nextOpen.time); ChatFormatting infoColor = MOTDColorParser.parseColor(MOTDConfig.INFO_COLOR.get()); parts.add(MOTDFormatter.colorize(openText, infoColor)); } private static Component combineParts(List parts) { String separator = MOTDConfig.SEPARATOR.get(); boolean useSecondLine = MOTDConfig.SHOW_ON_SECOND_LINE.get(); MutableComponent result = Component.empty(); if (useSecondLine) { // Put on second line result.append(Component.literal("\n")); } for (int i = 0; i < parts.size(); i++) { result.append(parts.get(i)); if (i < parts.size() - 1) { result.append(Component.literal(separator)); } } return result; } }