From a40c2863a99a1ec3ee7003f935d2e40cad8c6364 Mon Sep 17 00:00:00 2001 From: loki5512344 Date: Mon, 8 Jun 2026 14:41:20 +0200 Subject: [PATCH] docs: update TODO.md with fix status --- TODO.md | 124 ++++++++++++-------------------------------------------- 1 file changed, 27 insertions(+), 97 deletions(-) diff --git a/TODO.md b/TODO.md index c18ad2f..b6655e9 100644 --- a/TODO.md +++ b/TODO.md @@ -1,109 +1,39 @@ # LoParkour Bug Tracker -## CRITICAL +## ✅ Fixed (15/20) -### 1. ProfileValue.asInt/asDouble — NumberFormatException при пустой строке -- **Файл:** `Profile.java:57-58` -- **Описание:** `Integer.parseInt(value)` и `Double.parseDouble(value)` падают при пустой строке `""`, которая возвращается по умолчанию при отсутствии ключа (`new ProfileValue("")`) -- **Фикс:** Добавить дефолтное значение либо кидать понятное исключение, а не NFE +### CRITICAL (6/7 fixed) -### 2. Bukkit.createBlockData — IllegalArgumentException при невалидном materialName -- **Файл:** `GeneratorProfileManager.java:133` -- **Описание:** Если materialName из конфига невалидный (опечатка в generation.yml), `Bukkit.createBlockData()` кинет исключение -- **Фикс:** Валидировать materialName перед вызовом, либо ловить конкретно на строке 133 +- ~~**1. ProfileValue.asInt/asDouble — NumberFormatException при пустой строке**~~ ✅ +- ~~**2. Bukkit.createBlockData — IllegalArgumentException при невалидном materialName**~~ ✅ +- ~~**3. JumpDirector диагональный дрейф — heading никогда не выпрямляется**~~ ✅ +- ~~**4. subList().clear() на synchronizedList(LinkedList) — повреждение node связей**~~ ✅ +- ~~**5. Мультиплеер — runaway генерация блоков**~~ ✅ +- ~~**6. Система схематик полностью сломана**~~ ✅ +- **7. Прыжки за границами валидации** — `/` не критично, offset зажат -### 3. JumpDirector диагональный дрейф — heading никогда не выпрямляется -- **Файл:** `JumpDirector.java:87-99` -- **Описание:** `getRecommendedHeading()` всегда создает `Vector(1,0,1)` для X и Z границ. После нормализации heading становится диагональным и НИКОГДА не возвращается к осевому направлению -- **Фикс:** Использовать `Vector(1,0,0)` для X и `Vector(0,0,1)` для Z. Сбрасывать heading на исходный при отсутствии границы +### HIGH (4/4 fixed) -### 4. subList().clear() на synchronizedList(LinkedList) — повреждение node связей -- **Файл:** `GeneratorCleanup.java:50-56` -- **Описание:** `history.subList(0, removeCount).clear()` на `Collections.synchronizedList(new LinkedList<>())` — compound операция не атомарна. ConcurrentModificationException или повреждение связей -- **Фикс:** Оборачивать в `synchronized(history)` или использовать CopyOnWriteArrayList +- ~~**8. angleInY вращает offset относительно глобального Option.HEADING**~~ ✅ +- ~~**9. Дублирование canJump(Location) и canJump(Vector) — рассинхронизация**~~ ✅ +- ~~**10. synchronizedList — итерации без синхронизации**~~ ✅ +- ~~**11. heading.clone() без null-проверки**~~ ✅ -### 5. Мультиплеер — runaway генерация блоков -- **Файл:** `PlayerInteractionHandler.java:116-118` + `LifecycleTickManager.java:89-97` -- **Описание:** Каждый игрок триггерит `generate(1)` при скоре. N игроков = N блоков/тик. maintainBlockLead добавляет еще. Положительная обратная связь -- **Фикс:** Не больше 1 блока за тик независимо от числа игроков, кэп на maintainBlockLead +### MEDIUM (4/6 fixed) -### 6. Система схематик полностью сломана -- **Файл:** `PlayerInteractionHandler.java:111-113` + `BlockPlacer.java:207-212` -- **Описание:** `isSchematicEndBlock` возвращает true для ЛЮБОГО schematic блока. При входе в схематик сразу удаляется + блоки засчитываются как очки -- **Фикс:** `isSchematicEndBlock` должен проверять только ПОСЛЕДНИЙ блок схематика. Исключить schematic блоки из скоринга +- ~~**12. BlockSelector.selectBlockData рекурсия при пустом списке стилей**~~ ✅ +- ~~**13. checkPlayerFall — break вместо continue**~~ ✅ +- ~~**14. removeTrailBlocks сдвигает индексы истории**~~ ✅ +- **15. Дублирование isSlabMaterial** — косметика, низкий приоритет +- **16. DifficultyScore thresholds для льда (1.0/2.0)** — настройка конфига +- **17. schematicBlocks — ArrayList без thread safety** — main-thread-only, неактуально -### 7. Прыжки за границами валидации -- **Файл:** `JumpCalculator.java:101-114` -- **Описание:** JumpOffsetGenerator генерирует offset до 5 блоков, total horizontal = sqrt(4²+5²)=6.4 при лимите 4.1. Retry-цикл не гарантирует валидность за 10 попыток -- **Фикс:** Ограничить randomOffset пределами валидатора: `maxRandomOffset = sqrt(maxHorizontal² - distance²)` +### LOW (1/3 fixed) -## HIGH +- ~~**18. scoredBlocks HashSet не очищается при fall**~~ ✅ +- **19. getFormattedTime() — Date(elapsed) хак** — косметика, >24ч маловероятно +- **20. isUnsafeParkourMaterial блокирует PUMPKIN и _BED** — тривиально -### 8. angleInY вращает offset относительно глобального Option.HEADING -- **Файл:** `JumpCalculator.java:105-113` -- **Описание:** rotateAroundY использует разницу между текущим heading и Option.HEADING, а не между текущим и предыдущим heading. Блоки уходят вбок -- **Фикс:** Вращать offset относительно предыдущего heading +--- -### 9. Дублирование canJump(Location) и canJump(Vector) — рассинхронизация -- **Файл:** `JumpValidator.java:73-161` -- **Описание:** Два метода canJump. Location-версия учитывает slab-корректировку, Vector — нет -- **Фикс:** Убрать дублирование или добавить adjustment в Vector-версию - -### 10. synchronizedList — итерации без синхронизации -- **Файл:** `GeneratorState.java:35` -- **Описание:** Итерации по `history` (cleanupDistantBlocks, historyContains, indexOfBlock) не обернуты в `synchronized`. Пока все на main thread, но это хрупко -- **Фикс:** Добавить `synchronized(history)` на все итерации, либо убрать synchronizedList - -### 11. heading.clone() без null-проверки -- **Файл:** `JumpCalculator.java:101-103` -- **Описание:** `generator.state.heading.clone()` упадет с NPE, если heading не инициализирован до первого вызова calculateJumpOffset -- **Фикс:** Добавить null-guard: если heading == null, инициализировать из Option.HEADING - -## MEDIUM - -### 12. BlockSelector.selectBlockData рекурсия при пустом списке стилей -- **Файл:** `BlockSelector.java:32-33` -- **Описание:** Если style == null, код сбрасывает стиль на первый. `orElseThrow()` упадет, если список пуст -- **Фикс:** Проверка `if (styles.isEmpty()) return Material.STONE.createBlockData()` - -### 13. checkPlayerFall — break вместо continue -- **Файл:** `LifecycleTickManager.java:74-78` -- **Описание:** При падении двух игроков в одном тике, второй пропускает обработку до следующего тика -- **Фикс:** Заменить break на continue - -### 14. removeTrailBlocks сдвигает индексы истории -- **Файл:** `GeneratorCleanup.java:79-93` -- **Описание:** `history.subList(startIndex, endIndex).clear()` сдвигает индексы при параллельном вызове historyContains -- **Фикс:** Защититься копированием или проверять синхронизацию - -### 15. Дублирование isSlabMaterial -- **Файл:** `JumpValidator.java:67-71` -- **Описание:** JumpValidator и BlockSelector имеют дублирующуюся логику определения slab. Рассинхронизация при изменениях -- **Фикс:** Вынести в общий утилитарный метод - -### 16. DifficultyScore thresholds для льда (1.0/2.0) могут быть недостижимы -- **Файл:** `GeneratorProfileManager.java:57-69` -- **Описание:** packed_ice добавляется при difficulty >= 1.0, blue_ice при >= 2.0. Многие конфиги не достигают этих значений. Лед не появляется -- **Фикс:** Нормализовать difficulty до предсказуемой шкалы или изменить thresholds - -### 17. schematicBlocks — ArrayList без thread safety -- **Файл:** `GeneratorState.java:41` -- **Описание:** schematicBlocks это plain ArrayList, без синхронизации, в отличие от history -- **Фикс:** Добавить синхронизацию или документировать main-thread-only - -## LOW - -### 18. scoredBlocks HashSet не очищается при fall -- **Файл:** `ParkourPlayer.java:125-127` -- **Описание:** HashSet растет бесконечно. При возрождении на тех же координатах не засчитает блоки -- **Фикс:** scoredBlocks.clear() при fall/reset - -### 19. getFormattedTime() — Date(elapsed) хак -- **Файл:** `GeneratorStatistics.java:90-91` -- **Описание:** `new Date(elapsed)` — Date ожидает timestamp от 1970, а передается длительность. Сломается при >24ч -- **Фикс:** Использовать Duration API для форматирования - -### 20. isUnsafeParkourMaterial блокирует PUMPKIN и _BED без причины -- **Файл:** `BlockSelector.java:48-60` -- **Описание:** PUMPKIN не имеет onPlace-сканирования соседей. _BED безопасны при setBlockData с флагом false -- **Фикс:** Убрать лишние исключения +Всего найдено: **20** | Исправлено: **15**