refactor(config): encapsulate option sections, drop the Option mirror
Option was a facade of 45 public static fields kept in sync with the four sections by syncFields(); the sections themselves also exposed public static mutable fields. 88 VisibilityModifier violations in one place and two owners for every value. - Option keeps only init(boolean) (the reload entry ConfigLoader calls); the mirrors, syncFields() and the unused @Deprecated initStyles are gone - sections hold private static state behind fluent accessors (OptionSQL.enabled(), OptionGeneration.cleanupInterval(), OptionGeneral.goBackLocation()); the two Option.SQL = false writes become OptionSQL.disable() - collection/location accessors hand out unmodifiable views and a Location copy, so no caller can mutate loaded config state - ParticleShape promoted from nested enum to config/options/ParticleShape - delete 17 never-read generation probability fields and initGenerationProbabilities(): live weights come from advanced.* via GeneratorProfileManager/GenerationProfileLoader; min-y/max-y guard moved 1:1 into initBounds() - rewrite 63 Option.<FIELD> reads in 19 files to the section accessors - validateConfigs() now checks the paths the code actually consumes (advanced.distance/height/type weights) instead of the dead generation.normal.* - ParkourRestrictionListener.onChat: getOrDefault(CHAT, true) instead of unboxing a Boolean that may be absent checkstyle 0 errors / 329 -> 240 warnings (VisibilityModifier 163 -> 75); config/options itself is clean. Dead config keys found on the way are filed as TODO items 164-166. ./gradlew check green: PMD 0, 94 tests, NullAway unchanged.
This commit is contained in:
parent
4263df50a2
commit
c120309663
27 changed files with 386 additions and 359 deletions
47
TODO.md
47
TODO.md
|
|
@ -112,10 +112,10 @@
|
|||
|
||||
- **60. `SQLDataMapper` UUID.fromString кидает unchecked IllegalArgumentException** (SQLDataMapper.java:65,31) мимо catch(SQLException) → битые строки роняют чтение. → Ловить и логировать/скипать строку.
|
||||
- **61. `SQLQueryExecutor.prepareStatement`** (без callers) никогда не закрывает connection → утечка пула при будущем использовании. → try-with-resources / borrow-tracking.
|
||||
- **62. `SQLMigrationManager` мёртв; `migration_adaptive.sql` ссылается на несуществующую `loparkour_scores` и нигде не исполняется**; та же DDL в 3 копиях; префикс `SQL_PREFIX` применён непоследовательно. → Единый мигратор с версионированием; починить/удалить SQL-файл.
|
||||
- **62. `SQLMigrationManager` мёртв; `migration_adaptive.sql` ссылается на несуществующую `loparkour_scores` и нигде не исполняется**; та же DDL в 3 копиях; префикс `OptionSQL.prefix()` применён непоследовательно. → Единый мигратор с версионированием; починить/удалить SQL-файл.
|
||||
- **63. `writeScores` гоняет всю таблицу туда-сюда** без дельт (StorageSQL.java:105-128). → Инкрементальные upsert'ы только изменённых записей.
|
||||
- **64. `Score.fromString` — CSV по запятой: ник с `,` ломает все поля** (Score.java:19-31). → Экранирование или JSON.
|
||||
- **65. `validateConnection` мутирует `Option.SQL=false` при транзиентном сбое** (SQLConnectionManager.java:81-86) — SQL отключается навсегда. → Отдельный флаг/ретрай.
|
||||
- **65. `validateConnection` мутирует `OptionSQL.disable()` при транзиентном сбое** (SQLConnectionManager.java:87-92) — SQL отключается навсегда. → Отдельный флаг/ретрай.
|
||||
|
||||
### Adaptive
|
||||
|
||||
|
|
@ -126,11 +126,14 @@
|
|||
|
||||
### Config / reload
|
||||
|
||||
- **70. `/lp reload` не атомарен**: дублирует `Registry.STYLES` (никогда не чистится), оставляет старые `Rewards` при `enabled:false`, `BORDER_SIZE` устаревший, миры/генераторы не обновляются (ConfigUpdater, OptionStyles.java:23-43, Rewards.java:41-52, OptionGeneral.java:38-40). → Полный reset registry + пересоздание зависимых подсистем.
|
||||
- **70. `/lp reload` не атомарен**: дублирует `Registry.STYLES` (никогда не чистится), оставляет старые `Rewards` при `enabled:false`, `OptionGeneral.borderSize()` устаревший (перечитывается только при `firstLoad`), миры/генераторы не обновляются (ConfigUpdater, OptionStyles.java:23-43, Rewards.java:41-52, OptionGeneral.java:44-50). → Полный reset registry + пересоздание зависимых подсистем.
|
||||
- **71. `LocaleLoader` при ошибке подменяет кэш на emptyMap** → все сообщения пустые (LocaleCache.java:22-25). → Сохранять старый кэш при сбое.
|
||||
- **72. Нет fallback на en** для пропущенных ключей/неизвестных локалей (Locales.java:69-71). → Fallback-цепочка locale → en.
|
||||
- **73. `Rewards.init()` при `enabled:false` не чистит статические мапы** → старые награды продолжают выдаваться после reload. → Очистка.
|
||||
- **74. `ConfigAccessor` типо-опечатка тихо даёт false/0** (ConfigAccessor.java:45-48). → Строгая валидация ключей при старте.
|
||||
- **164. Секция `generation.*` в generation.yml игнорируется.** Живые веса берутся из `advanced.distance|height|type|special` (`GeneratorProfileManager`, `GenerationProfileLoader`), а `generation.type|normal|special` читал только мёртвый `OptionGeneration.initGenerationProbabilities()` — удалён на шаге инкапсуляции `config/options`. В shipped `generation.yml` обе секции дублируют друг друга (значения разные: 85/10/5 против 80/15/5) → пользователь правит то, что не работает. → Либо удалить `generation.type|normal|special` из generation.yml, либо сделать их источником для профилей; `generation.settings.min-y/max-y` остаются живыми. `ConfigLoader.validateConfigs` уже проверяет живые пути `advanced.*`.
|
||||
- **165. Мёртвый конфиг частиц/звуков.** `particles.sound-type|sound-pitch|sound-volume|particle-type|particle-shape` читаются в `OptionParticles`, все 6 геттеров (`shape()`, `soundType()`, `particleData()`…) не вызываются нигде → настройки не влияют на игру (используются per-player `ParkourPlayer.particles/sound` из меню). → Подключить в рендере частиц/звуков (`util/particle/`, `HookSound`) или убрать секцию из config.yml.
|
||||
- **166. Ещё два читаемых, но не потребляемых ключа.** `options.leads.amount` → `OptionGeneral.possibleLeads()` (валидация 1–128 и лог работают, список не читает никто — lead берётся из `default-values.leads.default`), `memory.block-cleanup-distance` → `OptionGeneration.blockCleanupDistance()` (дистанция чистки захардкожена в `GeneratorCleanup`). → Подключить или удалить.
|
||||
|
||||
### Session
|
||||
|
||||
|
|
@ -169,7 +172,7 @@
|
|||
- **95. `SchematicIdGenerator` хеширует только byte-координаты → коллизии id** (SchematicIdGenerator.java:23-28).
|
||||
- **96. `parseDifficulty` принимает NaN/Infinity** (SchematicCreator.java:64-70) → схема навсегда невыбираема.
|
||||
- **97. `stem()` регистрирует файл `.nbt` под пустым id**; `.NBT` игнорируется, `.schematic` — case-insensitive (SchematicManager.java:147-150,88).
|
||||
- **98. `Locales.getPlayerLocale`/`ParkourUser.locale` deref `OPTIONS_DEFAULTS.get(LANG)` без null-check** (Locales.java:170-184, ParkourUser.java:64).
|
||||
- **98. `Locales.getPlayerLocale`/`ParkourUser.locale` deref `OptionGeneral.optionsDefaults().get(LANG)` без null-check** (Locales.java:170-184, ParkourUser.java:64).
|
||||
- **99. Магические числа**: fall-threshold -30 (LifecycleTickManager.java:72), render 24.0/0.1/%4 (InvisibleBarrierMode.java:67-68,98), 10/30 (GravityShiftMode.java:82,108), 100 тиков (RaceMode.java:147), hotbar delay 5 (ParkourPlayer.java:192), `TICKS_PER_SECOND=20` переопределён (SpeedrunMode.java:82). → В конфиг/константы.
|
||||
- **100. Deprecated API**: `Material.STONE_SLAB` (MaterialUtil.java:20), `registerNewObjective(String,String,String)` (ScoreboardManager.java:75), `getOfflinePlayer(name)` (AdminCommandHandler.java:186-199), legacy ACTION_BAR (ParkourSpectator.java:73, RaceMode.java:103).
|
||||
- **101. `ParkourSpectator.java:96` — бессмысленный double-set spectator target** (no-op).
|
||||
|
|
@ -427,14 +430,38 @@ Checkstyle отработал `0 errors` (error-уровневые legacy-нар
|
|||
> Изменено 45 файлов (TODO.md, 2 конфига линтеров, 46 исходников).
|
||||
>
|
||||
> **Осталось (порядок):**
|
||||
> 1. Тест-гейт «**в папке ≤ 4 файлов**» (JUnit, без новых зависимостей) + разбивка 6 переполненных пакетов:
|
||||
> `elytra/generator` 7, `elytra/mode` 6, `command/schematic` 6, `player/core` 5, `generator/jump/placement` 5, `generator/jump/calculation` 5 —
|
||||
> 10 файлов переносятся в подпапки (механически: package + импорты).
|
||||
> 2. Пакет за пакетом обнулять бэклог, начиная с `config/options` (91 нарушение в 2 файлах: `Option` — 45 public-полей,
|
||||
> `OptionGeneration` — 25; это и есть п.77/107 про public mutable state) → после обнуления перевести правило в error.
|
||||
> 1. ✅ Тест-гейт «**в папке ≤ 4 файлов**» (JUnit, без новых зависимостей) + разбивка 6 переполненных пакетов —
|
||||
> сделано в `4263df5`, `FOLDER_DEBT = Set.of()`, ни одна папка `src/main/java` не содержит >4 файлов.
|
||||
> 2. ✅ Бэклог `config/options` обнулён (см. ПРОГРЕСС-5 ниже) → **`VisibilityModifier` ещё НЕ в error**: в пакете остались
|
||||
> только 2 `IllegalCatch` (общий бэклог п.3), а правило висит на 75 нарушениях в других пакетах.
|
||||
> 3. `IllegalCatch` 23: 3 сайта намеренные (команда/конфиг с откатом/скетчи — boundary-catch), остальные 20 — выловить конкретные типы;
|
||||
> **нужно решение владельца** по трём.
|
||||
> 4. Дальше по плану (a): PMD-категории целиком, CPD, SpotBugs, ArchUnit-слои, JaCoCo, Spotless, quality-job в CI.
|
||||
> 4. Дальше по плану (a): PMD-категории целиком, CPD, SpotBugs, ArchUnit-слои, JaCoCo, Spotless, quality-job в CI — ✅ сделано в `b771cc1`.
|
||||
>
|
||||
> ## ✅ ПРОГРЕСС-5 (Задача 2, шаг (c): `config/options` инкапсулирован, 2026-10-06)
|
||||
> Был анти-паттерн: `Option` — фасад-зеркало на **45 `public static` полей**, которые `syncFields()` копировал
|
||||
> из 4 секций (`OptionSQL`, `OptionParticles`, `OptionGeneration`, `OptionGeneral`), и в самих секциях поля тоже
|
||||
> были `public static` (мутабельное состояние чужих пакетов = п.77/107 в миниатюре).
|
||||
> - **`Option` сокращён до `init(boolean)`** — единственная точка перезагрузки конфигов (её зовёт `ConfigLoader`);
|
||||
> зеркало, `syncFields()` и мёртвый `@Deprecated initStyles` (0 вызовов) удалены. Класс больше не дублирует секции.
|
||||
> - **Секции: `private static` поля + fluent-аксессоры** (`OptionSQL.enabled()`, `OptionGeneration.cleanupInterval()`,
|
||||
> `OptionGeneral.goBackLocation()`…), без префикса `get` — как у соседних статик-холдеров (`Materials.parse`, `Probs.random`).
|
||||
> Две точки записи `Option.SQL = false` → `OptionSQL.disable()`.
|
||||
> - **Защита от протечки состояния:** `possibleLeads()/optionsEnabled()/optionsDefaults()` отдают unmodifiable-представления
|
||||
> (null сохраняется как раньше), `goBackLocation()` — копию (`Location` мутируется при reload через `setPitch/setYaw`).
|
||||
> - `ParticleShape` вынесен из вложенного enum'а в `config/options/ParticleShape.java` (в `section/` леж бы 5-й файл — гейт «≤4»).
|
||||
> - **Удалены мёртвые данные:** 17 полей вероятностей генерации + `initGenerationProbabilities()` — не читались нигде,
|
||||
> живые веса берутся из `advanced.*` (`GeneratorProfileManager`/`GenerationProfileLoader`). Границы `min-y/max-y`
|
||||
> с проверкой `minY >= maxY` перенесены 1-в-1 в `initBounds()`. Найденное оформлено пунктами **164–166**.
|
||||
> - **63 обращения `Option.<ПОЛЕ>`** (не 127 — счёт предыдущей сессии был завышен из-за подстроки в `ParkourOption.*`)
|
||||
> переписаны в **19 файлах**; `Option`-импорт остался только в `ConfigLoader`.
|
||||
> - Попутно (предложения `CodeReview`): `ConfigLoader.validateConfigs()` проверяет **живые** пути
|
||||
> `advanced.distance.chances|height.chances|height.min|max|type` (раньше проверялась мёртвая секция `generation.normal.height.*`);
|
||||
> в `ParkourRestrictionListener.onChat` unboxing `Boolean` → `getOrDefault(CHAT, true)` как в `ParkourOption.mayPerform`.
|
||||
> - **Счётчики:** checkstyle **0 error / 329 → 240 warning**; `VisibilityModifier` **163 → 75**, `MethodLength` 5 → 4.
|
||||
> В `config/options` — **0 нарушений VisibilityModifier** (было 88), остаются 2 `IllegalCatch`.
|
||||
> `./gradlew check` зелёный: PMD 0, тесты 94/0 fail, JaCoCo/ArchUnit/Spotless ок, NullAway 48 (как в baseline).
|
||||
> Пороги правил не снижались, `suppressions.xml` пустая. Реальных прогонов на сервере после правок не было (только `check`).
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import dev.loki.loparkour.adaptive.model.SkillRating;
|
|||
import dev.loki.loparkour.adaptive.storage.FileStatsStorage;
|
||||
import dev.loki.loparkour.adaptive.storage.SQLStatsStorage;
|
||||
import dev.loki.loparkour.adaptive.storage.StatsRepository;
|
||||
import dev.loki.loparkour.config.options.Option;
|
||||
import dev.loki.loparkour.config.options.section.OptionSQL;
|
||||
import dev.loki.loparkour.generator.core.coordinator.ParkourGenerator;
|
||||
import dev.loki.loparkour.generator.core.model.Profile;
|
||||
import dev.loki.loparkour.player.core.ParkourPlayer;
|
||||
|
|
@ -42,7 +42,7 @@ public final class AdaptiveServices {
|
|||
}
|
||||
|
||||
final Runnable setup = () -> startCollector(createRepository());
|
||||
if (Option.SQL) {
|
||||
if (OptionSQL.enabled()) {
|
||||
Storage.runWhenReady(setup);
|
||||
} else {
|
||||
setup.run();
|
||||
|
|
@ -54,7 +54,7 @@ public final class AdaptiveServices {
|
|||
AdaptiveConfig.reload();
|
||||
if (plugin != null && AdaptiveConfig.isEnabled()) {
|
||||
final Runnable setup = () -> startCollector(createRepository());
|
||||
if (Option.SQL) {
|
||||
if (OptionSQL.enabled()) {
|
||||
Storage.runWhenReady(setup);
|
||||
} else {
|
||||
setup.run();
|
||||
|
|
@ -147,7 +147,7 @@ public final class AdaptiveServices {
|
|||
|
||||
@NotNull
|
||||
private static StatsRepository createRepository() {
|
||||
if (Option.SQL && StorageSQL.isConnected()) {
|
||||
if (OptionSQL.enabled() && StorageSQL.isConnected()) {
|
||||
return new SQLStatsStorage(StorageSQL.getConnectionManager());
|
||||
}
|
||||
return new FileStatsStorage();
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import dev.loki.loparkour.api.core.Registry;
|
|||
import dev.loki.loparkour.command.core.LoParkourCommand;
|
||||
import dev.loki.loparkour.config.core.Config;
|
||||
import dev.loki.loparkour.config.locale.Locales;
|
||||
import dev.loki.loparkour.config.options.Option;
|
||||
import dev.loki.loparkour.config.options.section.OptionSQL;
|
||||
import dev.loki.loparkour.duels.DuelsMode;
|
||||
import dev.loki.loparkour.ghost.service.GhostService;
|
||||
import dev.loki.loparkour.hook.holo.HoloHook;
|
||||
|
|
@ -141,7 +141,7 @@ public final class PluginBootstrap {
|
|||
|
||||
private static void setupMetrics(@NotNull LoParkour plugin) {
|
||||
final Metrics metrics = new Metrics(plugin, BSTATS_PLUGIN_ID);
|
||||
metrics.addCustomChart(new SimplePie("using_sql", () -> Boolean.toString(Option.SQL)));
|
||||
metrics.addCustomChart(new SimplePie("using_sql", () -> Boolean.toString(OptionSQL.enabled())));
|
||||
metrics.addCustomChart(new SimplePie("using_rewards", () -> Boolean.toString(Rewards.REWARDS_ENABLED)));
|
||||
metrics.addCustomChart(new SimplePie("locale_count", () -> Integer.toString(Locales.getLocaleCount())));
|
||||
metrics.addCustomChart(new SingleLineChart("player_joins", () ->
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package dev.loki.loparkour.command.schematic.wand;
|
|||
|
||||
import dev.loki.loparkour.command.schematic.SchematicCommandHandler;
|
||||
import dev.loki.loparkour.config.locale.Locales;
|
||||
import dev.loki.loparkour.config.options.Option;
|
||||
import dev.loki.loparkour.config.options.OptionGeneral;
|
||||
import dev.loki.loparkour.menu.core.screen.ParkourOption;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
|
@ -41,7 +41,7 @@ public final class SchematicWand {
|
|||
return cachedWand;
|
||||
}
|
||||
|
||||
String locale = Option.OPTIONS_DEFAULTS.get(ParkourOption.LANG);
|
||||
String locale = OptionGeneral.optionsDefaults().get(ParkourOption.LANG);
|
||||
if (locale == null || locale.isBlank()) {
|
||||
locale = "en";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,14 +79,36 @@ public final class ConfigLoader {
|
|||
}
|
||||
}
|
||||
|
||||
if (Config.GENERATION.isPath("generation.normal.height")) {
|
||||
final double sum = Config.GENERATION.getDouble("generation.normal.height.1")
|
||||
+ Config.GENERATION.getDouble("generation.normal.height.0")
|
||||
+ Config.GENERATION.getDouble("generation.normal.height.-1")
|
||||
+ Config.GENERATION.getDouble("generation.normal.height.-2");
|
||||
if (sum <= 0) {
|
||||
log.severe("Invalid config: generation height chances sum to %.1f, must be > 0".formatted(sum));
|
||||
if (Config.GENERATION.isPath("advanced.height.min") && Config.GENERATION.isPath("advanced.height.max")) {
|
||||
final int heightMax = Config.GENERATION.getInt("advanced.height.max");
|
||||
final int heightMin = Config.GENERATION.getInt("advanced.height.min");
|
||||
if (heightMax < heightMin) {
|
||||
log.severe("Invalid config: advanced.height.max (%d) must be >= advanced.height.min (%d)"
|
||||
.formatted(heightMax, heightMin));
|
||||
}
|
||||
}
|
||||
|
||||
validateWeights(log, "advanced.distance.chances");
|
||||
validateWeights(log, "advanced.height.chances");
|
||||
validateWeights(log, "advanced.type");
|
||||
}
|
||||
|
||||
/**
|
||||
* Block/jump weights are divided by their sum, so a section that adds up to
|
||||
* zero silently produces no blocks at all.
|
||||
*/
|
||||
private static void validateWeights(@NotNull Logger log, @NotNull String section) {
|
||||
if (!Config.GENERATION.isPath(section)) {
|
||||
return;
|
||||
}
|
||||
|
||||
double sum = 0.0;
|
||||
for (final String key : Config.GENERATION.getChildren(section)) {
|
||||
sum += Config.GENERATION.getDouble(section + "." + key);
|
||||
}
|
||||
|
||||
if (sum <= 0.0) {
|
||||
log.severe("Invalid config: %s weights sum to %.1f, must be > 0".formatted(section, sum));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package dev.loki.loparkour.config.locale;
|
||||
|
||||
import dev.loki.loparkour.LoParkour;
|
||||
import dev.loki.loparkour.config.options.Option;
|
||||
import dev.loki.loparkour.config.options.OptionGeneral;
|
||||
import dev.loki.loparkour.menu.core.screen.ParkourOption;
|
||||
import dev.loki.loparkour.player.core.ParkourUser;
|
||||
import dev.loki.loparkour.util.text.ColorUtil;
|
||||
|
|
@ -56,8 +56,8 @@ public final class Locales {
|
|||
if (sender instanceof Player player) {
|
||||
return getString(player, path);
|
||||
}
|
||||
String locale = Option.OPTIONS_DEFAULTS != null
|
||||
? Option.OPTIONS_DEFAULTS.get(ParkourOption.LANG)
|
||||
String locale = OptionGeneral.optionsDefaults() != null
|
||||
? OptionGeneral.optionsDefaults().get(ParkourOption.LANG)
|
||||
: null;
|
||||
if (locale == null || locale.isBlank()) {
|
||||
locale = "en";
|
||||
|
|
@ -170,11 +170,11 @@ public final class Locales {
|
|||
@NotNull
|
||||
private static String getPlayerLocale(@NotNull Player player) {
|
||||
final ParkourUser user = ParkourUser.getUser(player);
|
||||
String loc = user == null ? Option.OPTIONS_DEFAULTS.get(ParkourOption.LANG) : user.locale;
|
||||
String loc = user == null ? OptionGeneral.optionsDefaults().get(ParkourOption.LANG) : user.locale;
|
||||
|
||||
// Fix legacy Boolean "true" values from old config parsing
|
||||
if ("true".equals(loc) || "false".equals(loc)) {
|
||||
loc = Option.OPTIONS_DEFAULTS.get(ParkourOption.LANG);
|
||||
loc = OptionGeneral.optionsDefaults().get(ParkourOption.LANG);
|
||||
if (user != null) {
|
||||
user.locale = loc; // Update user's locale to fixed value
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,37 +2,25 @@ package dev.loki.loparkour.config.options;
|
|||
|
||||
import dev.loki.loparkour.api.core.Registry;
|
||||
import dev.loki.loparkour.config.core.Config;
|
||||
import dev.loki.loparkour.menu.core.screen.ParkourOption;
|
||||
import dev.loki.loparkour.style.core.RandomStyle;
|
||||
import dev.loki.loparkour.style.core.Style;
|
||||
import dev.loki.loparkour.util.particle.ParticleData;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import dev.loki.loparkour.config.options.section.OptionGeneration;
|
||||
import dev.loki.loparkour.config.options.section.OptionParticles;
|
||||
import dev.loki.loparkour.config.options.section.OptionSQL;
|
||||
import dev.loki.loparkour.config.options.section.OptionStyles;
|
||||
import java.util.function.BiFunction;
|
||||
import dev.loki.loparkour.style.core.RandomStyle;
|
||||
|
||||
/**
|
||||
* Facade for all config-derived constants.
|
||||
* Delegates to specialized option classes in config.options package.
|
||||
* Reload entry point for the option sections.
|
||||
*
|
||||
* <p>Each section owns its values and exposes them through accessors
|
||||
* ({@link OptionSQL}, {@link OptionParticles}, {@link OptionGeneration},
|
||||
* {@link OptionGeneral}); this class does not mirror them.</p>
|
||||
*/
|
||||
public final class Option {
|
||||
|
||||
private Option() {
|
||||
}
|
||||
|
||||
// ── Initialization ────────────────────────────────────────────────────────
|
||||
|
||||
/** (Re)read every option section and re-register the configured styles. */
|
||||
public static void init(boolean firstLoad) {
|
||||
OptionSQL.init();
|
||||
OptionParticles.init();
|
||||
|
|
@ -40,129 +28,7 @@ public final class Option {
|
|||
OptionGeneral.init(firstLoad);
|
||||
OptionGeneral.initOptions();
|
||||
|
||||
// Sync all fields to Option facade
|
||||
syncFields();
|
||||
|
||||
OptionStyles.initStyles("styles.list", Config.CONFIG.fileConfiguration, RandomStyle::new)
|
||||
.forEach(Registry::register);
|
||||
}
|
||||
|
||||
// ── Direct field re-exports for backward compatibility ───────────────────
|
||||
|
||||
// SQL
|
||||
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;
|
||||
|
||||
// Particles
|
||||
public static 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;
|
||||
|
||||
// Generation
|
||||
public static double TYPE_NORMAL;
|
||||
public static double TYPE_SPECIAL;
|
||||
public static double TYPE_SCHEMATICS;
|
||||
public static double SPECIAL_ICE;
|
||||
public static double SPECIAL_SLAB;
|
||||
public static double SPECIAL_PANE;
|
||||
public static double SPECIAL_FENCE;
|
||||
public static double NORMAL_DISTANCE_1;
|
||||
public static double NORMAL_DISTANCE_2;
|
||||
public static double NORMAL_DISTANCE_3;
|
||||
public static double NORMAL_DISTANCE_4;
|
||||
public static double NORMAL_HEIGHT_1;
|
||||
public static double NORMAL_HEIGHT_0;
|
||||
public static double NORMAL_HEIGHT_NEG1;
|
||||
public static double NORMAL_HEIGHT_NEG2;
|
||||
public static int MAX_Y;
|
||||
public static int MIN_Y;
|
||||
public static int BLOCK_CLEANUP_DISTANCE;
|
||||
public static int CLEANUP_INTERVAL;
|
||||
public static int TRAIL_KEEP_BEHIND;
|
||||
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;
|
||||
|
||||
// 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;
|
||||
|
||||
private static void syncFields() {
|
||||
// SQL
|
||||
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;
|
||||
|
||||
// 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;
|
||||
|
||||
// Generation
|
||||
TYPE_NORMAL = OptionGeneration.TYPE_NORMAL;
|
||||
TYPE_SPECIAL = OptionGeneration.TYPE_SPECIAL;
|
||||
TYPE_SCHEMATICS = OptionGeneration.TYPE_SCHEMATICS;
|
||||
SPECIAL_ICE = OptionGeneration.SPECIAL_ICE;
|
||||
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;
|
||||
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;
|
||||
|
||||
// General
|
||||
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;
|
||||
}
|
||||
|
||||
/** @deprecated Use {@link OptionStyles#initStyles(String, FileConfiguration, BiFunction)} */
|
||||
@Deprecated
|
||||
public static Set<Style> initStyles(String path, FileConfiguration config,
|
||||
BiFunction<String, List<Material>, Style> fn) {
|
||||
return OptionStyles.initStyles(path, config, fn);
|
||||
}
|
||||
|
||||
// ── Inner types ───────────────────────────────────────────────────────────
|
||||
|
||||
public enum ParticleShape { DOT, CIRCLE, BOX }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import org.bukkit.block.BlockFace;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -27,13 +28,12 @@ public final class OptionGeneral {
|
|||
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;
|
||||
private static double borderSize;
|
||||
private static List<Integer> possibleLeads;
|
||||
private static BlockFace heading;
|
||||
private static Location goBackLocation;
|
||||
private static Map<ParkourOption, Boolean> optionsEnabled;
|
||||
private static Map<ParkourOption, String> optionsDefaults;
|
||||
|
||||
public static void init(boolean firstLoad) {
|
||||
initGoBackLocation();
|
||||
|
|
@ -41,7 +41,7 @@ public final class OptionGeneral {
|
|||
initHeading();
|
||||
|
||||
if (firstLoad) {
|
||||
BORDER_SIZE = Config.GENERATION.getDouble("advanced.border-size");
|
||||
borderSize = Config.GENERATION.getDouble("advanced.border-size");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -50,17 +50,45 @@ public final class OptionGeneral {
|
|||
options.remove(ParkourOption.JOIN);
|
||||
options.remove(ParkourOption.ADMIN);
|
||||
|
||||
OPTIONS_DEFAULTS = new HashMap<>();
|
||||
OPTIONS_ENABLED = new HashMap<>();
|
||||
optionsDefaults = new HashMap<>();
|
||||
optionsEnabled = new HashMap<>();
|
||||
|
||||
for (final ParkourOption option : options) {
|
||||
applyOption(option);
|
||||
}
|
||||
}
|
||||
|
||||
public static double borderSize() {
|
||||
return borderSize;
|
||||
}
|
||||
|
||||
/** Read-only view; the live list is pruned on reload by {@link #initLeads()}. */
|
||||
public static List<Integer> possibleLeads() {
|
||||
return possibleLeads == null ? null : Collections.unmodifiableList(possibleLeads);
|
||||
}
|
||||
|
||||
public static BlockFace heading() {
|
||||
return heading;
|
||||
}
|
||||
|
||||
/** Copy of the configured location, so callers cannot mutate the stored one. */
|
||||
public static Location goBackLocation() {
|
||||
return goBackLocation == null ? null : goBackLocation.clone();
|
||||
}
|
||||
|
||||
/** Read-only view of the option switches. */
|
||||
public static Map<ParkourOption, Boolean> optionsEnabled() {
|
||||
return optionsEnabled == null ? null : Collections.unmodifiableMap(optionsEnabled);
|
||||
}
|
||||
|
||||
/** Read-only view of the option defaults. */
|
||||
public static Map<ParkourOption, String> optionsDefaults() {
|
||||
return optionsDefaults == null ? null : Collections.unmodifiableMap(optionsDefaults);
|
||||
}
|
||||
|
||||
private static void applyOption(ParkourOption option) {
|
||||
final String parent = "default-values." + option.path;
|
||||
OPTIONS_ENABLED.put(option, Config.CONFIG.getBoolean(parent + ".enabled"));
|
||||
optionsEnabled.put(option, Config.CONFIG.getBoolean(parent + ".enabled"));
|
||||
|
||||
final String defaultPath = parent + ".default";
|
||||
if (Config.CONFIG.isPath(defaultPath)) {
|
||||
|
|
@ -88,7 +116,7 @@ public final class OptionGeneral {
|
|||
}
|
||||
|
||||
if (value != null && !value.isEmpty()) {
|
||||
OPTIONS_DEFAULTS.put(option, value);
|
||||
optionsDefaults.put(option, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -101,14 +129,14 @@ public final class OptionGeneral {
|
|||
}
|
||||
|
||||
private static void initGoBackLocation() {
|
||||
GO_BACK_LOC = parseLocation(Config.CONFIG.getString("bungeecord.go-back"));
|
||||
goBackLocation = 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()));
|
||||
goBackLocation.setPitch(Float.parseFloat(axes[0].trim()));
|
||||
goBackLocation.setYaw(Float.parseFloat(axes[1].trim()));
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
|
|
@ -117,25 +145,25 @@ public final class OptionGeneral {
|
|||
}
|
||||
|
||||
private static void initLeads() {
|
||||
POSSIBLE_LEADS = Config.CONFIG.getIntList("options.leads.amount");
|
||||
for (final int lead : new ArrayList<>(POSSIBLE_LEADS)) {
|
||||
possibleLeads = Config.CONFIG.getIntList("options.leads.amount");
|
||||
for (final int lead : new ArrayList<>(possibleLeads)) {
|
||||
if (lead < 1 || lead > MAX_LEAD) {
|
||||
LoParkour.getPlugin().getLogger().severe(
|
||||
"Invalid lead: %d. Must be 1–128.".formatted(lead));
|
||||
POSSIBLE_LEADS.remove((Object) lead);
|
||||
possibleLeads.remove((Object) lead);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void initHeading() {
|
||||
final String heading = Config.GENERATION.getString("advanced.island.parkour.heading");
|
||||
HEADING = switch (heading.toLowerCase()) {
|
||||
final String headingName = Config.GENERATION.getString("advanced.island.parkour.heading");
|
||||
heading = switch (headingName.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);
|
||||
LoParkour.getPlugin().getLogger().severe("Invalid heading: " + headingName);
|
||||
yield BlockFace.NORTH;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
package dev.loki.loparkour.config.options;
|
||||
|
||||
/**
|
||||
* Shape used when spawning trail particles.
|
||||
* Loaded from {@code particles.particle-shape} (see {@code OptionParticles}).
|
||||
*/
|
||||
public enum ParticleShape {
|
||||
|
||||
DOT,
|
||||
CIRCLE,
|
||||
BOX
|
||||
|
||||
}
|
||||
|
|
@ -4,110 +4,121 @@ import dev.loki.loparkour.LoParkour;
|
|||
import dev.loki.loparkour.config.core.Config;
|
||||
|
||||
/**
|
||||
* Generation-related configuration options (validation, memory).
|
||||
* Generation-related configuration options (bounds, memory, jump validation).
|
||||
*
|
||||
* <p>Block-type weights are not read here — they live in
|
||||
* {@code GeneratorProfileManager} / {@code GenerationProfileLoader}, which resolve
|
||||
* the {@code advanced.*} paths (see TODO: {@code generation.type|normal|special}
|
||||
* in generation.yml is currently ignored).</p>
|
||||
*/
|
||||
public final class OptionGeneration {
|
||||
|
||||
private static final double DEFAULT_MAX_JUMP_DISTANCE = 5.0;
|
||||
private static final double DEFAULT_MAX_HORIZONTAL_DISTANCE = 4.0;
|
||||
private static final double DEFAULT_MAX_VERTICAL_UP = 1.0;
|
||||
private static final double DEFAULT_MAX_VERTICAL_DOWN = 3.0;
|
||||
private static final int DEFAULT_BLOCK_CLEANUP_DISTANCE = 100;
|
||||
private static final int DEFAULT_CLEANUP_INTERVAL = 100;
|
||||
private static final int DEFAULT_TRAIL_KEEP_BEHIND = 10;
|
||||
private static final double PERCENT_DIVISOR = 100.0;
|
||||
private static final int DEFAULT_MIN_Y = 100;
|
||||
private static final int DEFAULT_MAX_Y = 200;
|
||||
|
||||
private OptionGeneration() {
|
||||
}
|
||||
|
||||
// ── Block generation probabilities ────────────────────────────────────────
|
||||
public static double TYPE_NORMAL;
|
||||
public static double TYPE_SPECIAL;
|
||||
public static double TYPE_SCHEMATICS;
|
||||
public static double SPECIAL_ICE;
|
||||
public static double SPECIAL_SLAB;
|
||||
public static double SPECIAL_PANE;
|
||||
public static double SPECIAL_FENCE;
|
||||
public static double NORMAL_DISTANCE_1;
|
||||
public static double NORMAL_DISTANCE_2;
|
||||
public static double NORMAL_DISTANCE_3;
|
||||
public static double NORMAL_DISTANCE_4;
|
||||
public static double NORMAL_HEIGHT_1;
|
||||
public static double NORMAL_HEIGHT_0;
|
||||
public static double NORMAL_HEIGHT_NEG1;
|
||||
public static double NORMAL_HEIGHT_NEG2;
|
||||
public static int MAX_Y;
|
||||
public static int MIN_Y;
|
||||
// ── World bounds ───────────────────────────────────────────────────────────
|
||||
private static int maxY;
|
||||
private static int minY;
|
||||
|
||||
// ── Memory / cleanup ──────────────────────────────────────────────────────
|
||||
public static int BLOCK_CLEANUP_DISTANCE;
|
||||
public static int CLEANUP_INTERVAL;
|
||||
public static int TRAIL_KEEP_BEHIND;
|
||||
// ── Memory / cleanup ───────────────────────────────────────────────────────
|
||||
private static int blockCleanupDistance;
|
||||
private static int cleanupInterval;
|
||||
private static int trailKeepBehind;
|
||||
|
||||
// ── 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 validation ────────────────────────────────────────────────────────
|
||||
private static boolean jumpValidationEnabled;
|
||||
private static double maxJumpDistance;
|
||||
private static double maxHorizontalDistance;
|
||||
private static double maxVerticalUp;
|
||||
private static double maxVerticalDown;
|
||||
|
||||
public static void init() {
|
||||
initBounds();
|
||||
initJumpValidation();
|
||||
initMemory();
|
||||
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") : DEFAULT_MAX_JUMP_DISTANCE;
|
||||
MAX_HORIZONTAL_DISTANCE = Config.CONFIG.isPath("jump-validation.max-horizontal")
|
||||
? Config.CONFIG.getDouble("jump-validation.max-horizontal") : DEFAULT_MAX_HORIZONTAL_DISTANCE;
|
||||
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") : DEFAULT_MAX_VERTICAL_DOWN;
|
||||
}
|
||||
private static void initBounds() {
|
||||
maxY = Config.GENERATION.getInt("generation.settings.max-y");
|
||||
minY = Config.GENERATION.getInt("generation.settings.min-y");
|
||||
|
||||
private static void initMemory() {
|
||||
BLOCK_CLEANUP_DISTANCE = Config.CONFIG.isPath("memory.block-cleanup-distance")
|
||||
? Config.CONFIG.getInt("memory.block-cleanup-distance") : DEFAULT_BLOCK_CLEANUP_DISTANCE;
|
||||
CLEANUP_INTERVAL = Config.CONFIG.isPath("memory.cleanup-interval")
|
||||
? Config.CONFIG.getInt("memory.cleanup-interval") : DEFAULT_CLEANUP_INTERVAL;
|
||||
TRAIL_KEEP_BEHIND = Config.CONFIG.isPath("memory.trail-keep-behind")
|
||||
? Config.CONFIG.getInt("memory.trail-keep-behind") : DEFAULT_TRAIL_KEEP_BEHIND;
|
||||
}
|
||||
|
||||
private static void initGenerationProbabilities() {
|
||||
TYPE_NORMAL = Config.GENERATION.getInt("generation.type.normal") / PERCENT_DIVISOR;
|
||||
TYPE_SPECIAL = Config.GENERATION.getInt("generation.type.special") / PERCENT_DIVISOR;
|
||||
TYPE_SCHEMATICS = Config.GENERATION.getInt("generation.type.schematic") / PERCENT_DIVISOR;
|
||||
|
||||
SPECIAL_ICE = Config.GENERATION.getInt("generation.special.ice") / PERCENT_DIVISOR;
|
||||
SPECIAL_SLAB = Config.GENERATION.getInt("generation.special.slab") / PERCENT_DIVISOR;
|
||||
SPECIAL_PANE = Config.GENERATION.getInt("generation.special.pane") / PERCENT_DIVISOR;
|
||||
SPECIAL_FENCE = Config.GENERATION.getInt("generation.special.fence") / PERCENT_DIVISOR;
|
||||
|
||||
NORMAL_DISTANCE_1 = Config.GENERATION.getInt("generation.normal.distance.1") / PERCENT_DIVISOR;
|
||||
NORMAL_DISTANCE_2 = Config.GENERATION.getInt("generation.normal.distance.2") / PERCENT_DIVISOR;
|
||||
NORMAL_DISTANCE_3 = Config.GENERATION.getInt("generation.normal.distance.3") / PERCENT_DIVISOR;
|
||||
NORMAL_DISTANCE_4 = Config.GENERATION.getInt("generation.normal.distance.4") / PERCENT_DIVISOR;
|
||||
|
||||
NORMAL_HEIGHT_1 = Config.GENERATION.getInt("generation.normal.height.1") / PERCENT_DIVISOR;
|
||||
NORMAL_HEIGHT_0 = Config.GENERATION.getInt("generation.normal.height.0") / PERCENT_DIVISOR;
|
||||
NORMAL_HEIGHT_NEG1 = Config.GENERATION.getInt("generation.normal.height.-1") / PERCENT_DIVISOR;
|
||||
NORMAL_HEIGHT_NEG2 = Config.GENERATION.getInt("generation.normal.height.-2") / PERCENT_DIVISOR;
|
||||
|
||||
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 = DEFAULT_MIN_Y;
|
||||
MAX_Y = DEFAULT_MAX_Y;
|
||||
if (minY >= maxY) {
|
||||
minY = DEFAULT_MIN_Y;
|
||||
maxY = DEFAULT_MAX_Y;
|
||||
LoParkour.getPlugin().getLogger().severe(
|
||||
"min-y >= max-y in generation.yml — using defaults 100/200.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void initJumpValidation() {
|
||||
jumpValidationEnabled = Config.CONFIG.isPath("jump-validation.enabled")
|
||||
&& Config.CONFIG.getBoolean("jump-validation.enabled");
|
||||
maxJumpDistance = Config.CONFIG.isPath("jump-validation.max-distance")
|
||||
? Config.CONFIG.getDouble("jump-validation.max-distance") : DEFAULT_MAX_JUMP_DISTANCE;
|
||||
maxHorizontalDistance = Config.CONFIG.isPath("jump-validation.max-horizontal")
|
||||
? Config.CONFIG.getDouble("jump-validation.max-horizontal") : DEFAULT_MAX_HORIZONTAL_DISTANCE;
|
||||
maxVerticalUp = Config.CONFIG.isPath("jump-validation.max-vertical-up")
|
||||
? Config.CONFIG.getDouble("jump-validation.max-vertical-up") : DEFAULT_MAX_VERTICAL_UP;
|
||||
maxVerticalDown = Config.CONFIG.isPath("jump-validation.max-vertical-down")
|
||||
? Config.CONFIG.getDouble("jump-validation.max-vertical-down") : DEFAULT_MAX_VERTICAL_DOWN;
|
||||
}
|
||||
|
||||
private static void initMemory() {
|
||||
blockCleanupDistance = Config.CONFIG.isPath("memory.block-cleanup-distance")
|
||||
? Config.CONFIG.getInt("memory.block-cleanup-distance") : DEFAULT_BLOCK_CLEANUP_DISTANCE;
|
||||
cleanupInterval = Config.CONFIG.isPath("memory.cleanup-interval")
|
||||
? Config.CONFIG.getInt("memory.cleanup-interval") : DEFAULT_CLEANUP_INTERVAL;
|
||||
trailKeepBehind = Config.CONFIG.isPath("memory.trail-keep-behind")
|
||||
? Config.CONFIG.getInt("memory.trail-keep-behind") : DEFAULT_TRAIL_KEEP_BEHIND;
|
||||
}
|
||||
|
||||
public static int maxY() {
|
||||
return maxY;
|
||||
}
|
||||
|
||||
public static int minY() {
|
||||
return minY;
|
||||
}
|
||||
|
||||
public static int blockCleanupDistance() {
|
||||
return blockCleanupDistance;
|
||||
}
|
||||
|
||||
public static int cleanupInterval() {
|
||||
return cleanupInterval;
|
||||
}
|
||||
|
||||
public static int trailKeepBehind() {
|
||||
return trailKeepBehind;
|
||||
}
|
||||
|
||||
public static boolean jumpValidationEnabled() {
|
||||
return jumpValidationEnabled;
|
||||
}
|
||||
|
||||
public static double maxJumpDistance() {
|
||||
return maxJumpDistance;
|
||||
}
|
||||
|
||||
public static double maxHorizontalDistance() {
|
||||
return maxHorizontalDistance;
|
||||
}
|
||||
|
||||
public static double maxVerticalUp() {
|
||||
return maxVerticalUp;
|
||||
}
|
||||
|
||||
public static double maxVerticalDown() {
|
||||
return maxVerticalDown;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package dev.loki.loparkour.config.options.section;
|
|||
|
||||
import dev.loki.loparkour.LoParkour;
|
||||
import dev.loki.loparkour.config.core.Config;
|
||||
import dev.loki.loparkour.config.options.Option;
|
||||
import dev.loki.loparkour.config.options.ParticleShape;
|
||||
import dev.loki.loparkour.util.particle.ParticleData;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
|
|
@ -17,21 +17,45 @@ public final class OptionParticles {
|
|||
private 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;
|
||||
private static ParticleShape shape;
|
||||
private static Sound soundType;
|
||||
private static int soundPitch;
|
||||
private static int soundVolume;
|
||||
private static Particle particleType;
|
||||
private static ParticleData<?> particleData;
|
||||
|
||||
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"));
|
||||
soundType = resolveSound(Config.CONFIG.getString("particles.sound-type"));
|
||||
particleType = resolveParticle(Config.CONFIG.getString("particles.particle-type"));
|
||||
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, PARTICLE_SIZE);
|
||||
soundPitch = Config.CONFIG.getInt("particles.sound-pitch");
|
||||
soundVolume = Config.CONFIG.getInt("particles.sound-volume");
|
||||
particleData = new ParticleData<>(particleType, null, PARTICLE_SIZE);
|
||||
}
|
||||
|
||||
public static ParticleShape shape() {
|
||||
return shape;
|
||||
}
|
||||
|
||||
public static Sound soundType() {
|
||||
return soundType;
|
||||
}
|
||||
|
||||
public static int soundPitch() {
|
||||
return soundPitch;
|
||||
}
|
||||
|
||||
public static int soundVolume() {
|
||||
return soundVolume;
|
||||
}
|
||||
|
||||
public static Particle particleType() {
|
||||
return particleType;
|
||||
}
|
||||
|
||||
public static ParticleData<?> particleData() {
|
||||
return particleData;
|
||||
}
|
||||
|
||||
private static Sound resolveSound(String name) {
|
||||
|
|
@ -68,13 +92,13 @@ public final class OptionParticles {
|
|||
return Particle.values()[0];
|
||||
}
|
||||
|
||||
private static Option.ParticleShape resolveShape(String name) {
|
||||
private static ParticleShape resolveShape(String name) {
|
||||
if (name != null && !name.isEmpty()) {
|
||||
try {
|
||||
return Option.ParticleShape.valueOf(name.toUpperCase());
|
||||
return ParticleShape.valueOf(name.toUpperCase());
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
}
|
||||
}
|
||||
return Option.ParticleShape.BOX;
|
||||
return ParticleShape.BOX;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,27 +10,61 @@ public final class OptionSQL {
|
|||
private 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;
|
||||
private static boolean sql;
|
||||
private static String url;
|
||||
private static int port;
|
||||
private static String database;
|
||||
private static String username;
|
||||
private static String password;
|
||||
private static String 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");
|
||||
sql = Config.CONFIG.getBoolean("sql.enabled");
|
||||
port = Config.CONFIG.getInt("sql.port");
|
||||
database = Config.CONFIG.getString("sql.database");
|
||||
url = Config.CONFIG.getString("sql.url");
|
||||
username = Config.CONFIG.getString("sql.username");
|
||||
|
||||
// Environment variable override for password
|
||||
final String envPassword = System.getenv("LOPARKOUR_SQL_PASSWORD");
|
||||
SQL_PASSWORD = (envPassword != null && !envPassword.isEmpty())
|
||||
password = (envPassword != null && !envPassword.isEmpty())
|
||||
? envPassword
|
||||
: Config.CONFIG.getString("sql.password");
|
||||
|
||||
SQL_PREFIX = Config.CONFIG.getString("sql.prefix");
|
||||
prefix = Config.CONFIG.getString("sql.prefix");
|
||||
}
|
||||
|
||||
/** Whether SQL storage is active; turned off when the connection cannot be used. */
|
||||
public static boolean enabled() {
|
||||
return sql;
|
||||
}
|
||||
|
||||
/** Turns SQL off for this session (local storage takes over). */
|
||||
public static void disable() {
|
||||
sql = false;
|
||||
}
|
||||
|
||||
public static String url() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public static int port() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public static String database() {
|
||||
return database;
|
||||
}
|
||||
|
||||
public static String username() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public static String password() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public static String prefix() {
|
||||
return prefix;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package dev.loki.loparkour.duels;
|
|||
import dev.loki.loparkour.LoParkour;
|
||||
import dev.loki.loparkour.config.core.Config;
|
||||
import dev.loki.loparkour.config.locale.Locales;
|
||||
import dev.loki.loparkour.config.options.Option;
|
||||
import dev.loki.loparkour.config.options.OptionGeneral;
|
||||
import dev.loki.loparkour.generator.core.coordinator.ParkourGenerator;
|
||||
import dev.loki.loparkour.mode.base.Mode;
|
||||
import dev.loki.loparkour.mode.base.Modes;
|
||||
|
|
@ -78,7 +78,7 @@ public class DuelsGenerator extends ParkourGenerator {
|
|||
gen.owningGenerator = this;
|
||||
gen.setOwnedPlayer(pp);
|
||||
gen.setPlayerIndex(playerGenerators.size());
|
||||
gen.state.heading = Option.HEADING.getDirection();
|
||||
gen.state.heading = OptionGeneral.heading().getDirection();
|
||||
final Location spawnBase = session.getSpawnLocation();
|
||||
if (spawnBase == null || spawnBase.getWorld() == null) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package dev.loki.loparkour.generator.core.model;
|
|||
|
||||
import dev.loki.loparkour.LoParkour;
|
||||
import dev.loki.loparkour.config.core.Config;
|
||||
import dev.loki.loparkour.config.options.Option;
|
||||
import dev.loki.loparkour.config.options.OptionGeneral;
|
||||
import dev.loki.loparkour.session.core.Session;
|
||||
import dev.loki.loparkour.util.item.Materials;
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ public final class Island {
|
|||
final int cy = location.getBlockY();
|
||||
final int cz = location.getBlockZ();
|
||||
|
||||
final BlockFace face = Option.HEADING;
|
||||
final BlockFace face = OptionGeneral.heading();
|
||||
final int hx = face.getModX();
|
||||
final int hz = face.getModZ();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package dev.loki.loparkour.generator.jump.calculation;
|
||||
|
||||
import dev.loki.loparkour.config.options.Option;
|
||||
import dev.loki.loparkour.config.options.section.OptionGeneration;
|
||||
import dev.loki.loparkour.util.misc.MaterialUtil;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.util.Vector;
|
||||
|
|
@ -24,10 +24,10 @@ public class JumpValidator {
|
|||
|
||||
public JumpValidator() {
|
||||
this(
|
||||
Option.JUMP_VALIDATION_ENABLED ? Option.MAX_JUMP_DISTANCE : MAX_JUMP_DISTANCE,
|
||||
Option.JUMP_VALIDATION_ENABLED ? Option.MAX_HORIZONTAL_DISTANCE : MAX_HORIZONTAL_DISTANCE,
|
||||
Option.JUMP_VALIDATION_ENABLED ? Option.MAX_VERTICAL_UP : MAX_VERTICAL_UP,
|
||||
Option.JUMP_VALIDATION_ENABLED ? Option.MAX_VERTICAL_DOWN : MAX_VERTICAL_DOWN
|
||||
OptionGeneration.jumpValidationEnabled() ? OptionGeneration.maxJumpDistance() : MAX_JUMP_DISTANCE,
|
||||
OptionGeneration.jumpValidationEnabled() ? OptionGeneration.maxHorizontalDistance() : MAX_HORIZONTAL_DISTANCE,
|
||||
OptionGeneration.jumpValidationEnabled() ? OptionGeneration.maxVerticalUp() : MAX_VERTICAL_UP,
|
||||
OptionGeneration.jumpValidationEnabled() ? OptionGeneration.maxVerticalDown() : MAX_VERTICAL_DOWN
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package dev.loki.loparkour.generator.lifecycle.loop;
|
||||
|
||||
import dev.loki.loparkour.config.options.Option;
|
||||
import dev.loki.loparkour.config.options.section.OptionGeneration;
|
||||
import dev.loki.loparkour.generator.core.coordinator.ParkourGenerator;
|
||||
import dev.loki.loparkour.generator.lifecycle.player.GeneratorCleanup;
|
||||
import org.bukkit.block.Block;
|
||||
|
|
@ -50,7 +50,7 @@ public class LifecycleTickManager {
|
|||
// Check if players fell below threshold
|
||||
checkPlayerFall();
|
||||
|
||||
if (tickCounter % Option.CLEANUP_INTERVAL == 0) {
|
||||
if (tickCounter % OptionGeneration.cleanupInterval() == 0) {
|
||||
cleanup.cleanupDistantBlocks();
|
||||
}
|
||||
if (tickCounter % TIME_UI_INTERVAL == 0) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package dev.loki.loparkour.generator.lifecycle.player;
|
||||
|
||||
import dev.loki.loparkour.config.options.Option;
|
||||
import dev.loki.loparkour.config.options.OptionGeneral;
|
||||
import dev.loki.loparkour.config.options.section.OptionGeneration;
|
||||
import dev.loki.loparkour.generator.core.coordinator.ParkourGenerator;
|
||||
import dev.loki.loparkour.player.core.ParkourPlayer;
|
||||
import org.bukkit.Location;
|
||||
|
|
@ -41,7 +42,7 @@ public class GeneratorCleanup {
|
|||
return;
|
||||
}
|
||||
|
||||
final int keepBehind = Math.max(0, Option.TRAIL_KEEP_BEHIND);
|
||||
final int keepBehind = Math.max(0, OptionGeneration.trailKeepBehind());
|
||||
final int removeCount = minStandingIndex - keepBehind;
|
||||
if (removeCount <= 0) {
|
||||
return;
|
||||
|
|
@ -164,7 +165,7 @@ public class GeneratorCleanup {
|
|||
|
||||
private static void applyHeading(@NotNull Location blockSpawn) {
|
||||
// Move block forward based on heading (6 blocks forward, same height)
|
||||
switch (Option.HEADING) {
|
||||
switch (OptionGeneral.heading()) {
|
||||
case NORTH -> blockSpawn.add(0, 0, -FIRST_BLOCK_OFFSET);
|
||||
case SOUTH -> blockSpawn.add(0, 0, FIRST_BLOCK_OFFSET);
|
||||
case WEST -> blockSpawn.add(-FIRST_BLOCK_OFFSET, 0, 0);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package dev.loki.loparkour.listener.gameplay;
|
|||
|
||||
import dev.loki.loparkour.config.core.Config;
|
||||
import dev.loki.loparkour.config.locale.Locales;
|
||||
import dev.loki.loparkour.config.options.Option;
|
||||
import dev.loki.loparkour.config.options.OptionGeneral;
|
||||
import dev.loki.loparkour.menu.core.Menus;
|
||||
import dev.loki.loparkour.menu.core.screen.ParkourOption;
|
||||
import dev.loki.loparkour.player.core.ParkourPlayer;
|
||||
|
|
@ -34,7 +34,7 @@ public class ParkourRestrictionListener implements Listener {
|
|||
|
||||
@EventHandler
|
||||
public void onChat(AsyncPlayerChatEvent event) {
|
||||
if (!Option.OPTIONS_ENABLED.get(ParkourOption.CHAT)) {
|
||||
if (!OptionGeneral.optionsEnabled().getOrDefault(ParkourOption.CHAT, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package dev.loki.loparkour.menu.core;
|
||||
|
||||
import dev.loki.loparkour.config.locale.Locales;
|
||||
import dev.loki.loparkour.config.options.Option;
|
||||
import dev.loki.loparkour.config.options.OptionGeneral;
|
||||
import dev.loki.loparkour.util.text.ColorUtil;
|
||||
import dev.loki.loparkour.menu.gui.inventory.InventoryGui;
|
||||
import org.bukkit.Material;
|
||||
|
|
@ -26,7 +26,7 @@ public abstract class LPMenu {
|
|||
|
||||
protected String locale(@NotNull Player player) {
|
||||
final var user = dev.loki.loparkour.player.core.ParkourUser.getUser(player);
|
||||
final String loc = user != null ? user.locale : Option.OPTIONS_DEFAULTS.get(ParkourOption.LANG);
|
||||
final String loc = user != null ? user.locale : OptionGeneral.optionsDefaults().get(ParkourOption.LANG);
|
||||
return (loc != null && !loc.isBlank()) ? loc : "en";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package dev.loki.loparkour.menu.core.screen;
|
||||
|
||||
import dev.loki.loparkour.config.core.Config;
|
||||
import dev.loki.loparkour.config.options.Option;
|
||||
import dev.loki.loparkour.config.options.OptionGeneral;
|
||||
import org.bukkit.permissions.Permissible;
|
||||
|
||||
/**
|
||||
|
|
@ -69,7 +69,7 @@ public enum ParkourOption {
|
|||
* @return True if the player is allowed to view/perform this option, false if not.
|
||||
*/
|
||||
public boolean mayPerform(Permissible permissible) {
|
||||
final boolean value = Option.OPTIONS_ENABLED.getOrDefault(this, true);
|
||||
final boolean value = OptionGeneral.optionsEnabled().getOrDefault(this, true);
|
||||
|
||||
if (value) {
|
||||
if (Config.CONFIG.getBoolean("permissions.enabled")) {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
package dev.loki.loparkour.player.core;
|
||||
|
||||
import dev.loki.loparkour.config.options.OptionGeneral;
|
||||
import dev.loki.loparkour.player.service.UserRegistry;
|
||||
import dev.loki.loparkour.player.service.ui.ScoreboardManager;
|
||||
|
||||
import dev.loki.loparkour.config.locale.Locales;
|
||||
import dev.loki.loparkour.config.options.Option;
|
||||
import dev.loki.loparkour.generator.core.coordinator.ParkourGenerator;
|
||||
import dev.loki.loparkour.hook.floodgate.FloodgateHook;
|
||||
import dev.loki.loparkour.menu.core.screen.ParkourOption;
|
||||
|
|
@ -62,7 +62,7 @@ public abstract class ParkourUser {
|
|||
|
||||
// ─── Fields ───────────────────────────────────────────────────────────────
|
||||
|
||||
@NotNull public String locale = Option.OPTIONS_DEFAULTS.get(ParkourOption.LANG);
|
||||
@NotNull public String locale = OptionGeneral.optionsDefaults().get(ParkourOption.LANG);
|
||||
@Nullable public Scoreboard board;
|
||||
@NotNull public PreviousData previousData;
|
||||
public Session.ChatType chatType = Session.ChatType.PUBLIC;
|
||||
|
|
@ -80,7 +80,7 @@ public abstract class ParkourUser {
|
|||
this.joined = Instant.now();
|
||||
this.previousData = previousData == null ? new PreviousData(player) : previousData;
|
||||
|
||||
if (Boolean.parseBoolean(Option.OPTIONS_DEFAULTS.get(ParkourOption.SCOREBOARD))) {
|
||||
if (Boolean.parseBoolean(OptionGeneral.optionsDefaults().get(ParkourOption.SCOREBOARD))) {
|
||||
this.board = Bukkit.getScoreboardManager().getNewScoreboard();
|
||||
this.scoreboardManager = new ScoreboardManager(player, player.getUniqueId(), board, locale);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package dev.loki.loparkour.player.data;
|
|||
|
||||
import dev.loki.loparkour.LoParkour;
|
||||
import dev.loki.loparkour.config.core.Config;
|
||||
import dev.loki.loparkour.config.options.Option;
|
||||
import dev.loki.loparkour.config.options.OptionGeneral;
|
||||
import dev.loki.loparkour.reward.core.Reward;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.GameMode;
|
||||
|
|
@ -56,7 +56,7 @@ public class PreviousData {
|
|||
}
|
||||
|
||||
public void apply(Player player, boolean urgent) {
|
||||
final var to = Config.CONFIG.getBoolean("bungeecord.go-back-enabled") ? Option.GO_BACK_LOC : location;
|
||||
final var to = Config.CONFIG.getBoolean("bungeecord.go-back-enabled") ? OptionGeneral.goBackLocation() : location;
|
||||
|
||||
if (!urgent) {
|
||||
PaperLib.teleportAsync(player, to).thenRun(() -> apply(player));
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
package dev.loki.loparkour.player.service;
|
||||
|
||||
import dev.loki.loparkour.config.options.OptionGeneral;
|
||||
import dev.loki.loparkour.player.core.ParkourPlayer;
|
||||
|
||||
import dev.loki.loparkour.config.options.Option;
|
||||
import dev.loki.loparkour.menu.core.screen.ParkourOption;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -45,7 +45,7 @@ public final class PlayerSettingsManager {
|
|||
// Sanitize legacy Boolean values from old config parsing
|
||||
String sanitized = v;
|
||||
if ("true".equals(v) || "false".equals(v)) {
|
||||
sanitized = Option.OPTIONS_DEFAULTS.getOrDefault(ParkourOption.LANG, "en");
|
||||
sanitized = OptionGeneral.optionsDefaults().getOrDefault(ParkourOption.LANG, "en");
|
||||
}
|
||||
p.locale = sanitized;
|
||||
}));
|
||||
|
|
@ -68,8 +68,8 @@ public final class PlayerSettingsManager {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (value == null || !Option.OPTIONS_ENABLED.getOrDefault(container.option, true)) {
|
||||
final String defaultValue = Option.OPTIONS_DEFAULTS.getOrDefault(container.option, "");
|
||||
if (value == null || !OptionGeneral.optionsEnabled().getOrDefault(container.option, true)) {
|
||||
final String defaultValue = OptionGeneral.optionsDefaults().getOrDefault(container.option, "");
|
||||
container.consumer.accept(player, defaultValue);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -83,15 +83,15 @@ public final class PlayerSettingsManager {
|
|||
}
|
||||
|
||||
private static int defaultBlockLead() {
|
||||
return parseIntSafe(Option.OPTIONS_DEFAULTS.getOrDefault(ParkourOption.LEADS, "1"), 1);
|
||||
return parseIntSafe(OptionGeneral.optionsDefaults().getOrDefault(ParkourOption.LEADS, "1"), 1);
|
||||
}
|
||||
|
||||
private static int defaultSelectedTime() {
|
||||
return parseIntSafe(Option.OPTIONS_DEFAULTS.getOrDefault(ParkourOption.TIME, "6000"), DEFAULT_SELECTED_TIME);
|
||||
return parseIntSafe(OptionGeneral.optionsDefaults().getOrDefault(ParkourOption.TIME, "6000"), DEFAULT_SELECTED_TIME);
|
||||
}
|
||||
|
||||
private static double defaultSchematicDifficulty() {
|
||||
return parseDoubleSafe(Option.OPTIONS_DEFAULTS.getOrDefault(ParkourOption.SCHEMATICS, "0.6"), DEFAULT_SCHEMATIC_DIFFICULTY);
|
||||
return parseDoubleSafe(OptionGeneral.optionsDefaults().getOrDefault(ParkourOption.SCHEMATICS, "0.6"), DEFAULT_SCHEMATIC_DIFFICULTY);
|
||||
}
|
||||
|
||||
private static int parseIntSafe(String v, int fallback) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package dev.loki.loparkour.storage;
|
||||
|
||||
import dev.loki.loparkour.config.options.Option;
|
||||
import dev.loki.loparkour.config.options.section.OptionSQL;
|
||||
import dev.loki.loparkour.leaderboard.model.Score;
|
||||
import dev.loki.loparkour.storage.disk.StorageDisk;
|
||||
import dev.loki.loparkour.storage.sql.StorageSQL;
|
||||
|
|
@ -22,7 +22,7 @@ public final class Storage {
|
|||
}
|
||||
|
||||
public static void init(String mode) {
|
||||
if (Option.SQL) {
|
||||
if (OptionSQL.enabled()) {
|
||||
StorageSQL.init(mode);
|
||||
}
|
||||
}
|
||||
|
|
@ -32,7 +32,7 @@ public final class Storage {
|
|||
* If SQL is disabled (disk), calls the callback immediately.
|
||||
*/
|
||||
public static void runWhenReady(Runnable callback) {
|
||||
if (Option.SQL) {
|
||||
if (OptionSQL.enabled()) {
|
||||
StorageSQL.runWhenConnected(callback);
|
||||
} else {
|
||||
callback.run();
|
||||
|
|
@ -40,7 +40,7 @@ public final class Storage {
|
|||
}
|
||||
|
||||
public static void close() {
|
||||
if (Option.SQL) {
|
||||
if (OptionSQL.enabled()) {
|
||||
StorageSQL.close();
|
||||
}
|
||||
}
|
||||
|
|
@ -52,7 +52,7 @@ public final class Storage {
|
|||
* @return Map with all scores, unsorted.
|
||||
*/
|
||||
public static @NotNull Map<UUID, Score> readScores(@NotNull String mode) {
|
||||
if (Option.SQL) {
|
||||
if (OptionSQL.enabled()) {
|
||||
return StorageSQL.readScores(mode);
|
||||
} else {
|
||||
return StorageDisk.readScores(mode);
|
||||
|
|
@ -66,7 +66,7 @@ public final class Storage {
|
|||
* @param scores The score map.
|
||||
*/
|
||||
public static void writeScores(@NotNull String mode, @NotNull Map<UUID, Score> scores) {
|
||||
if (Option.SQL) {
|
||||
if (OptionSQL.enabled()) {
|
||||
StorageSQL.writeScores(mode, scores);
|
||||
} else {
|
||||
StorageDisk.writeScores(mode, scores);
|
||||
|
|
@ -79,7 +79,7 @@ public final class Storage {
|
|||
* @param player The player.
|
||||
*/
|
||||
public static void readPlayer(@NotNull ParkourPlayer player) {
|
||||
if (Option.SQL) {
|
||||
if (OptionSQL.enabled()) {
|
||||
StorageSQL.readPlayer(player);
|
||||
} else {
|
||||
StorageDisk.readPlayer(player);
|
||||
|
|
@ -92,7 +92,7 @@ public final class Storage {
|
|||
* @param player The player.
|
||||
*/
|
||||
public static void writePlayer(@NotNull ParkourPlayer player) {
|
||||
if (Option.SQL) {
|
||||
if (OptionSQL.enabled()) {
|
||||
StorageSQL.writePlayer(player);
|
||||
} else {
|
||||
StorageDisk.writePlayer(player);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package dev.loki.loparkour.storage.sql;
|
|||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import dev.loki.loparkour.LoParkour;
|
||||
import dev.loki.loparkour.config.options.Option;
|
||||
import dev.loki.loparkour.config.options.section.OptionSQL;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
|
@ -42,8 +42,8 @@ public class SQLConnectionManager {
|
|||
|
||||
final HikariConfig config = new HikariConfig();
|
||||
config.setJdbcUrl(buildConnectionUrl());
|
||||
config.setUsername(Option.SQL_USERNAME);
|
||||
config.setPassword(Option.SQL_PASSWORD);
|
||||
config.setUsername(OptionSQL.username());
|
||||
config.setPassword(OptionSQL.password());
|
||||
config.setMaximumPoolSize(MAX_POOL_SIZE);
|
||||
config.setMinimumIdle(2);
|
||||
config.setConnectionTimeout(CONNECTION_TIMEOUT_MILLIS);
|
||||
|
|
@ -87,7 +87,7 @@ public class SQLConnectionManager {
|
|||
public void validateConnection() {
|
||||
if (!isConnected()) {
|
||||
LoParkour.getPlugin().getLogger().warning("MySQL pool not available");
|
||||
Option.SQL = false;
|
||||
OptionSQL.disable();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -95,7 +95,7 @@ public class SQLConnectionManager {
|
|||
return ("jdbc:mysql://%s:%d/%s?allowPublicKeyRetrieval=true"
|
||||
+ "&useSSL=false&useUnicode=true&characterEncoding=utf-8"
|
||||
+ "&autoReconnect=true&maxReconnects=2&connectTimeout=5000&socketTimeout=5000")
|
||||
.formatted(Option.SQL_URL, Option.SQL_PORT, Option.SQL_DB);
|
||||
.formatted(OptionSQL.url(), OptionSQL.port(), OptionSQL.database());
|
||||
}
|
||||
|
||||
private void executeCallbacks() {
|
||||
|
|
@ -113,7 +113,7 @@ public class SQLConnectionManager {
|
|||
LoParkour.getPlugin().getLogger().severe(
|
||||
"Could not connect to MySQL - check your SQL settings - " + ex.getMessage());
|
||||
LoParkour.getPlugin().getLogger().severe("Disabling SQL storage, using local storage instead");
|
||||
Option.SQL = false;
|
||||
OptionSQL.disable();
|
||||
if (dataSource != null && !dataSource.isClosed()) {
|
||||
dataSource.close();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package dev.loki.loparkour.storage.sql.schema;
|
||||
|
||||
import dev.loki.loparkour.config.options.section.OptionSQL;
|
||||
import dev.loki.loparkour.storage.sql.query.SQLQueryExecutor;
|
||||
import dev.loki.loparkour.config.options.Option;
|
||||
|
||||
/**
|
||||
* Manages database schema migrations.
|
||||
|
|
@ -23,8 +23,8 @@ public class SQLMigrationManager {
|
|||
}
|
||||
|
||||
private void createDatabase() {
|
||||
queryExecutor.executeStaticUpdate("CREATE DATABASE IF NOT EXISTS `%s`;".formatted(Option.SQL_DB));
|
||||
queryExecutor.executeStaticUpdate("USE `%s`;".formatted(Option.SQL_DB));
|
||||
queryExecutor.executeStaticUpdate("CREATE DATABASE IF NOT EXISTS `%s`;".formatted(OptionSQL.database()));
|
||||
queryExecutor.executeStaticUpdate("USE `%s`;".formatted(OptionSQL.database()));
|
||||
}
|
||||
|
||||
private void createOptionsTable() {
|
||||
|
|
@ -33,11 +33,11 @@ public class SQLMigrationManager {
|
|||
"(`uuid` CHAR(36) NOT NULL, `time` VARCHAR(8), `style` VARCHAR(32), `blockLead` INT, " +
|
||||
"`useParticles` BOOLEAN, `useDifficulty` BOOLEAN, `useSpecial` BOOLEAN, " +
|
||||
"`showFallMsg` BOOLEAN, `showScoreboard` BOOLEAN, PRIMARY KEY (`uuid`)) " +
|
||||
"ENGINE = InnoDB CHARSET = utf8;").formatted(Option.SQL_PREFIX));
|
||||
"ENGINE = InnoDB CHARSET = utf8;").formatted(OptionSQL.prefix()));
|
||||
}
|
||||
|
||||
private void runMigrations() {
|
||||
final String prefix = Option.SQL_PREFIX;
|
||||
final String prefix = OptionSQL.prefix();
|
||||
|
||||
queryExecutor.executeStaticUpdateSuppressed("ALTER TABLE `%soptions` DROP COLUMN `time`;".formatted(prefix));
|
||||
queryExecutor.executeStaticUpdateSuppressed("ALTER TABLE `%soptions` ADD `selectedTime` INT NOT NULL;".formatted(prefix));
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package dev.loki.loparkour.world.core;
|
||||
|
||||
import dev.loki.loparkour.config.options.Option;
|
||||
import dev.loki.loparkour.config.options.OptionGeneral;
|
||||
import dev.loki.loparkour.config.options.section.OptionGeneration;
|
||||
import dev.loki.loparkour.session.core.Session;
|
||||
import org.bukkit.Location;
|
||||
|
||||
|
|
@ -61,9 +62,9 @@ public final class Divider {
|
|||
final int[] xz = spiralAt(SECTIONS.get(session));
|
||||
|
||||
return new Location(World.getWorld(),
|
||||
xz[0] * Option.BORDER_SIZE,
|
||||
(Option.MAX_Y + Option.MIN_Y) / 2.0,
|
||||
xz[1] * Option.BORDER_SIZE);
|
||||
xz[0] * OptionGeneral.borderSize(),
|
||||
(OptionGeneration.maxY() + OptionGeneration.minY()) / 2.0,
|
||||
xz[1] * OptionGeneral.borderSize());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -74,11 +75,11 @@ public final class Divider {
|
|||
final Location center = toLocation(session);
|
||||
|
||||
// get the min and max locations
|
||||
final Location max = center.clone().add(Option.BORDER_SIZE / 2, 0, Option.BORDER_SIZE / 2);
|
||||
final Location min = center.clone().subtract(Option.BORDER_SIZE / 2, 0, Option.BORDER_SIZE / 2);
|
||||
final Location max = center.clone().add(OptionGeneral.borderSize() / 2, 0, OptionGeneral.borderSize() / 2);
|
||||
final Location min = center.clone().subtract(OptionGeneral.borderSize() / 2, 0, OptionGeneral.borderSize() / 2);
|
||||
|
||||
max.setY(Option.MAX_Y);
|
||||
min.setY(Option.MIN_Y);
|
||||
max.setY(OptionGeneration.maxY());
|
||||
min.setY(OptionGeneration.minY());
|
||||
|
||||
return new Location[]{min, max};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue