package dev.loki.loparkour.config.options; import dev.loki.loparkour.LoParkour; import dev.loki.loparkour.config.core.Config; import dev.loki.loparkour.menu.core.screen.ParkourOption; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.block.BlockFace; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; /** * General configuration options (heading, border, leads, go-back location, parkour options). */ public final class OptionGeneral { private static final int MAX_LEAD = 128; private static final int MIN_AXIS_VALUES = 4; private static final int WORLD_VALUE_INDEX = 3; private static final int FALLBACK_Y = 100; private OptionGeneral() { } public static double BORDER_SIZE; public static List POSSIBLE_LEADS; public static BlockFace HEADING; public static Location GO_BACK_LOC; public static Map OPTIONS_ENABLED; public static Map OPTIONS_DEFAULTS; public static void init(boolean firstLoad) { initGoBackLocation(); initLeads(); initHeading(); if (firstLoad) { BORDER_SIZE = Config.GENERATION.getDouble("advanced.border-size"); } } public static void initOptions() { final List options = new ArrayList<>(Arrays.asList(ParkourOption.values())); options.remove(ParkourOption.JOIN); options.remove(ParkourOption.ADMIN); OPTIONS_DEFAULTS = new HashMap<>(); OPTIONS_ENABLED = new HashMap<>(); for (final ParkourOption option : options) { applyOption(option); } } private static void applyOption(ParkourOption option) { final String parent = "default-values." + option.path; OPTIONS_ENABLED.put(option, Config.CONFIG.getBoolean(parent + ".enabled")); final String defaultPath = parent + ".default"; if (Config.CONFIG.isPath(defaultPath)) { applyDefaultValue(option, defaultPath); } else { warnMissingDefault(option, defaultPath); } } private static void applyDefaultValue(ParkourOption option, String defaultPath) { String value = Config.CONFIG.getString(defaultPath); // Sanitize legacy Boolean values for LANG option if (option == ParkourOption.LANG && ("true".equals(value) || "false".equals(value) || "1".equals(value) || "0".equals(value))) { value = "en"; LoParkour.getPlugin().getLogger().warning( "LANG option had invalid Boolean value, reset to 'en'"); } // Debug logging if (option == ParkourOption.LANG) { LoParkour.getPlugin().getLogger().info( "LANG option: path=" + defaultPath + ", value=" + value); } if (value != null && !value.isEmpty()) { OPTIONS_DEFAULTS.put(option, value); } } private static void warnMissingDefault(ParkourOption option, String defaultPath) { if (option == ParkourOption.LANG) { LoParkour.getPlugin().getLogger().warning("LANG default path not found: " + defaultPath); LoParkour.getPlugin().getLogger().warning( "Available keys: " + Config.CONFIG.fileConfiguration.getKeys(true)); } } private static void initGoBackLocation() { GO_BACK_LOC = parseLocation(Config.CONFIG.getString("bungeecord.go-back")); try { final String axesRaw = Config.CONFIG.getString("bungeecord.go-back-axes"); if (!axesRaw.isEmpty()) { final String[] axes = axesRaw.split(","); if (axes.length >= 2) { GO_BACK_LOC.setPitch(Float.parseFloat(axes[0].trim())); GO_BACK_LOC.setYaw(Float.parseFloat(axes[1].trim())); } } } catch (Exception ex) { LoParkour.getPlugin().getLogger().warning("Invalid bungeecord.go-back-axes, using 0,0"); } } private static void initLeads() { POSSIBLE_LEADS = Config.CONFIG.getIntList("options.leads.amount"); for (final int lead : new ArrayList<>(POSSIBLE_LEADS)) { if (lead < 1 || lead > MAX_LEAD) { LoParkour.getPlugin().getLogger().severe( "Invalid lead: %d. Must be 1–128.".formatted(lead)); POSSIBLE_LEADS.remove((Object) lead); } } } private static void initHeading() { final String heading = Config.GENERATION.getString("advanced.island.parkour.heading"); HEADING = switch (heading.toLowerCase()) { case "north" -> BlockFace.NORTH; case "south" -> BlockFace.SOUTH; case "west" -> BlockFace.WEST; case "east" -> BlockFace.EAST; default -> { LoParkour.getPlugin().getLogger().severe("Invalid heading: " + heading); yield BlockFace.NORTH; } }; } private static Location parseLocation(String location) { try { final String[] values = location.replaceAll("[()]", "").replaceAll("[, ]", " ").trim().split("\\s+"); if (values.length < MIN_AXIS_VALUES) { throw new IllegalArgumentException("Expected 4 values (x,y,z,world), got " + values.length); } World world = Bukkit.getWorld(values[WORLD_VALUE_INDEX]); if (world == null) { world = Bukkit.getWorlds().get(0); } return new Location(world, Double.parseDouble(values[0]), Double.parseDouble(values[1]), Double.parseDouble(values[2])); } catch (Exception ex) { LoParkour.getPlugin().getLogger().warning( "Invalid bungeecord.go-back value '" + location + "'. Falling back to spawn world origin."); final World fallback = Bukkit.getWorlds().isEmpty() ? null : Bukkit.getWorlds().get(0); return new Location(fallback, 0, FALLBACK_Y, 0); } } }