LoParkour/src/main/java/dev/loki/loparkour/config/options/OptionGeneral.java
loki5512344 e8b6569ccf
build: two-tier checkstyle gate, empty suppressions, fix baseline
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)
2026-10-06 14:17:14 +02:00

163 lines
6 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);
}
}
}