refactor(config): split Option.java into 5 specialized classes
- Created config/options/ package - OptionSQL.java - SQL configuration - OptionParticles.java - particles and sounds - OptionGeneration.java - generation parameters - OptionGeneral.java - general settings - OptionStyles.java - style initialization - Option.java now acts as facade with field sync - Backward compatibility maintained via public static fields - All tests pass, build successful Wave 1/8 complete (335 lines → 5 files)
This commit is contained in:
parent
a7afe34fea
commit
371e38bfac
6 changed files with 519 additions and 291 deletions
|
|
@ -1,332 +1,153 @@
|
||||||
package dev.loki.loparkour.config;
|
package dev.loki.loparkour.config;
|
||||||
|
|
||||||
import dev.loki.loparkour.LoParkour;
|
|
||||||
import dev.loki.loparkour.util.Materials;
|
|
||||||
import dev.loki.loparkour.api.Registry;
|
import dev.loki.loparkour.api.Registry;
|
||||||
|
import dev.loki.loparkour.config.options.*;
|
||||||
import dev.loki.loparkour.menu.ParkourOption;
|
import dev.loki.loparkour.menu.ParkourOption;
|
||||||
import dev.loki.loparkour.style.RandomStyle;
|
import dev.loki.loparkour.style.RandomStyle;
|
||||||
import dev.loki.loparkour.style.Style;
|
import dev.loki.loparkour.style.Style;
|
||||||
import dev.loki.loparkour.util.ParticleData;
|
import dev.loki.loparkour.util.ParticleData;
|
||||||
import org.bukkit.*;
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.Particle;
|
||||||
|
import org.bukkit.Sound;
|
||||||
import org.bukkit.block.BlockFace;
|
import org.bukkit.block.BlockFace;
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All config-derived constants used at runtime.
|
* Facade for all config-derived constants.
|
||||||
|
* Delegates to specialized option classes in config.options package.
|
||||||
*/
|
*/
|
||||||
public class Option {
|
public class Option {
|
||||||
|
|
||||||
// ── General ───────────────────────────────────────────────────────────────
|
// ── Initialization ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
public static double BORDER_SIZE;
|
public static void init(boolean firstLoad) {
|
||||||
public static List<Integer> POSSIBLE_LEADS;
|
OptionSQL.init();
|
||||||
public static BlockFace HEADING;
|
OptionParticles.init();
|
||||||
|
OptionGeneration.init();
|
||||||
|
OptionGeneral.init(firstLoad);
|
||||||
|
OptionGeneral.initOptions();
|
||||||
|
|
||||||
public static Map<ParkourOption, Boolean> OPTIONS_ENABLED;
|
// Sync all fields to Option facade
|
||||||
public static Map<ParkourOption, String> OPTIONS_DEFAULTS;
|
syncFields();
|
||||||
|
|
||||||
public static Location GO_BACK_LOC;
|
OptionStyles.initStyles("styles.list", Config.CONFIG.fileConfiguration, RandomStyle::new)
|
||||||
|
.forEach(Registry::register);
|
||||||
|
}
|
||||||
|
|
||||||
// ── SQL ───────────────────────────────────────────────────────────────────
|
// ── Direct field re-exports for backward compatibility ───────────────────
|
||||||
|
|
||||||
|
// SQL
|
||||||
public static boolean SQL;
|
public static boolean SQL;
|
||||||
public static String SQL_URL;
|
public static String SQL_URL;
|
||||||
public static int SQL_PORT;
|
public static int SQL_PORT;
|
||||||
public static String SQL_DB;
|
public static String SQL_DB;
|
||||||
public static String SQL_USERNAME;
|
public static String SQL_USERNAME;
|
||||||
public static String SQL_PASSWORD;
|
public static String SQL_PASSWORD;
|
||||||
public static String SQL_PREFIX;
|
public static String SQL_PREFIX;
|
||||||
|
|
||||||
// ── Particles / Sound ─────────────────────────────────────────────────────
|
// Particles
|
||||||
|
public static ParticleShape PARTICLE_SHAPE;
|
||||||
public static ParticleShape PARTICLE_SHAPE;
|
public static Sound SOUND_TYPE;
|
||||||
public static Sound SOUND_TYPE;
|
public static int SOUND_PITCH;
|
||||||
public static int SOUND_PITCH;
|
public static int SOUND_VOLUME;
|
||||||
public static int SOUND_VOLUME;
|
public static Particle PARTICLE_TYPE;
|
||||||
public static Particle PARTICLE_TYPE;
|
|
||||||
public static ParticleData<?> PARTICLE_DATA;
|
public static ParticleData<?> PARTICLE_DATA;
|
||||||
|
|
||||||
// ── Generation ────────────────────────────────────────────────────────────
|
// Generation
|
||||||
|
|
||||||
public static double TYPE_NORMAL, TYPE_SPECIAL, TYPE_SCHEMATICS;
|
public static double TYPE_NORMAL, TYPE_SPECIAL, TYPE_SCHEMATICS;
|
||||||
public static double SPECIAL_ICE, SPECIAL_SLAB, SPECIAL_PANE, SPECIAL_FENCE;
|
public static double SPECIAL_ICE, SPECIAL_SLAB, SPECIAL_PANE, SPECIAL_FENCE;
|
||||||
public static double NORMAL_DISTANCE_1, NORMAL_DISTANCE_2, NORMAL_DISTANCE_3, NORMAL_DISTANCE_4;
|
public static double NORMAL_DISTANCE_1, NORMAL_DISTANCE_2, NORMAL_DISTANCE_3, NORMAL_DISTANCE_4;
|
||||||
public static double NORMAL_HEIGHT_1, NORMAL_HEIGHT_0, NORMAL_HEIGHT_NEG1, NORMAL_HEIGHT_NEG2;
|
public static double NORMAL_HEIGHT_1, NORMAL_HEIGHT_0, NORMAL_HEIGHT_NEG1, NORMAL_HEIGHT_NEG2;
|
||||||
public static int MAX_Y, MIN_Y;
|
public static int MAX_Y, MIN_Y;
|
||||||
public static int BLOCK_CLEANUP_DISTANCE, CLEANUP_INTERVAL;
|
public static int BLOCK_CLEANUP_DISTANCE, CLEANUP_INTERVAL, TRAIL_KEEP_BEHIND;
|
||||||
/** Block indices to keep behind the rearmost player before trail air-cleanup. */
|
|
||||||
public static int TRAIL_KEEP_BEHIND;
|
|
||||||
public static boolean GHOST_MODE_ENABLED;
|
public static boolean GHOST_MODE_ENABLED;
|
||||||
public static int GHOST_SHOW_TOP;
|
public static int GHOST_SHOW_TOP;
|
||||||
public static double GHOST_TRANSPARENCY;
|
public static double GHOST_TRANSPARENCY;
|
||||||
|
|
||||||
// ── Jump validation ───────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
public static boolean JUMP_VALIDATION_ENABLED;
|
public static boolean JUMP_VALIDATION_ENABLED;
|
||||||
public static double MAX_JUMP_DISTANCE;
|
public static double MAX_JUMP_DISTANCE, MAX_HORIZONTAL_DISTANCE, MAX_VERTICAL_UP, MAX_VERTICAL_DOWN;
|
||||||
public static double MAX_HORIZONTAL_DISTANCE;
|
public static boolean JUMP_TYPES_ENABLED;
|
||||||
public static double MAX_VERTICAL_UP;
|
public static Map<String, Boolean> JUMP_TYPE_ENABLED;
|
||||||
public static double MAX_VERTICAL_DOWN;
|
public static Map<String, Double> JUMP_TYPE_CHANCE;
|
||||||
|
|
||||||
// ── Jump types ────────────────────────────────────────────────────────────
|
// General
|
||||||
|
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 boolean JUMP_TYPES_ENABLED;
|
private static void syncFields() {
|
||||||
public static Map<String, Boolean> JUMP_TYPE_ENABLED;
|
// SQL
|
||||||
public static Map<String, Double> JUMP_TYPE_CHANCE;
|
SQL = OptionSQL.SQL;
|
||||||
|
SQL_URL = OptionSQL.SQL_URL;
|
||||||
|
SQL_PORT = OptionSQL.SQL_PORT;
|
||||||
|
SQL_DB = OptionSQL.SQL_DB;
|
||||||
|
SQL_USERNAME = OptionSQL.SQL_USERNAME;
|
||||||
|
SQL_PASSWORD = OptionSQL.SQL_PASSWORD;
|
||||||
|
SQL_PREFIX = OptionSQL.SQL_PREFIX;
|
||||||
|
|
||||||
// ── init ──────────────────────────────────────────────────────────────────
|
// Particles
|
||||||
|
PARTICLE_SHAPE = OptionParticles.PARTICLE_SHAPE;
|
||||||
|
SOUND_TYPE = OptionParticles.SOUND_TYPE;
|
||||||
|
SOUND_PITCH = OptionParticles.SOUND_PITCH;
|
||||||
|
SOUND_VOLUME = OptionParticles.SOUND_VOLUME;
|
||||||
|
PARTICLE_TYPE = OptionParticles.PARTICLE_TYPE;
|
||||||
|
PARTICLE_DATA = OptionParticles.PARTICLE_DATA;
|
||||||
|
|
||||||
public static void init(boolean firstLoad) {
|
// Generation
|
||||||
initSql();
|
TYPE_NORMAL = OptionGeneration.TYPE_NORMAL;
|
||||||
initParticles();
|
TYPE_SPECIAL = OptionGeneration.TYPE_SPECIAL;
|
||||||
initGeneration();
|
TYPE_SCHEMATICS = OptionGeneration.TYPE_SCHEMATICS;
|
||||||
initGeneral(firstLoad);
|
SPECIAL_ICE = OptionGeneration.SPECIAL_ICE;
|
||||||
initOptions();
|
SPECIAL_SLAB = OptionGeneration.SPECIAL_SLAB;
|
||||||
|
SPECIAL_PANE = OptionGeneration.SPECIAL_PANE;
|
||||||
|
SPECIAL_FENCE = OptionGeneration.SPECIAL_FENCE;
|
||||||
|
NORMAL_DISTANCE_1 = OptionGeneration.NORMAL_DISTANCE_1;
|
||||||
|
NORMAL_DISTANCE_2 = OptionGeneration.NORMAL_DISTANCE_2;
|
||||||
|
NORMAL_DISTANCE_3 = OptionGeneration.NORMAL_DISTANCE_3;
|
||||||
|
NORMAL_DISTANCE_4 = OptionGeneration.NORMAL_DISTANCE_4;
|
||||||
|
NORMAL_HEIGHT_1 = OptionGeneration.NORMAL_HEIGHT_1;
|
||||||
|
NORMAL_HEIGHT_0 = OptionGeneration.NORMAL_HEIGHT_0;
|
||||||
|
NORMAL_HEIGHT_NEG1 = OptionGeneration.NORMAL_HEIGHT_NEG1;
|
||||||
|
NORMAL_HEIGHT_NEG2 = OptionGeneration.NORMAL_HEIGHT_NEG2;
|
||||||
|
MAX_Y = OptionGeneration.MAX_Y;
|
||||||
|
MIN_Y = OptionGeneration.MIN_Y;
|
||||||
|
BLOCK_CLEANUP_DISTANCE = OptionGeneration.BLOCK_CLEANUP_DISTANCE;
|
||||||
|
CLEANUP_INTERVAL = OptionGeneration.CLEANUP_INTERVAL;
|
||||||
|
TRAIL_KEEP_BEHIND = OptionGeneration.TRAIL_KEEP_BEHIND;
|
||||||
|
GHOST_MODE_ENABLED = OptionGeneration.GHOST_MODE_ENABLED;
|
||||||
|
GHOST_SHOW_TOP = OptionGeneration.GHOST_SHOW_TOP;
|
||||||
|
GHOST_TRANSPARENCY = OptionGeneration.GHOST_TRANSPARENCY;
|
||||||
|
JUMP_VALIDATION_ENABLED = OptionGeneration.JUMP_VALIDATION_ENABLED;
|
||||||
|
MAX_JUMP_DISTANCE = OptionGeneration.MAX_JUMP_DISTANCE;
|
||||||
|
MAX_HORIZONTAL_DISTANCE = OptionGeneration.MAX_HORIZONTAL_DISTANCE;
|
||||||
|
MAX_VERTICAL_UP = OptionGeneration.MAX_VERTICAL_UP;
|
||||||
|
MAX_VERTICAL_DOWN = OptionGeneration.MAX_VERTICAL_DOWN;
|
||||||
|
JUMP_TYPES_ENABLED = OptionGeneration.JUMP_TYPES_ENABLED;
|
||||||
|
JUMP_TYPE_ENABLED = OptionGeneration.JUMP_TYPE_ENABLED;
|
||||||
|
JUMP_TYPE_CHANCE = OptionGeneration.JUMP_TYPE_CHANCE;
|
||||||
|
|
||||||
initStyles("styles.list", Config.CONFIG.fileConfiguration, RandomStyle::new)
|
// General
|
||||||
.forEach(Registry::register);
|
BORDER_SIZE = OptionGeneral.BORDER_SIZE;
|
||||||
|
POSSIBLE_LEADS = OptionGeneral.POSSIBLE_LEADS;
|
||||||
|
HEADING = OptionGeneral.HEADING;
|
||||||
|
GO_BACK_LOC = OptionGeneral.GO_BACK_LOC;
|
||||||
|
OPTIONS_ENABLED = OptionGeneral.OPTIONS_ENABLED;
|
||||||
|
OPTIONS_DEFAULTS = OptionGeneral.OPTIONS_DEFAULTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── SQL ───────────────────────────────────────────────────────────────────
|
/** @deprecated Use {@link OptionStyles#initStyles(String, FileConfiguration, BiFunction)} */
|
||||||
|
@Deprecated
|
||||||
private static void initSql() {
|
public static Set<Style> initStyles(String path, FileConfiguration config,
|
||||||
SQL = Config.CONFIG.getBoolean("sql.enabled");
|
BiFunction<String, List<Material>, Style> fn) {
|
||||||
SQL_PORT = Config.CONFIG.getInt("sql.port");
|
return OptionStyles.initStyles(path, config, fn);
|
||||||
SQL_DB = Config.CONFIG.getString("sql.database");
|
|
||||||
SQL_URL = Config.CONFIG.getString("sql.url");
|
|
||||||
SQL_USERNAME = Config.CONFIG.getString("sql.username");
|
|
||||||
String envPassword = System.getenv("LOPARKOUR_SQL_PASSWORD");
|
|
||||||
SQL_PASSWORD = (envPassword != null && !envPassword.isEmpty())
|
|
||||||
? envPassword
|
|
||||||
: Config.CONFIG.getString("sql.password");
|
|
||||||
SQL_PREFIX = Config.CONFIG.getString("sql.prefix");
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Particles / Sound ─────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
private static void initParticles() {
|
|
||||||
SOUND_TYPE = resolveSound(Config.CONFIG.getString("particles.sound-type"));
|
|
||||||
PARTICLE_TYPE = resolveParticle(Config.CONFIG.getString("particles.particle-type"));
|
|
||||||
PARTICLE_SHAPE = resolveShape(Config.CONFIG.getString("particles.particle-shape"));
|
|
||||||
|
|
||||||
SOUND_PITCH = Config.CONFIG.getInt("particles.sound-pitch");
|
|
||||||
SOUND_VOLUME = Config.CONFIG.getInt("particles.sound-volume");
|
|
||||||
PARTICLE_DATA = new ParticleData<>(PARTICLE_TYPE, null, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Sound resolveSound(String name) {
|
|
||||||
if (name != null && !name.isEmpty()) {
|
|
||||||
try { return Sound.valueOf(name.toUpperCase()); }
|
|
||||||
catch (IllegalArgumentException ignored) {}
|
|
||||||
}
|
|
||||||
for (String fb : new String[]{"BLOCK_NOTE_BLOCK_GUITAR", "BLOCK_NOTE_BLOCK_PLING", "BLOCK_NOTE_PLING"}) {
|
|
||||||
try { return Sound.valueOf(fb); }
|
|
||||||
catch (IllegalArgumentException ignored) {}
|
|
||||||
}
|
|
||||||
LoParkour.getPlugin().getLogger().warning("Could not resolve any sound, using first available.");
|
|
||||||
return Sound.values()[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Particle resolveParticle(String name) {
|
|
||||||
if (name != null && !name.isEmpty()) {
|
|
||||||
try { return Particle.valueOf(name.toUpperCase()); }
|
|
||||||
catch (IllegalArgumentException ignored) {}
|
|
||||||
}
|
|
||||||
for (String fb : new String[]{"INSTANT_EFFECT", "SPELL_INSTANT", "CRIT"}) {
|
|
||||||
try { return Particle.valueOf(fb); }
|
|
||||||
catch (IllegalArgumentException ignored) {}
|
|
||||||
}
|
|
||||||
LoParkour.getPlugin().getLogger().warning("Could not resolve any particle, using first available.");
|
|
||||||
return Particle.values()[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ParticleShape resolveShape(String name) {
|
|
||||||
if (name != null && !name.isEmpty()) {
|
|
||||||
try { return ParticleShape.valueOf(name.toUpperCase()); }
|
|
||||||
catch (IllegalArgumentException ignored) {}
|
|
||||||
}
|
|
||||||
return ParticleShape.BOX;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Generation ────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
private static void initGeneration() {
|
|
||||||
JUMP_VALIDATION_ENABLED = Config.CONFIG.isPath("jump-validation.enabled") && Config.CONFIG.getBoolean("jump-validation.enabled");
|
|
||||||
MAX_JUMP_DISTANCE = Config.CONFIG.isPath("jump-validation.max-distance") ? Config.CONFIG.getDouble("jump-validation.max-distance") : 5.0;
|
|
||||||
MAX_HORIZONTAL_DISTANCE = Config.CONFIG.isPath("jump-validation.max-horizontal") ? Config.CONFIG.getDouble("jump-validation.max-horizontal") : 4.0;
|
|
||||||
MAX_VERTICAL_UP = Config.CONFIG.isPath("jump-validation.max-vertical-up") ? Config.CONFIG.getDouble("jump-validation.max-vertical-up") : 1.0;
|
|
||||||
MAX_VERTICAL_DOWN = Config.CONFIG.isPath("jump-validation.max-vertical-down") ? Config.CONFIG.getDouble("jump-validation.max-vertical-down") : 3.0;
|
|
||||||
|
|
||||||
JUMP_TYPES_ENABLED = Config.CONFIG.isPath("jump-types.enabled") && Config.CONFIG.getBoolean("jump-types.enabled");
|
|
||||||
JUMP_TYPE_ENABLED = new HashMap<>();
|
|
||||||
JUMP_TYPE_CHANCE = new HashMap<>();
|
|
||||||
if (Config.CONFIG.isPath("jump-types.types")) {
|
|
||||||
for (String type : Config.CONFIG.getChildren("jump-types.types")) {
|
|
||||||
String p = "jump-types.types." + type;
|
|
||||||
JUMP_TYPE_ENABLED.put(type, Config.CONFIG.isPath(p + ".enabled") && Config.CONFIG.getBoolean(p + ".enabled"));
|
|
||||||
JUMP_TYPE_CHANCE.put(type, Config.CONFIG.isPath(p + ".chance") ? Config.CONFIG.getDouble(p + ".chance") : 0.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BLOCK_CLEANUP_DISTANCE = Config.CONFIG.isPath("memory.block-cleanup-distance") ? Config.CONFIG.getInt("memory.block-cleanup-distance") : 100;
|
|
||||||
CLEANUP_INTERVAL = Config.CONFIG.isPath("memory.cleanup-interval") ? Config.CONFIG.getInt("memory.cleanup-interval") : 100;
|
|
||||||
TRAIL_KEEP_BEHIND = Config.CONFIG.isPath("memory.trail-keep-behind") ? Config.CONFIG.getInt("memory.trail-keep-behind") : 10;
|
|
||||||
|
|
||||||
GHOST_MODE_ENABLED = Config.CONFIG.isPath("ghost-mode.enabled") && Config.CONFIG.getBoolean("ghost-mode.enabled");
|
|
||||||
GHOST_SHOW_TOP = Config.CONFIG.isPath("ghost-mode.show-top") ? Config.CONFIG.getInt("ghost-mode.show-top") : 3;
|
|
||||||
GHOST_TRANSPARENCY = Config.CONFIG.isPath("ghost-mode.transparency") ? Config.CONFIG.getDouble("ghost-mode.transparency") : 0.5;
|
|
||||||
|
|
||||||
TYPE_NORMAL = Config.GENERATION.getInt("generation.type.normal") / 100.0;
|
|
||||||
TYPE_SPECIAL = Config.GENERATION.getInt("generation.type.special") / 100.0;
|
|
||||||
TYPE_SCHEMATICS = Config.GENERATION.getInt("generation.type.schematic") / 100.0;
|
|
||||||
|
|
||||||
SPECIAL_ICE = Config.GENERATION.getInt("generation.special.ice") / 100.0;
|
|
||||||
SPECIAL_SLAB = Config.GENERATION.getInt("generation.special.slab") / 100.0;
|
|
||||||
SPECIAL_PANE = Config.GENERATION.getInt("generation.special.pane") / 100.0;
|
|
||||||
SPECIAL_FENCE = Config.GENERATION.getInt("generation.special.fence") / 100.0;
|
|
||||||
|
|
||||||
NORMAL_DISTANCE_1 = Config.GENERATION.getInt("generation.normal.distance.1") / 100.0;
|
|
||||||
NORMAL_DISTANCE_2 = Config.GENERATION.getInt("generation.normal.distance.2") / 100.0;
|
|
||||||
NORMAL_DISTANCE_3 = Config.GENERATION.getInt("generation.normal.distance.3") / 100.0;
|
|
||||||
NORMAL_DISTANCE_4 = Config.GENERATION.getInt("generation.normal.distance.4") / 100.0;
|
|
||||||
|
|
||||||
NORMAL_HEIGHT_1 = Config.GENERATION.getInt("generation.normal.height.1") / 100.0;
|
|
||||||
NORMAL_HEIGHT_0 = Config.GENERATION.getInt("generation.normal.height.0") / 100.0;
|
|
||||||
NORMAL_HEIGHT_NEG1 = Config.GENERATION.getInt("generation.normal.height.-1") / 100.0;
|
|
||||||
NORMAL_HEIGHT_NEG2 = Config.GENERATION.getInt("generation.normal.height.-2") / 100.0;
|
|
||||||
|
|
||||||
MAX_Y = Config.GENERATION.getInt("generation.settings.max-y");
|
|
||||||
MIN_Y = Config.GENERATION.getInt("generation.settings.min-y");
|
|
||||||
|
|
||||||
if (MIN_Y >= MAX_Y) {
|
|
||||||
MIN_Y = 100; MAX_Y = 200;
|
|
||||||
LoParkour.getPlugin().getLogger().severe("min-y >= max-y in generation.yml — using defaults 100/200.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── General ───────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
private static void initGeneral(boolean firstLoad) {
|
|
||||||
GO_BACK_LOC = parseLocation(Config.CONFIG.getString("bungeecord.go-back"));
|
|
||||||
try {
|
|
||||||
String axesRaw = Config.CONFIG.getString("bungeecord.go-back-axes");
|
|
||||||
if (!axesRaw.isEmpty()) {
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
POSSIBLE_LEADS = Config.CONFIG.getIntList("options.leads.amount");
|
|
||||||
for (int lead : new ArrayList<>(POSSIBLE_LEADS)) {
|
|
||||||
if (lead < 1 || lead > 128) {
|
|
||||||
LoParkour.getPlugin().getLogger().severe("Invalid lead: %d. Must be 1–128.".formatted(lead));
|
|
||||||
POSSIBLE_LEADS.remove((Object) lead);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (firstLoad) {
|
|
||||||
BORDER_SIZE = Config.GENERATION.getDouble("advanced.border-size");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void initOptions() {
|
|
||||||
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 (ParkourOption option : options) {
|
|
||||||
String parent = "default-values." + option.path;
|
|
||||||
OPTIONS_ENABLED.put(option, Config.CONFIG.getBoolean(parent + ".enabled"));
|
|
||||||
|
|
||||||
String defaultPath = parent + ".default";
|
|
||||||
if (Config.CONFIG.isPath(defaultPath)) {
|
|
||||||
// Always read as String to avoid Boolean parsing issues
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Debug: path not found
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Helpers ───────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
private static Location parseLocation(String location) {
|
|
||||||
try {
|
|
||||||
String[] values = location.replaceAll("[()]", "").replaceAll("[, ]", " ").trim().split("\\s+");
|
|
||||||
if (values.length < 4) {
|
|
||||||
throw new IllegalArgumentException("Expected 4 values (x,y,z,world), got " + values.length);
|
|
||||||
}
|
|
||||||
World world = Bukkit.getWorld(values[3]);
|
|
||||||
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.");
|
|
||||||
World fallback = Bukkit.getWorlds().isEmpty() ? null : Bukkit.getWorlds().get(0);
|
|
||||||
return new Location(fallback, 0, 100, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Set<Style> initStyles(String path, FileConfiguration config, BiFunction<String, List<Material>, Style> fn) {
|
|
||||||
var styles = new HashSet<Style>();
|
|
||||||
ConfigAccessor accessor = new ConfigAccessor(config, "config.yml");
|
|
||||||
for (String style : accessor.getChildren(path, false)) {
|
|
||||||
styles.add(fn.apply(style,
|
|
||||||
config.getStringList("%s.%s".formatted(path, style)).stream()
|
|
||||||
.map(name -> {
|
|
||||||
Material m = Materials.parse(name);
|
|
||||||
if (m == null) {
|
|
||||||
LoParkour.getPlugin().getLogger().severe("Invalid material %s in style %s".formatted(name, style));
|
|
||||||
return Material.STONE;
|
|
||||||
}
|
|
||||||
return m;
|
|
||||||
})
|
|
||||||
.toList()));
|
|
||||||
}
|
|
||||||
return styles;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Inner types ───────────────────────────────────────────────────────────
|
// ── Inner types ───────────────────────────────────────────────────────────
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,138 @@
|
||||||
|
package dev.loki.loparkour.config.options;
|
||||||
|
|
||||||
|
import dev.loki.loparkour.LoParkour;
|
||||||
|
import dev.loki.loparkour.config.Config;
|
||||||
|
import dev.loki.loparkour.menu.ParkourOption;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* General configuration options (heading, border, leads, go-back location, parkour options).
|
||||||
|
*/
|
||||||
|
public class 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() {
|
||||||
|
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 (ParkourOption option : options) {
|
||||||
|
String parent = "default-values." + option.path;
|
||||||
|
OPTIONS_ENABLED.put(option, Config.CONFIG.getBoolean(parent + ".enabled"));
|
||||||
|
|
||||||
|
String defaultPath = parent + ".default";
|
||||||
|
if (Config.CONFIG.isPath(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);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Debug: path not found
|
||||||
|
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 {
|
||||||
|
String axesRaw = Config.CONFIG.getString("bungeecord.go-back-axes");
|
||||||
|
if (!axesRaw.isEmpty()) {
|
||||||
|
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 (int lead : new ArrayList<>(POSSIBLE_LEADS)) {
|
||||||
|
if (lead < 1 || lead > 128) {
|
||||||
|
LoParkour.getPlugin().getLogger().severe(
|
||||||
|
"Invalid lead: %d. Must be 1–128.".formatted(lead));
|
||||||
|
POSSIBLE_LEADS.remove((Object) lead);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void initHeading() {
|
||||||
|
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 {
|
||||||
|
String[] values = location.replaceAll("[()]", "").replaceAll("[, ]", " ").trim().split("\\s+");
|
||||||
|
if (values.length < 4) {
|
||||||
|
throw new IllegalArgumentException("Expected 4 values (x,y,z,world), got " + values.length);
|
||||||
|
}
|
||||||
|
World world = Bukkit.getWorld(values[3]);
|
||||||
|
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.");
|
||||||
|
World fallback = Bukkit.getWorlds().isEmpty() ? null : Bukkit.getWorlds().get(0);
|
||||||
|
return new Location(fallback, 0, 100, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,129 @@
|
||||||
|
package dev.loki.loparkour.config.options;
|
||||||
|
|
||||||
|
import dev.loki.loparkour.LoParkour;
|
||||||
|
import dev.loki.loparkour.config.Config;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generation-related configuration options (jump types, validation, memory, ghost mode).
|
||||||
|
*/
|
||||||
|
public class OptionGeneration {
|
||||||
|
|
||||||
|
// ── Block generation probabilities ────────────────────────────────────────
|
||||||
|
public static double TYPE_NORMAL, TYPE_SPECIAL, TYPE_SCHEMATICS;
|
||||||
|
public static double SPECIAL_ICE, SPECIAL_SLAB, SPECIAL_PANE, SPECIAL_FENCE;
|
||||||
|
public static double NORMAL_DISTANCE_1, NORMAL_DISTANCE_2, NORMAL_DISTANCE_3, NORMAL_DISTANCE_4;
|
||||||
|
public static double NORMAL_HEIGHT_1, NORMAL_HEIGHT_0, NORMAL_HEIGHT_NEG1, NORMAL_HEIGHT_NEG2;
|
||||||
|
public static int MAX_Y, MIN_Y;
|
||||||
|
|
||||||
|
// ── Memory / cleanup ──────────────────────────────────────────────────────
|
||||||
|
public static int BLOCK_CLEANUP_DISTANCE;
|
||||||
|
public static int CLEANUP_INTERVAL;
|
||||||
|
public static int TRAIL_KEEP_BEHIND;
|
||||||
|
|
||||||
|
// ── Ghost mode ────────────────────────────────────────────────────────────
|
||||||
|
public static boolean GHOST_MODE_ENABLED;
|
||||||
|
public static int GHOST_SHOW_TOP;
|
||||||
|
public static double GHOST_TRANSPARENCY;
|
||||||
|
|
||||||
|
// ── Jump validation ───────────────────────────────────────────────────────
|
||||||
|
public static boolean JUMP_VALIDATION_ENABLED;
|
||||||
|
public static double MAX_JUMP_DISTANCE;
|
||||||
|
public static double MAX_HORIZONTAL_DISTANCE;
|
||||||
|
public static double MAX_VERTICAL_UP;
|
||||||
|
public static double MAX_VERTICAL_DOWN;
|
||||||
|
|
||||||
|
// ── Jump types ────────────────────────────────────────────────────────────
|
||||||
|
public static boolean JUMP_TYPES_ENABLED;
|
||||||
|
public static Map<String, Boolean> JUMP_TYPE_ENABLED;
|
||||||
|
public static Map<String, Double> JUMP_TYPE_CHANCE;
|
||||||
|
|
||||||
|
public static void init() {
|
||||||
|
initJumpValidation();
|
||||||
|
initJumpTypes();
|
||||||
|
initMemory();
|
||||||
|
initGhostMode();
|
||||||
|
initGenerationProbabilities();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void initJumpValidation() {
|
||||||
|
JUMP_VALIDATION_ENABLED = Config.CONFIG.isPath("jump-validation.enabled")
|
||||||
|
&& Config.CONFIG.getBoolean("jump-validation.enabled");
|
||||||
|
MAX_JUMP_DISTANCE = Config.CONFIG.isPath("jump-validation.max-distance")
|
||||||
|
? Config.CONFIG.getDouble("jump-validation.max-distance") : 5.0;
|
||||||
|
MAX_HORIZONTAL_DISTANCE = Config.CONFIG.isPath("jump-validation.max-horizontal")
|
||||||
|
? Config.CONFIG.getDouble("jump-validation.max-horizontal") : 4.0;
|
||||||
|
MAX_VERTICAL_UP = Config.CONFIG.isPath("jump-validation.max-vertical-up")
|
||||||
|
? Config.CONFIG.getDouble("jump-validation.max-vertical-up") : 1.0;
|
||||||
|
MAX_VERTICAL_DOWN = Config.CONFIG.isPath("jump-validation.max-vertical-down")
|
||||||
|
? Config.CONFIG.getDouble("jump-validation.max-vertical-down") : 3.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void initJumpTypes() {
|
||||||
|
JUMP_TYPES_ENABLED = Config.CONFIG.isPath("jump-types.enabled")
|
||||||
|
&& Config.CONFIG.getBoolean("jump-types.enabled");
|
||||||
|
JUMP_TYPE_ENABLED = new HashMap<>();
|
||||||
|
JUMP_TYPE_CHANCE = new HashMap<>();
|
||||||
|
|
||||||
|
if (Config.CONFIG.isPath("jump-types.types")) {
|
||||||
|
for (String type : Config.CONFIG.getChildren("jump-types.types")) {
|
||||||
|
String p = "jump-types.types." + type;
|
||||||
|
JUMP_TYPE_ENABLED.put(type, Config.CONFIG.isPath(p + ".enabled")
|
||||||
|
&& Config.CONFIG.getBoolean(p + ".enabled"));
|
||||||
|
JUMP_TYPE_CHANCE.put(type, Config.CONFIG.isPath(p + ".chance")
|
||||||
|
? Config.CONFIG.getDouble(p + ".chance") : 0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void initMemory() {
|
||||||
|
BLOCK_CLEANUP_DISTANCE = Config.CONFIG.isPath("memory.block-cleanup-distance")
|
||||||
|
? Config.CONFIG.getInt("memory.block-cleanup-distance") : 100;
|
||||||
|
CLEANUP_INTERVAL = Config.CONFIG.isPath("memory.cleanup-interval")
|
||||||
|
? Config.CONFIG.getInt("memory.cleanup-interval") : 100;
|
||||||
|
TRAIL_KEEP_BEHIND = Config.CONFIG.isPath("memory.trail-keep-behind")
|
||||||
|
? Config.CONFIG.getInt("memory.trail-keep-behind") : 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void initGhostMode() {
|
||||||
|
GHOST_MODE_ENABLED = Config.CONFIG.isPath("ghost-mode.enabled")
|
||||||
|
&& Config.CONFIG.getBoolean("ghost-mode.enabled");
|
||||||
|
GHOST_SHOW_TOP = Config.CONFIG.isPath("ghost-mode.show-top")
|
||||||
|
? Config.CONFIG.getInt("ghost-mode.show-top") : 3;
|
||||||
|
GHOST_TRANSPARENCY = Config.CONFIG.isPath("ghost-mode.transparency")
|
||||||
|
? Config.CONFIG.getDouble("ghost-mode.transparency") : 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void initGenerationProbabilities() {
|
||||||
|
TYPE_NORMAL = Config.GENERATION.getInt("generation.type.normal") / 100.0;
|
||||||
|
TYPE_SPECIAL = Config.GENERATION.getInt("generation.type.special") / 100.0;
|
||||||
|
TYPE_SCHEMATICS = Config.GENERATION.getInt("generation.type.schematic") / 100.0;
|
||||||
|
|
||||||
|
SPECIAL_ICE = Config.GENERATION.getInt("generation.special.ice") / 100.0;
|
||||||
|
SPECIAL_SLAB = Config.GENERATION.getInt("generation.special.slab") / 100.0;
|
||||||
|
SPECIAL_PANE = Config.GENERATION.getInt("generation.special.pane") / 100.0;
|
||||||
|
SPECIAL_FENCE = Config.GENERATION.getInt("generation.special.fence") / 100.0;
|
||||||
|
|
||||||
|
NORMAL_DISTANCE_1 = Config.GENERATION.getInt("generation.normal.distance.1") / 100.0;
|
||||||
|
NORMAL_DISTANCE_2 = Config.GENERATION.getInt("generation.normal.distance.2") / 100.0;
|
||||||
|
NORMAL_DISTANCE_3 = Config.GENERATION.getInt("generation.normal.distance.3") / 100.0;
|
||||||
|
NORMAL_DISTANCE_4 = Config.GENERATION.getInt("generation.normal.distance.4") / 100.0;
|
||||||
|
|
||||||
|
NORMAL_HEIGHT_1 = Config.GENERATION.getInt("generation.normal.height.1") / 100.0;
|
||||||
|
NORMAL_HEIGHT_0 = Config.GENERATION.getInt("generation.normal.height.0") / 100.0;
|
||||||
|
NORMAL_HEIGHT_NEG1 = Config.GENERATION.getInt("generation.normal.height.-1") / 100.0;
|
||||||
|
NORMAL_HEIGHT_NEG2 = Config.GENERATION.getInt("generation.normal.height.-2") / 100.0;
|
||||||
|
|
||||||
|
MAX_Y = Config.GENERATION.getInt("generation.settings.max-y");
|
||||||
|
MIN_Y = Config.GENERATION.getInt("generation.settings.min-y");
|
||||||
|
|
||||||
|
if (MIN_Y >= MAX_Y) {
|
||||||
|
MIN_Y = 100;
|
||||||
|
MAX_Y = 200;
|
||||||
|
LoParkour.getPlugin().getLogger().severe(
|
||||||
|
"min-y >= max-y in generation.yml — using defaults 100/200.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
package dev.loki.loparkour.config.options;
|
||||||
|
|
||||||
|
import dev.loki.loparkour.LoParkour;
|
||||||
|
import dev.loki.loparkour.config.Config;
|
||||||
|
import dev.loki.loparkour.config.Option;
|
||||||
|
import dev.loki.loparkour.util.ParticleData;
|
||||||
|
import org.bukkit.Particle;
|
||||||
|
import org.bukkit.Sound;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Particle and sound configuration options.
|
||||||
|
*/
|
||||||
|
public class OptionParticles {
|
||||||
|
|
||||||
|
public static Option.ParticleShape PARTICLE_SHAPE;
|
||||||
|
public static Sound SOUND_TYPE;
|
||||||
|
public static int SOUND_PITCH;
|
||||||
|
public static int SOUND_VOLUME;
|
||||||
|
public static Particle PARTICLE_TYPE;
|
||||||
|
public static ParticleData<?> PARTICLE_DATA;
|
||||||
|
|
||||||
|
public static void init() {
|
||||||
|
SOUND_TYPE = resolveSound(Config.CONFIG.getString("particles.sound-type"));
|
||||||
|
PARTICLE_TYPE = resolveParticle(Config.CONFIG.getString("particles.particle-type"));
|
||||||
|
PARTICLE_SHAPE = resolveShape(Config.CONFIG.getString("particles.particle-shape"));
|
||||||
|
|
||||||
|
SOUND_PITCH = Config.CONFIG.getInt("particles.sound-pitch");
|
||||||
|
SOUND_VOLUME = Config.CONFIG.getInt("particles.sound-volume");
|
||||||
|
PARTICLE_DATA = new ParticleData<>(PARTICLE_TYPE, null, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Sound resolveSound(String name) {
|
||||||
|
if (name != null && !name.isEmpty()) {
|
||||||
|
try { return Sound.valueOf(name.toUpperCase()); }
|
||||||
|
catch (IllegalArgumentException ignored) {}
|
||||||
|
}
|
||||||
|
for (String fb : new String[]{"BLOCK_NOTE_BLOCK_GUITAR", "BLOCK_NOTE_BLOCK_PLING", "BLOCK_NOTE_PLING"}) {
|
||||||
|
try { return Sound.valueOf(fb); }
|
||||||
|
catch (IllegalArgumentException ignored) {}
|
||||||
|
}
|
||||||
|
LoParkour.getPlugin().getLogger().warning("Could not resolve any sound, using first available.");
|
||||||
|
return Sound.values()[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Particle resolveParticle(String name) {
|
||||||
|
if (name != null && !name.isEmpty()) {
|
||||||
|
try { return Particle.valueOf(name.toUpperCase()); }
|
||||||
|
catch (IllegalArgumentException ignored) {}
|
||||||
|
}
|
||||||
|
for (String fb : new String[]{"INSTANT_EFFECT", "SPELL_INSTANT", "CRIT"}) {
|
||||||
|
try { return Particle.valueOf(fb); }
|
||||||
|
catch (IllegalArgumentException ignored) {}
|
||||||
|
}
|
||||||
|
LoParkour.getPlugin().getLogger().warning("Could not resolve any particle, using first available.");
|
||||||
|
return Particle.values()[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Option.ParticleShape resolveShape(String name) {
|
||||||
|
if (name != null && !name.isEmpty()) {
|
||||||
|
try { return Option.ParticleShape.valueOf(name.toUpperCase()); }
|
||||||
|
catch (IllegalArgumentException ignored) {}
|
||||||
|
}
|
||||||
|
return Option.ParticleShape.BOX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
package dev.loki.loparkour.config.options;
|
||||||
|
|
||||||
|
import dev.loki.loparkour.LoParkour;
|
||||||
|
import dev.loki.loparkour.config.Config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SQL database configuration options.
|
||||||
|
*/
|
||||||
|
public class OptionSQL {
|
||||||
|
|
||||||
|
public static boolean SQL;
|
||||||
|
public static String SQL_URL;
|
||||||
|
public static int SQL_PORT;
|
||||||
|
public static String SQL_DB;
|
||||||
|
public static String SQL_USERNAME;
|
||||||
|
public static String SQL_PASSWORD;
|
||||||
|
public static String SQL_PREFIX;
|
||||||
|
|
||||||
|
public static void init() {
|
||||||
|
SQL = Config.CONFIG.getBoolean("sql.enabled");
|
||||||
|
SQL_PORT = Config.CONFIG.getInt("sql.port");
|
||||||
|
SQL_DB = Config.CONFIG.getString("sql.database");
|
||||||
|
SQL_URL = Config.CONFIG.getString("sql.url");
|
||||||
|
SQL_USERNAME = Config.CONFIG.getString("sql.username");
|
||||||
|
|
||||||
|
// Environment variable override for password
|
||||||
|
String envPassword = System.getenv("LOPARKOUR_SQL_PASSWORD");
|
||||||
|
SQL_PASSWORD = (envPassword != null && !envPassword.isEmpty())
|
||||||
|
? envPassword
|
||||||
|
: Config.CONFIG.getString("sql.password");
|
||||||
|
|
||||||
|
SQL_PREFIX = Config.CONFIG.getString("sql.prefix");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
package dev.loki.loparkour.config.options;
|
||||||
|
|
||||||
|
import dev.loki.loparkour.LoParkour;
|
||||||
|
import dev.loki.loparkour.config.ConfigAccessor;
|
||||||
|
import dev.loki.loparkour.style.Style;
|
||||||
|
import dev.loki.loparkour.util.Materials;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Style initialization utilities.
|
||||||
|
*/
|
||||||
|
public class OptionStyles {
|
||||||
|
|
||||||
|
public static Set<Style> initStyles(String path, FileConfiguration config,
|
||||||
|
BiFunction<String, List<Material>, Style> fn) {
|
||||||
|
var styles = new HashSet<Style>();
|
||||||
|
ConfigAccessor accessor = new ConfigAccessor(config, "config.yml");
|
||||||
|
|
||||||
|
for (String style : accessor.getChildren(path, false)) {
|
||||||
|
styles.add(fn.apply(style,
|
||||||
|
config.getStringList("%s.%s".formatted(path, style)).stream()
|
||||||
|
.map(name -> {
|
||||||
|
Material m = Materials.parse(name);
|
||||||
|
if (m == null) {
|
||||||
|
LoParkour.getPlugin().getLogger().severe(
|
||||||
|
"Invalid material %s in style %s".formatted(name, style));
|
||||||
|
return Material.STONE;
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
})
|
||||||
|
.toList()));
|
||||||
|
}
|
||||||
|
return styles;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue