Checkstyle is now a ratchet: severity="error" only for rules that are at zero violations, design-debt rules report as warnings and must be flipped to error as soon as their backlog hits zero (tracked in TODO.md). - thresholds tightened: MethodLength 80->40, CyclomaticComplexity 20->15, NestedIfDepth 3->2, ParameterNumber 7->5; new rules ReturnCount(5), FinalClass, HiddenField, VisibilityModifier; MagicNumber and FinalLocalVariable promoted from warning to error (both clean) - suppressions.xml emptied: 45 legacy entries removed, never add back - fixed 102 baseline violations (431->329): FinalClass in 37 classes, WhitespaceAround in 11 files - TODO.md: Task 1 done (lolib removed, smoke test passed) and Task 2 baseline recorded (red report, per-package list, next steps)
163 lines
6 KiB
Java
163 lines
6 KiB
Java
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<Integer> POSSIBLE_LEADS;
|
||
public static BlockFace HEADING;
|
||
public static Location GO_BACK_LOC;
|
||
|
||
public static Map<ParkourOption, Boolean> OPTIONS_ENABLED;
|
||
public static Map<ParkourOption, String> 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<ParkourOption> 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);
|
||
}
|
||
}
|
||
}
|