Fix locale bug and parkour spawn position
- Fix locale 'true' bug with sanitization at all levels: * ConfigAccessor.getString() - force String.valueOf() * Option.java - sanitize LANG defaults from config * PlayerSettingsManager - sanitize on settings load * SQLDataMapper - sanitize on SQL load * StorageDisk - sanitize on JSON load * SQLMigrationManager - SQL migration to fix DB - Fix parkour first block position: * Island.java - spawn 6 blocks forward + 1 up from center * GeneratorCleanup.java - same position after fall/reset - Add spawn-location config option at top of config.yml
This commit is contained in:
parent
b0c03cd484
commit
3546d7f9e3
10 changed files with 154 additions and 272 deletions
107
TODO.md
107
TODO.md
|
|
@ -1,6 +1,6 @@
|
||||||
# LoParkour — TODO
|
# LoParkour — TODO
|
||||||
|
|
||||||
> Обновлено: 2026-04-01.
|
> Обновлено: 2026-04-09.
|
||||||
|
|
||||||
## Легенда
|
## Легенда
|
||||||
|
|
||||||
|
|
@ -11,9 +11,93 @@
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Главный план (стабилизация)
|
## Текущие задачи (2026-04-09)
|
||||||
|
|
||||||
Консолидировано после обхода: меню/util, `LoParkour`, `LoParkourCommand`, join/teleport, `SessionStateManager`, `Island.build()`, Locales, LoLib 3.x.
|
### 🔴 P0 — Критичные баги
|
||||||
|
|
||||||
|
| # | Задача | Статус |
|
||||||
|
|---|--------|--------|
|
||||||
|
| 1 | Баг с локалью `'true'` в БД/конфиге | ✅ Исправлено (санитизация на всех уровнях) |
|
||||||
|
| 2 | Первый блок паркура генерится на платформе | ✅ Исправлено (6 блоков вперёд + 1 вверх) |
|
||||||
|
| 3 | ElytraMode полностью не работает | 🔴 **КРИТИЧНО** - отсутствуют классы |
|
||||||
|
|
||||||
|
### 🟡 P1 — Важные недоработки
|
||||||
|
|
||||||
|
| # | Задача | Статус |
|
||||||
|
|---|--------|--------|
|
||||||
|
| 4 | GravityShiftMode не реализован | 🟡 Только конфиг |
|
||||||
|
| 5 | HardcoreMode не реализован | 🟡 Только конфиг |
|
||||||
|
|
||||||
|
### 🟢 P2 — Проверка после исправлений
|
||||||
|
|
||||||
|
| # | Задача | Статус |
|
||||||
|
|---|--------|--------|
|
||||||
|
| 6 | DefaultMode после изменений Island.java | 🟢 Требует проверки |
|
||||||
|
| 7 | SpeedrunMode таймеры блоков | 🟢 Требует проверки |
|
||||||
|
| 8 | RaceMode прогресс-бар и финиш | 🟢 Требует проверки |
|
||||||
|
| 9 | CoopMode мультиплеер | 🟢 Требует проверки |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Детальный план исправления режимов
|
||||||
|
|
||||||
|
### ElytraMode (4-6 часов)
|
||||||
|
|
||||||
|
**Проблема:** Отсутствуют классы, на которые ссылается `ElytraGenerator`:
|
||||||
|
- `ElytraConfig` - загрузка настроек из config.yml
|
||||||
|
- `ElytraRing` - модель кольца (центр, радиус, направление)
|
||||||
|
- `ElytraRingGenerator` - генерация колец по траектории
|
||||||
|
- `ElytraPhysics` - проверка пролёта, падения, буста
|
||||||
|
- `ElytraRenderer` - отрисовка частицами
|
||||||
|
|
||||||
|
**План:**
|
||||||
|
1. Создать `mode/elytra/ElytraConfig.java`
|
||||||
|
2. Создать `mode/elytra/ElytraRing.java`
|
||||||
|
3. Создать `mode/elytra/ElytraRingGenerator.java`
|
||||||
|
4. Создать `mode/elytra/ElytraPhysics.java`
|
||||||
|
5. Создать `mode/elytra/ElytraRenderer.java`
|
||||||
|
6. Исправить `generateFirst()` в `ElytraGenerator`
|
||||||
|
7. Добавить выдачу элитры и фейерверков
|
||||||
|
|
||||||
|
### GravityShiftMode (2-3 часа)
|
||||||
|
|
||||||
|
**План:**
|
||||||
|
1. Создать `GravityShiftMode.java`
|
||||||
|
2. Создать `GravityShiftGenerator extends ParkourGenerator`
|
||||||
|
3. Счётчик прыжков, каждые N прыжков - случайный эффект
|
||||||
|
4. Эффекты: jump-boost, speed, slowness, levitation
|
||||||
|
5. Зарегистрировать в `Modes.java`
|
||||||
|
|
||||||
|
### HardcoreMode (1-2 часа)
|
||||||
|
|
||||||
|
**План:**
|
||||||
|
1. Создать `HardcoreMode.java`
|
||||||
|
2. Создать `HardcoreGenerator extends ParkourGenerator`
|
||||||
|
3. Переопределить `fall()` - сбросить `collectedRewards`
|
||||||
|
4. Зарегистрировать в `Modes.java`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Исправления от 2026-04-09
|
||||||
|
|
||||||
|
### ✅ Баг с локалью
|
||||||
|
- `ConfigAccessor.getString()` - форсирует String через `String.valueOf()`
|
||||||
|
- `Option.java:267-272` - санитизация при загрузке дефолтов из конфига
|
||||||
|
- `PlayerSettingsManager.java:37-44` - санитизация при загрузке настроек
|
||||||
|
- `SQLDataMapper.java:87-95` - санитизация при загрузке из SQL
|
||||||
|
- `StorageDisk.java:90-106` - санитизация при загрузке из JSON
|
||||||
|
- `SQLMigrationManager.java:51-53` - SQL миграция для исправления БД
|
||||||
|
|
||||||
|
### ✅ Первый блок паркура
|
||||||
|
- `Island.java:75-90` - первый блок на 6 блоков вперёд + 1 вверх от центра
|
||||||
|
- `GeneratorCleanup.java:110-127` - после падения тоже 6 вперёд + 1 вверх
|
||||||
|
|
||||||
|
### ✅ Spawn location в конфиге
|
||||||
|
- Добавлены `spawn-location` и `spawn-axes` в начало config.yml
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Главный план (стабилизация)
|
||||||
|
|
||||||
### P0 — блокер загрузки или геймплей
|
### P0 — блокер загрузки или геймплей
|
||||||
|
|
||||||
|
|
@ -37,17 +121,6 @@
|
||||||
| 6 | `LifecycleTickManager` / cleanup / time UI | ✅ |
|
| 6 | `LifecycleTickManager` / cleanup / time UI | ✅ |
|
||||||
| 7 | Scoring в воздухе | ✅ документировано (стояние на блоке) |
|
| 7 | Scoring в воздухе | ✅ документировано (стояние на блоке) |
|
||||||
|
|
||||||
### Контекст (не в «критичном» списке)
|
|
||||||
|
|
||||||
- Порядок `generateFirst` / телепорт из `Island.build()` — ок при неизменённом порядке вызовов.
|
|
||||||
- `history.contains(Block)` — Bukkit сравнивает по миру и координатам.
|
|
||||||
- `InventoryType.CHEST` в GUI — при странных кейсах проверить тип инвентаря.
|
|
||||||
|
|
||||||
### Порядок работ (регрессия)
|
|
||||||
|
|
||||||
1. `./gradlew build`, старт без `LinkageError`.
|
|
||||||
2. Ручной прогон паркура: счёт, меню, scoreboard, режимы.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Follow-up (сделано в коде)
|
## Follow-up (сделано в коде)
|
||||||
|
|
@ -62,7 +135,6 @@
|
||||||
- **RandomStyle** / **ElytraGenerator**: защита от пустых списков.
|
- **RandomStyle** / **ElytraGenerator**: защита от пустых списков.
|
||||||
- **InventoryData**: новые сохранения в **YAML**; legacy binary читается один раз при миграции.
|
- **InventoryData**: новые сохранения в **YAML**; legacy binary читается один раз при миграции.
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Чек-лист перед релизом
|
## Чек-лист перед релизом
|
||||||
|
|
@ -71,7 +143,4 @@
|
||||||
- [ ] Старт сервера, `/parkour`, меню, один полный забег
|
- [ ] Старт сервера, `/parkour`, меню, один полный забег
|
||||||
- [ ] SQL: при проде выставить `LOPARKOUR_SQL_PASSWORD` на хосте
|
- [ ] SQL: при проде выставить `LOPARKOUR_SQL_PASSWORD` на хосте
|
||||||
- [ ] Проверить миграцию старых `.dat` инвентарей при первом заходе игрока
|
- [ ] Проверить миграцию старых `.dat` инвентарей при первом заходе игрока
|
||||||
|
- [ ] Протестировать все режимы: default, speedrun, race, coop, elytra, gravity-shift, hardcore
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -85,11 +85,17 @@ public class ConfigAccessor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get string value at path.
|
* Get string value at path.
|
||||||
|
* Forces conversion to String even if YAML parsed as Boolean/Number.
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
public String getString(@NotNull String path) {
|
public String getString(@NotNull String path) {
|
||||||
warnIfMissing(path);
|
warnIfMissing(path);
|
||||||
return config.getString(path, "");
|
Object value = config.get(path);
|
||||||
|
if (value == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
// Force toString() to handle Boolean/Number values
|
||||||
|
return String.valueOf(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -266,6 +266,12 @@ public class Option {
|
||||||
// Always read as String to avoid Boolean parsing issues
|
// Always read as String to avoid Boolean parsing issues
|
||||||
String value = Config.CONFIG.getString(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
|
// Debug logging
|
||||||
if (option == ParkourOption.LANG) {
|
if (option == ParkourOption.LANG) {
|
||||||
LoParkour.getPlugin().getLogger().info("LANG option: path=" + defaultPath + ", value=" + value);
|
LoParkour.getPlugin().getLogger().info("LANG option: path=" + defaultPath + ", value=" + value);
|
||||||
|
|
|
||||||
|
|
@ -72,11 +72,12 @@ public final class Island {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Player stand 2 blocks "behind" center along heading; course line continues +4 then first jump +4 more (old island logic)
|
// Player spawns at center, first parkour block 6 blocks forward and 1 block up
|
||||||
int px = cx - 2 * hx;
|
int px = cx;
|
||||||
int pz = cz - 2 * hz;
|
int pz = cz;
|
||||||
int qx = px + 4 * hx;
|
int qx = cx + 6 * hx;
|
||||||
int qz = pz + 4 * hz;
|
int qz = cz + 6 * hz;
|
||||||
|
int qy = cy + 1;
|
||||||
|
|
||||||
Block playerFoot = world.getBlockAt(px, cy, pz);
|
Block playerFoot = world.getBlockAt(px, cy, pz);
|
||||||
|
|
||||||
|
|
@ -84,10 +85,7 @@ public final class Island {
|
||||||
ps.setYaw((float) Config.GENERATION.getInt("advanced.island.spawn.yaw"));
|
ps.setYaw((float) Config.GENERATION.getInt("advanced.island.spawn.yaw"));
|
||||||
ps.setPitch((float) Config.GENERATION.getInt("advanced.island.spawn.pitch"));
|
ps.setPitch((float) Config.GENERATION.getInt("advanced.island.spawn.pitch"));
|
||||||
|
|
||||||
Location parkourStart = world.getBlockAt(qx, cy, qz).getLocation().add(
|
Location parkourStart = world.getBlockAt(qx, qy, qz).getLocation();
|
||||||
h.getX() * 4,
|
|
||||||
0,
|
|
||||||
h.getZ() * 4);
|
|
||||||
|
|
||||||
session.generator.generateFirst(ps, parkourStart);
|
session.generator.generateFirst(ps, parkourStart);
|
||||||
session.generator.startTick();
|
session.generator.startTick();
|
||||||
|
|
|
||||||
|
|
@ -111,15 +111,15 @@ public class GeneratorCleanup {
|
||||||
// Regenerate first block
|
// Regenerate first block
|
||||||
Location spawn = generator.state.playerSpawn;
|
Location spawn = generator.state.playerSpawn;
|
||||||
if (spawn != null) {
|
if (spawn != null) {
|
||||||
// Place first block ahead of spawn based on heading direction
|
// Place first block 6 blocks forward and 1 block up from spawn
|
||||||
Location blockSpawn = spawn.clone().add(0, -1, 0);
|
Location blockSpawn = spawn.clone();
|
||||||
|
|
||||||
// Move block forward based on heading
|
// Move block forward based on heading (6 blocks forward, 1 up)
|
||||||
switch (dev.loki.loparkour.config.Option.HEADING) {
|
switch (dev.loki.loparkour.config.Option.HEADING) {
|
||||||
case NORTH -> blockSpawn.add(0, 0, -3);
|
case NORTH -> blockSpawn.add(0, 1, -6);
|
||||||
case SOUTH -> blockSpawn.add(0, 0, 3);
|
case SOUTH -> blockSpawn.add(0, 1, 6);
|
||||||
case WEST -> blockSpawn.add(-3, 0, 0);
|
case WEST -> blockSpawn.add(-6, 1, 0);
|
||||||
case EAST -> blockSpawn.add(3, 0, 0);
|
case EAST -> blockSpawn.add(6, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
generator.generateFirst(spawn, blockSpawn);
|
generator.generateFirst(spawn, blockSpawn);
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,13 @@ public class PlayerSettingsManager {
|
||||||
p.selectedTime = parseIntSafe(v, defaultSelectedTime())));
|
p.selectedTime = parseIntSafe(v, defaultSelectedTime())));
|
||||||
COLUMN_MAPPINGS.put("collectedRewards", new OptionContainer(null, PlayerSettingsManager::applyCollectedRewards));
|
COLUMN_MAPPINGS.put("collectedRewards", new OptionContainer(null, PlayerSettingsManager::applyCollectedRewards));
|
||||||
COLUMN_MAPPINGS.put("locale", new OptionContainer(ParkourOption.LANG, (p, v) -> {
|
COLUMN_MAPPINGS.put("locale", new OptionContainer(ParkourOption.LANG, (p, v) -> {
|
||||||
p._locale = v;
|
// Sanitize legacy Boolean values from old config parsing
|
||||||
p.locale = v;
|
String sanitized = v;
|
||||||
|
if ("true".equals(v) || "false".equals(v)) {
|
||||||
|
sanitized = Option.OPTIONS_DEFAULTS.getOrDefault(ParkourOption.LANG, "en");
|
||||||
|
}
|
||||||
|
p._locale = sanitized;
|
||||||
|
p.locale = sanitized;
|
||||||
}));
|
}));
|
||||||
COLUMN_MAPPINGS.put("schematicDifficulty", new OptionContainer(ParkourOption.SCHEMATICS, (p, v) ->
|
COLUMN_MAPPINGS.put("schematicDifficulty", new OptionContainer(ParkourOption.SCHEMATICS, (p, v) ->
|
||||||
p.schematicDifficulty = parseDoubleSafe(v, defaultSchematicDifficulty())));
|
p.schematicDifficulty = parseDoubleSafe(v, defaultSchematicDifficulty())));
|
||||||
|
|
|
||||||
|
|
@ -85,9 +85,14 @@ public class SQLDataMapper {
|
||||||
* Apply player data to ParkourPlayer object.
|
* Apply player data to ParkourPlayer object.
|
||||||
*/
|
*/
|
||||||
public static void applyPlayerData(@NotNull ParkourPlayer player, @NotNull PlayerData data) {
|
public static void applyPlayerData(@NotNull ParkourPlayer player, @NotNull PlayerData data) {
|
||||||
player.locale = data.locale();
|
// Sanitize legacy Boolean locale values
|
||||||
|
String locale = data.locale();
|
||||||
|
if (locale == null || "true".equals(locale) || "false".equals(locale) || "1".equals(locale) || "0".equals(locale)) {
|
||||||
|
locale = "en";
|
||||||
|
}
|
||||||
|
player.locale = locale;
|
||||||
player.style = data.styleName();
|
player.style = data.styleName();
|
||||||
|
|
||||||
// Apply settings if available
|
// Apply settings if available
|
||||||
if (data.settings() != null && !data.settings().isEmpty()) {
|
if (data.settings() != null && !data.settings().isEmpty()) {
|
||||||
deserializeSettings(player, data.settings());
|
deserializeSettings(player, data.settings());
|
||||||
|
|
|
||||||
|
|
@ -46,5 +46,9 @@ class SQLMigrationManager {
|
||||||
queryExecutor.executeStaticUpdateSuppressed("ALTER TABLE `%soptions` ADD `sound` BOOLEAN;".formatted(prefix));
|
queryExecutor.executeStaticUpdateSuppressed("ALTER TABLE `%soptions` ADD `sound` BOOLEAN;".formatted(prefix));
|
||||||
queryExecutor.executeStaticUpdateSuppressed("ALTER TABLE `%soptions` DROP COLUMN `useDifficulty`;".formatted(prefix));
|
queryExecutor.executeStaticUpdateSuppressed("ALTER TABLE `%soptions` DROP COLUMN `useDifficulty`;".formatted(prefix));
|
||||||
queryExecutor.executeStaticUpdateSuppressed("ALTER TABLE `%soptions` DROP COLUMN `useStructure`;".formatted(prefix));
|
queryExecutor.executeStaticUpdateSuppressed("ALTER TABLE `%soptions` DROP COLUMN `useStructure`;".formatted(prefix));
|
||||||
|
|
||||||
|
// Fix legacy Boolean locale values (true/false) to proper locale codes
|
||||||
|
queryExecutor.executeStaticUpdateSuppressed(
|
||||||
|
"UPDATE `%soptions` SET `locale` = 'en' WHERE `locale` IN ('true', 'false', '1', '0');".formatted(prefix));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,13 @@ class StorageDisk {
|
||||||
settings.put("showScoreboard", from.showScoreboard);
|
settings.put("showScoreboard", from.showScoreboard);
|
||||||
settings.put("selectedTime", from.selectedTime);
|
settings.put("selectedTime", from.selectedTime);
|
||||||
settings.put("collectedRewards", from.collectedRewards);
|
settings.put("collectedRewards", from.collectedRewards);
|
||||||
settings.put("locale", from._locale);
|
|
||||||
|
// Sanitize legacy Boolean locale values
|
||||||
|
String locale = from._locale;
|
||||||
|
if (locale == null || "true".equals(locale) || "false".equals(locale) || "1".equals(locale) || "0".equals(locale)) {
|
||||||
|
locale = "en";
|
||||||
|
}
|
||||||
|
settings.put("locale", locale);
|
||||||
settings.put("schematicDifficulty", from.schematicDifficulty);
|
settings.put("schematicDifficulty", from.schematicDifficulty);
|
||||||
settings.put("sound", from.sound);
|
settings.put("sound", from.sound);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,107 +17,53 @@
|
||||||
# #
|
# #
|
||||||
#===============================================================================#
|
#===============================================================================#
|
||||||
|
|
||||||
|
# -= Spawn location =-
|
||||||
|
# Location where players spawn when joining parkour
|
||||||
|
# Syntax: '(x,y,z,worldName)'
|
||||||
|
spawn-location: '(0,100,0,loparkour)'
|
||||||
|
|
||||||
|
# -= Spawn axes =-
|
||||||
|
# Sets the pitch and yaw of the spawn location
|
||||||
|
# First argument is pitch, second is yaw
|
||||||
|
spawn-axes: '0,0'
|
||||||
|
|
||||||
# -= Debugging =-
|
# -= Debugging =-
|
||||||
debug: false
|
debug: false
|
||||||
|
|
||||||
# -= Enable joining =-
|
# -= Enable joining =-
|
||||||
# Whether players can join the parkour.
|
|
||||||
# When joining is disabled, the IP instance on this server will only read data from leaderboard databases.
|
|
||||||
# Set joining to false if you want to create a cross-server leaderboard on this server.
|
|
||||||
# true = players can join, false = players can't join.
|
|
||||||
joining: true
|
joining: true
|
||||||
|
|
||||||
# -= Proxy options =-
|
# -= Proxy options =-
|
||||||
# Change the proxy settings. Applies to Velocity as well.
|
|
||||||
# This also applies to servers who only want to run this plugin.
|
|
||||||
bungeecord:
|
bungeecord:
|
||||||
|
|
||||||
# -= Proxy enabled =-
|
|
||||||
# Enabling this will make players who join the server automatically join the parkour.
|
|
||||||
# You can enable this even without BungeeCord to make this a parkour-only server.
|
|
||||||
# True = players will automatically join the parkour on join, false = players have to use the menu/parkour command.
|
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
# -= Proxy return server =-
|
|
||||||
# The server the players will be returned to after they leave.
|
|
||||||
return_server: 'Lobby'
|
return_server: 'Lobby'
|
||||||
|
|
||||||
# -= Go back enabled =-
|
|
||||||
# Whether players should be teleported to a specific location after leaving.
|
|
||||||
# True = players get teleported to a specific location when they leave, false = they go to their location when they joined.
|
|
||||||
go-back-enabled: false
|
go-back-enabled: false
|
||||||
|
|
||||||
# -= Go back location =-
|
|
||||||
# The place players will go back to when they leave
|
|
||||||
# Only applies if proxy mode is disabled and the go-back-enabled option is true.
|
|
||||||
# Syntax: '(x,y,z,worldName)'
|
|
||||||
go-back: '(0,100,0,world)'
|
go-back: '(0,100,0,world)'
|
||||||
|
|
||||||
# -= Go back axes =-
|
|
||||||
# Sets the pitch and yaw of the go-back location.
|
|
||||||
# The first argument is the pitch, second yaw.
|
|
||||||
go-back-axes: '0,0'
|
go-back-axes: '0,0'
|
||||||
|
|
||||||
# -= Storage update interval =-
|
# -= Storage update interval =-
|
||||||
# The amount of seconds between every disk/database storage update.
|
|
||||||
# In this update, the in-memory scores will be written to storage.
|
|
||||||
# A lower number might reduce the chance of losing data on server crashes,
|
|
||||||
# but will increase the amount of requests to the disk/database.
|
|
||||||
# (requires a restart, default = 300)
|
|
||||||
storage-update-interval: 300
|
storage-update-interval: 300
|
||||||
|
|
||||||
# -= MySQL =-
|
# -= MySQL =-
|
||||||
# The options for using MySQL as storage.
|
|
||||||
sql:
|
sql:
|
||||||
|
|
||||||
# -= MySQL enabled =-
|
|
||||||
# Using databases makes you able to sync player data across multiple servers.
|
|
||||||
# True = data will be stored in a database, false = data will be stored locally.
|
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
# -= MySQL settings =-
|
|
||||||
url: 'localhost'
|
url: 'localhost'
|
||||||
port: 3306
|
port: 3306
|
||||||
username: 'efnilite'
|
username: 'efnilite'
|
||||||
# If env LOPARKOUR_SQL_PASSWORD is set (non-empty), it overrides this value (recommended for production).
|
|
||||||
password: 'super secret password'
|
password: 'super secret password'
|
||||||
database: 'ip'
|
database: 'ip'
|
||||||
|
|
||||||
# -= MySQL prefix =-
|
|
||||||
# The prefix given to any table names
|
|
||||||
# The default is ''. Example: 'ip-' -> this would make the table 'ip-players'
|
|
||||||
prefix: ''
|
prefix: ''
|
||||||
|
|
||||||
# -= World options =-
|
# -= World options =-
|
||||||
world:
|
world:
|
||||||
|
|
||||||
# -= World name =-
|
|
||||||
# The world in which parkour will take place
|
|
||||||
name: 'loparkour'
|
name: 'loparkour'
|
||||||
|
island-schematic: 'island'
|
||||||
# -= Island schematic =-
|
|
||||||
# Name of the spawn island schematic (schematics-new folder). Falls back to generation.yml if empty.
|
|
||||||
island-schematic: island
|
|
||||||
|
|
||||||
# -= Delete world on reload =-
|
|
||||||
# Deletes the world on reload/restart of the server.
|
|
||||||
# This makes sure there are no ghost blocks left when a server crash occurs.
|
|
||||||
# Disable this if you want to have a custom map.
|
|
||||||
delete-on-reload: true
|
delete-on-reload: true
|
||||||
|
|
||||||
# -= World fall back =-
|
|
||||||
# The world players will be teleported to if they accidentally join the Parkour world without joining parkour
|
|
||||||
fall-back: 'world'
|
fall-back: 'world'
|
||||||
|
|
||||||
# -= General options =-
|
# -= General options =-
|
||||||
options:
|
options:
|
||||||
|
|
||||||
# -= Leads options =-
|
|
||||||
leads:
|
leads:
|
||||||
|
|
||||||
# -= Leads amounts =-
|
|
||||||
# The lead amounts a player can select in their options menu.
|
|
||||||
# Values also need to be above 1 and below 64.
|
|
||||||
amount:
|
amount:
|
||||||
- 1
|
- 1
|
||||||
- 2
|
- 2
|
||||||
|
|
@ -130,46 +76,15 @@ options:
|
||||||
- 9
|
- 9
|
||||||
- 10
|
- 10
|
||||||
|
|
||||||
# -= Time options =-
|
|
||||||
time:
|
time:
|
||||||
|
|
||||||
# -= Time format =-
|
|
||||||
# Choose between:
|
|
||||||
# 24 - 24 hour clock. (00:00, 12:00, 23:59)
|
|
||||||
# 12 - 12 hour clock. (12:00 AM, 12:00 PM, 11:59 PM)
|
|
||||||
format: 24
|
format: 24
|
||||||
|
|
||||||
# -= Score time format =-
|
|
||||||
# H = hours, m = minutes, s = seconds, S = milliseconds
|
|
||||||
score-format: "mm:ss:SSS"
|
score-format: "mm:ss:SSS"
|
||||||
|
|
||||||
# -= Inventory handling =-
|
|
||||||
# Toggles the inventory handling system.
|
|
||||||
# True = players' inventories get saved and cleared when they join the parkour and when they leave they get their items back
|
|
||||||
# False = players keep their inventories when they join the parkour
|
|
||||||
inventory-handling: true
|
inventory-handling: true
|
||||||
|
|
||||||
# -= Inventory saving =-
|
|
||||||
# Logs inventories of the players that join to the inventories/ folder.
|
|
||||||
# It is highly recommended to keep this enabled. Server crashes or errors while leaving might cause
|
|
||||||
# inventories of players to be lost if this is set to false!
|
|
||||||
# Use /ip recoverinventory to recover inventories of players who joined the parkour and who lost their inventories in a crash, etc.
|
|
||||||
inventory-saving: true
|
inventory-saving: true
|
||||||
|
|
||||||
# -= Alternate inventory saving command =-
|
|
||||||
# If you don't trust this plugin to save inventories, you can select another plugin to execute a command
|
|
||||||
# to save players' inventories.
|
|
||||||
# Example: /inventory save %player%
|
|
||||||
# This command will be executed by console.
|
|
||||||
alt-inventory-saving-command: ''
|
alt-inventory-saving-command: ''
|
||||||
|
|
||||||
# -= Disables inventory blocks =-
|
|
||||||
# Disables the ability for a player to open blocks with an inventory.
|
|
||||||
disable-inventory-blocks: false
|
disable-inventory-blocks: false
|
||||||
|
|
||||||
# -= Hotbar slots =-
|
|
||||||
# Configure which hotbar slots (0-8) to use for parkour items
|
|
||||||
# Items will be placed in these slots in order: play, community, settings, lobby, quit
|
|
||||||
hotbar-slots:
|
hotbar-slots:
|
||||||
play: 1
|
play: 1
|
||||||
community: 3
|
community: 3
|
||||||
|
|
@ -178,33 +93,13 @@ options:
|
||||||
quit: 7
|
quit: 7
|
||||||
|
|
||||||
# -= Permissions options =-
|
# -= Permissions options =-
|
||||||
# These permissions are used to determine which things the player can change.
|
|
||||||
# Find them at https://efnilite.dev/projects/ip/wiki
|
|
||||||
permissions:
|
permissions:
|
||||||
|
|
||||||
# -= Permissions enabled =-
|
|
||||||
# If permission handling is enabled.
|
|
||||||
# True = players need a permission to join, view the leaderboard, etc., false = players can do and view anything
|
|
||||||
# from this plugin besides admin commands.
|
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
# -= Per style permissions =-
|
|
||||||
# Gives every style a permission. The permission is the name of the style.
|
|
||||||
# Syntax: ip.settings.styles.<style> - example: ip.settings.styles.red
|
|
||||||
# Useful for servers with ranks.
|
|
||||||
per-style: false
|
per-style: false
|
||||||
|
|
||||||
# -= Focus mode options =-
|
# -= Focus mode options =-
|
||||||
focus-mode:
|
focus-mode:
|
||||||
|
|
||||||
# -= Focus mode enabled =-
|
|
||||||
# If focus mode is enabled players can't use commands while in parkour.
|
|
||||||
# Note: this might not work on all commands because Minecraft.
|
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
# -=
|
|
||||||
# A whitelist for commands which ARE allowed during focus mode (if focus mode is enabled).
|
|
||||||
# If you want to disable the default whitelisted commands you can remove every item in the list below.
|
|
||||||
whitelist:
|
whitelist:
|
||||||
- 'ip'
|
- 'ip'
|
||||||
- 'parkour'
|
- 'parkour'
|
||||||
|
|
@ -217,10 +112,6 @@ focus-mode:
|
||||||
|
|
||||||
# -= Styles options =-
|
# -= Styles options =-
|
||||||
styles:
|
styles:
|
||||||
|
|
||||||
# -= Styles list =-
|
|
||||||
# The list of all available styles, which you can add to if you want.
|
|
||||||
# For changes, you have to restart or reload your server.
|
|
||||||
list:
|
list:
|
||||||
red: [red_wool, red_stained_glass, red_concrete, red_terracotta, red_concrete_slab, red_terracotta_slab]
|
red: [red_wool, red_stained_glass, red_concrete, red_terracotta, red_concrete_slab, red_terracotta_slab]
|
||||||
blue: [blue_wool, blue_stained_glass, blue_concrete, blue_terracotta, blue_concrete_slab, blue_terracotta_slab]
|
blue: [blue_wool, blue_stained_glass, blue_concrete, blue_terracotta, blue_concrete_slab, blue_terracotta_slab]
|
||||||
|
|
@ -244,37 +135,15 @@ styles:
|
||||||
|
|
||||||
# -= Jump validation options =-
|
# -= Jump validation options =-
|
||||||
jump-validation:
|
jump-validation:
|
||||||
|
|
||||||
# -= Jump validation enabled =-
|
|
||||||
# Validates generated jumps using Minecraft physics.
|
|
||||||
# Ensures all jumps are physically possible.
|
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
# -= Maximum jump distance =-
|
|
||||||
# Maximum 3D distance for a jump (Pythagorean theorem).
|
|
||||||
max-distance: 4.5
|
max-distance: 4.5
|
||||||
|
|
||||||
# -= Maximum horizontal distance =-
|
|
||||||
# Maximum horizontal distance (X and Z axes only).
|
|
||||||
max-horizontal: 4.1
|
max-horizontal: 4.1
|
||||||
|
|
||||||
# -= Maximum vertical up =-
|
|
||||||
# Maximum height a player can jump up.
|
|
||||||
max-vertical-up: 1.25
|
max-vertical-up: 1.25
|
||||||
|
|
||||||
# -= Maximum vertical down =-
|
|
||||||
# Maximum height a player can jump down.
|
|
||||||
max-vertical-down: 3.0
|
max-vertical-down: 3.0
|
||||||
|
|
||||||
# -= Jump types options =-
|
# -= Jump types options =-
|
||||||
jump-types:
|
jump-types:
|
||||||
|
|
||||||
# -= Jump types enabled =-
|
|
||||||
# Enables special jump types (neo-jumps, fence jumps, etc.).
|
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
# -= Jump types list =-
|
|
||||||
# Configure which jump types are enabled and their spawn chances.
|
|
||||||
types:
|
types:
|
||||||
neo-jump:
|
neo-jump:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
@ -294,50 +163,24 @@ jump-types:
|
||||||
|
|
||||||
# -= Memory optimization =-
|
# -= Memory optimization =-
|
||||||
memory:
|
memory:
|
||||||
|
|
||||||
# -= Block cleanup distance =-
|
|
||||||
# Span (in history indices) for schematic trail removal and similar bulk clears.
|
|
||||||
block-cleanup-distance: 20
|
block-cleanup-distance: 20
|
||||||
|
|
||||||
# -= Trail keep-behind =-
|
|
||||||
# How many course blocks to keep behind the rearmost standing player before removing older trail (index-based; not world distance).
|
|
||||||
trail-keep-behind: 10
|
trail-keep-behind: 10
|
||||||
|
|
||||||
# -= Cleanup interval =-
|
|
||||||
# How often (in ticks) to run trail cleanup behind players.
|
|
||||||
# 20 ticks = 1 second
|
|
||||||
cleanup-interval: 100
|
cleanup-interval: 100
|
||||||
|
|
||||||
# -= Ghost mode options =-
|
# -= Ghost mode options =-
|
||||||
ghost-mode:
|
ghost-mode:
|
||||||
|
|
||||||
# -= Ghost mode enabled =-
|
|
||||||
# Shows ghosts of top players running alongside you.
|
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
# -= Show top =-
|
|
||||||
# How many top ghosts to show (1-3).
|
|
||||||
show-top: 3
|
show-top: 3
|
||||||
|
|
||||||
# -= Ghost transparency =-
|
|
||||||
# Transparency of ghost entities (0.0 = invisible, 1.0 = fully visible).
|
|
||||||
transparency: 0.5
|
transparency: 0.5
|
||||||
|
|
||||||
# -= Game modes options =-
|
# -= Game modes options =-
|
||||||
modes:
|
modes:
|
||||||
|
|
||||||
# -= Speedrun mode =-
|
|
||||||
speedrun:
|
speedrun:
|
||||||
# Block lifetime in seconds before disappearing
|
|
||||||
block-lifetime: 1.5
|
block-lifetime: 1.5
|
||||||
# Warning time in seconds before block disappears
|
|
||||||
warning-time: 0.5
|
warning-time: 0.5
|
||||||
|
|
||||||
# -= Gravity shift mode =-
|
|
||||||
gravity-shift:
|
gravity-shift:
|
||||||
# Interval in jumps before effect changes
|
|
||||||
interval: 10
|
interval: 10
|
||||||
|
|
||||||
effects:
|
effects:
|
||||||
jump-boost:
|
jump-boost:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
@ -356,97 +199,45 @@ modes:
|
||||||
amplifier: 1
|
amplifier: 1
|
||||||
duration: 5
|
duration: 5
|
||||||
|
|
||||||
# -= Hardcore mode =-
|
|
||||||
hardcore:
|
hardcore:
|
||||||
# Reset all rewards on fall
|
|
||||||
reset-rewards: true
|
reset-rewards: true
|
||||||
|
|
||||||
# -= Elytra mode =-
|
|
||||||
elytra:
|
elytra:
|
||||||
# Enable elytra mode
|
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
# --- Ring course settings ---
|
|
||||||
# Minimum distance (blocks) between consecutive rings
|
|
||||||
ring-distance-min: 20
|
ring-distance-min: 20
|
||||||
# Maximum distance (blocks) between consecutive rings
|
|
||||||
ring-distance-max: 40
|
ring-distance-max: 40
|
||||||
# Ring radius in blocks. Player must fly through the center hole.
|
|
||||||
ring-size: 5
|
ring-size: 5
|
||||||
# How many rings to generate ahead of the player
|
|
||||||
ring-lead: 8
|
ring-lead: 8
|
||||||
# Maximum horizontal heading change per ring in degrees (course curvature)
|
|
||||||
max-heading-change-horizontal: 30
|
max-heading-change-horizontal: 30
|
||||||
# Maximum vertical heading change per ring in degrees
|
|
||||||
max-heading-change-vertical: 15
|
max-heading-change-vertical: 15
|
||||||
# Maximum Y blocks above spawn point that the course can reach
|
|
||||||
max-height-above-spawn: 60
|
max-height-above-spawn: 60
|
||||||
# How far from the course (blocks) before a fall is triggered
|
|
||||||
max-deviation: 25
|
max-deviation: 25
|
||||||
|
|
||||||
# --- Firework / boost settings ---
|
|
||||||
# Firework velocity boost multiplier
|
|
||||||
boost-power: 1.5
|
boost-power: 1.5
|
||||||
# Cooldown between firework boosts in milliseconds
|
|
||||||
firework-cooldown-ms: 3000
|
firework-cooldown-ms: 3000
|
||||||
# Number of fireworks given at session start
|
|
||||||
starting-fireworks: 64
|
starting-fireworks: 64
|
||||||
|
|
||||||
# -= Race mode =-
|
|
||||||
race:
|
race:
|
||||||
# Enable race mode
|
|
||||||
enabled: true
|
enabled: true
|
||||||
# Target score to win
|
|
||||||
target-score: 100
|
target-score: 100
|
||||||
|
|
||||||
# -= Co-op mode =-
|
|
||||||
coop:
|
coop:
|
||||||
# Enable co-op mode
|
|
||||||
enabled: true
|
enabled: true
|
||||||
# Maximum players in co-op session
|
|
||||||
max-players: 4
|
max-players: 4
|
||||||
|
|
||||||
|
|
||||||
# -= Scoring options =-
|
# -= Scoring options =-
|
||||||
scoring:
|
scoring:
|
||||||
|
|
||||||
# -= All points =-
|
|
||||||
# This will give the player all possible points.
|
|
||||||
# If a player skips a block jump, it will still give the points for that block.
|
|
||||||
all-points: false
|
all-points: false
|
||||||
|
|
||||||
# -= Rewards use total score =-
|
|
||||||
# Whether interval rewards should use the total score of a session or not.
|
|
||||||
# The total score doesn't reset when a player falls.
|
|
||||||
rewards-use-total-score: false
|
rewards-use-total-score: false
|
||||||
|
|
||||||
# -= Particle options =-
|
# -= Particle options =-
|
||||||
particles:
|
particles:
|
||||||
|
|
||||||
# -= Particle shape =-
|
|
||||||
# The shape of the particle that will appear when a new block generates.
|
|
||||||
# Possible options: dot, box, circle
|
|
||||||
particle-shape: 'box'
|
particle-shape: 'box'
|
||||||
|
|
||||||
# -= Particle type =-
|
|
||||||
# The type of particle that will appear when a new block generates.
|
|
||||||
# You can find all types at https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Particle.html
|
|
||||||
particle-type: 'SPELL_INSTANT'
|
particle-type: 'SPELL_INSTANT'
|
||||||
|
|
||||||
# -= Sound type =-
|
|
||||||
# The sound that will play when a new block generates.
|
|
||||||
# You can find all sounds at https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Sound.html
|
|
||||||
sound-type: 'BLOCK_NOTE_BLOCK_GUITAR'
|
sound-type: 'BLOCK_NOTE_BLOCK_GUITAR'
|
||||||
|
|
||||||
# -= Sound pitch =-
|
|
||||||
# The pitch of the sound that will play when a new block generates.
|
|
||||||
sound-pitch: 3
|
sound-pitch: 3
|
||||||
|
|
||||||
# -= Sound volume =-
|
|
||||||
sound-volume: 2
|
sound-volume: 2
|
||||||
|
|
||||||
# -= Default values =-
|
# -= Default values =-
|
||||||
# This is a list of all options and defaults.
|
|
||||||
default-values:
|
default-values:
|
||||||
main:
|
main:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
@ -456,39 +247,33 @@ default-values:
|
||||||
|
|
||||||
play:
|
play:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
single:
|
single:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
spectator:
|
spectator:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
community:
|
community:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
leaderboards:
|
leaderboards:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
settings:
|
settings:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
lang:
|
lang:
|
||||||
enabled: true
|
enabled: true
|
||||||
default: en
|
default: 'en'
|
||||||
|
|
||||||
chat:
|
chat:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
parkour_settings:
|
parkour_settings:
|
||||||
|
|
||||||
item:
|
item:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
items:
|
items:
|
||||||
|
|
||||||
styles:
|
styles:
|
||||||
enabled: true
|
enabled: true
|
||||||
default: "red"
|
default: 'red'
|
||||||
|
|
||||||
leads:
|
leads:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
@ -524,9 +309,7 @@ default-values:
|
||||||
|
|
||||||
lobby:
|
lobby:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
visibility:
|
visibility:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
player_management:
|
player_management:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue