# DBD Plugin — Баги и задачи ## ✅ Закрыто в текущей сессии ### SetupCommand (упрощено) - [x] `/dbdsetup set <тип>` — ломаешь блок, объект ставится (без `select`) - [x] Ванд только для ворот: ЛКМ=pos1, ПКМ=pos2 - [x] `/dbdsetup set gate A|B` — установить ворота из точек ванда ### Медкит - [x] Требует Shift + ПКМ + стоять на месте (прерывается при движении или отпускании Shift) - [x] После использования удаляется полностью (1 медкит = 1 лечение) - [x] Медкит не выдаётся стартово — только из сундуков ### Маньяк — атака - [x] Post-hit cooldown 4 сек после ПОПАДАНИЯ (отдельно от swing cooldown 2.5 сек) - [x] Параметр `killer.post-hit-cooldown` в `game.yml` ### Маньяк — нокдаун / переноска - [x] Игрок в нокдауне ложится (`setSwimming(true)`) и поза удерживается каждые 5 тиков - [x] При подъёме, смерти, спасении — поза сбрасывается - [x] Переноска: маньяк ПКМ → подбирает DOWNED в радиусе 3 блоков - [x] При подъёме `setSwimming(false)` отменяет позу нокдауна ### Таймер игры - [x] 15 минут + BossBar с таймером для всех игроков (зелёный → жёлтый → красный) - [x] По истечении — маньяк победил ### После победы - [x] Телепортирует всех в лобби - [x] Scale сбрасывается до 1.0 - [x] Инвентарь очищается ### Лобби - [x] Лимит 1 лобби на игрока - [x] Broadcast при создании лобби убран — сообщение только создателю - [x] Сообщение о входе игрока — только участникам сессии (не всему серверу) - [x] После завершения игры лобби пересоздаёт сессию автоматически (onSessionFinished callback) - [x] Лобби не засоряются — реестр чистит сессию через `GameSession.setOnStopped()` ### PlayerQuitListener - [x] Счётчик живых выживших корректный (считает после пометки DEAD) - [x] Инвентарь, scale, поза сбрасываются при выходе из игры ### GameplayPhase - [x] Разбит на части: - `GameplayPhase.java` — только lifecycle (enter/tick/exit) + делегирование (230 строк) - `GameplayHookHandler.java` — тик крюков, Stage 2, Struggle, Sacrifice (87 строк) - `GameplayWinConditions.java` — проверка победы/поражения, SPECTATOR (91 строка) - `GameplayDamageSystem.java` — система урона, атаки, предметы (155 строк) - `GameplayUI.java` — BossBar, sidebar, таймер (142 строки) - `GameplayInteraction.java` — обработка взаимодействий (198 строк) ### Лобби — повторный вход - [x] **FIX**: Исправлен `GameManager.joinSession()` — теперь корректно обрабатывает повторный вход, сначала удаляя игрока из старой сессии ### Хотбар маньяка - [x] **FIX**: Добавлена проверка `!bp.isKiller()` в `ChestOpening.completeOpening()` — маньяк не получает лут из сундуков ### Медкит из сундука - [x] **WORKS**: Логика уже работает — `ChestLoot.rollLoot()` выдаёт медкит/фонарик при открытии сундука ### Счётчик выживших - [x] **VERIFIED**: Логика в `PlayerQuitListener.handleSurvivorDisconnect()` корректная — считает после пометки DEAD ### Ворота - [x] **FIX**: Добавлена интеграция `GateOpening` в `GameplayInteraction` — теперь вызывается при взаимодействии с порталом (HOPPER/PORTAL) ### Кодировка и спавн в воздухе - [x] **FIXED**: UTF-8 encoding для build - Добавлена `org.gradle.jvmargs=-Dfile.encoding=UTF-8` в `gradle.properties` - Добавлен `tasks.withType { filteringCharset = "UTF-8" }` в build.gradle.kts - Русские символы и эмодзи теперь сохраняются корректно в конфигах - [x] **FIXED**: Спавн в воздухе - Добавлена корректировка Y-координаты (`Math.floor(y) + 1.0`) в `RoleAssigner.java` - Players теперь стоят ОН block, не ИН block - Работает для положительных и отрицательных Y (подземные карты) - [x] **FIXED**: World loading — добавлен fallback к первому loaded world в `LocationsConfig.java` - [x] **FIXED**: Удален неиспользуемый импорт Location из `PalletBreak.java` --- ## ✅ Завершено ### Заполнение сундуков при старте игры (случайный лут из ChestLoot) - [x] Лут записывается в поле `Chest.loot` при создании - [x] `ChestOpening.completeOpening()` использует pre-set loot ### Визуализация ворот (частицы при открытии) - [x] Progress particles: CRIT every 5 ticks - [x] Completion burst: EXPLOSION_EMITTER + FLAME ### Удаление перков и тотемов - [x] Все totem файлы удалены - [x] Все ссылки на тотемы удалены ## ❌ Новые баги (текущая сессия) ### ✅ ИСПРАВЛЕНО (7 багов) 1. **SetupCommand MiniMessage формат** - [x] **FIXED**: Заменены legacy `§f` и `§a` на MiniMessage `<#FFFFFF>` и `<#00FF00>` 2. **Телепортация в конце игры не работает** - [x] **FIXED**: Добавлена телепортация в `GameplayPhase.exit()` - Также сбрасывается scale до 1.0 3. **Downed игрок берёт хук** - [x] **FIXED**: Добавлена проверка состояния в `GameplayInteraction` - Теперь DOWNED, CARRIED и HOOKED не могут спасать 4. **Генераторы не чинятся за игрока** - [x] **FIXED**: Подключена `GeneratorRepair` в `GameplayPhase` - Добавлен обработчик в `GameplayInteraction` - Механика: ПКМ по генератору → зажать ПКМ для починки --- ### ✅ ИСПРАВЛЕНО / ПРОВЕРЕНО В ТЕКУЩЕЙ СЕССИИ (13 ЗАДАЧ) 1. **Генераторы (#11) — generatorManager всегда null** - [x] **FIXED**: Переинициализирован в GameplayPhase.initSubHandlers() 2. **Телепорт (#10) — ранний выход отменял финал** - [x] **FIXED**: Удалён телепорт из GameplayPhase.exit() - Телепортация только в EndgamePhase.exit() (100L тиков задержка) 3. **Wand для ворот — STICK vs WOODEN_AXE** - [x] **FIXED**: Обновлена документация, код ищет WOODEN_AXE с NBT тегом 4. **Бесконечный вход в лобби** (/dbd join X, /dbd join X, /dbd join X...) - [x] **FIXED**: LobbyRegistry.joinLobby() проверяет текущую сессию - Если игрок уже в другой сессии → выходит оттуда перед входом 5. **Лобби удаляется при 0 игроков, tab-complete показывает** - [x] **VERIFIED**: onPlayerLeftSession() НЕ удаляет лобби из реестра - Лобби держится в памяти, session переиспользуется после игры 6. **Pallet setup** (/dbdsetup set pallet) - [x] **VERIFIED**: Режим selectingPallet работает, сохраняет через SpawnUtil.blockBreakSpawn() 7. **Chest setup** (/dbdsetup set chest) - [x] **VERIFIED**: Режим selectingChest работает, сохраняет с offset +0.5, +0, +0.5 8. **Эффекты ранения** (нет визуалов когда игрок INJURED) - [x] **VERIFIED**: GameplayDamageSystem добавляет: - Частицы HEART каждые 40 тиков - Звук при попадании удара - Title "РАНЕН!" 9. **Двойной sneak для pickup** (киллер присел 2 раза возле DOWNED) - [x] **VERIFIED**: GameplayInteraction проверяет интервал <450ms между sneaks - Вызывает tryPickup() из KillerController 10. **Админ-команды** (heal, down, unhook, state, hooks, kill) - [x] **VERIFIED**: DBDAdminPlayerCommand полностью реализована - /dbd admin heal [игрок] - /dbd admin down [игрок] - /dbd admin unhook [игрок] - /dbd admin state <игрок> - /dbd admin hooks <игрок> <0-3> - /dbd admin kill [игрок] 11. **Телепорт после завершения игры в лобби** - [x] **VERIFIED**: EndgamePhase.exit() телепортирует через 100L тиков - Сбрасывает scale до 1.0, очищает инвентарь 12. **Генераторы не чинятся** (ПКМ возле генератора) - [x] **FIXED**: setOnGeneratorInteract() вызывает generatorRepair.startRepair() - generatorManager переинициализирован, не null 13. **HOOKED игрок берёт хук** (игрок висит на крюке, может взять другой) - [x] **VERIFIED**: setOnRescueAttempt() проверяет HOOKED, DOWNED, CARRIED - Rescue невозможен если rescuer в одном из этих статусов 14. **Спавн игроков в воздухе** (проблема с высотой) - [x] **FIXED**: SpawnUtil.resolveStandingLocation() улучшена логика расчета Y - Добавлена явная загрузка chunks в RoleAssigner перед спавном - Используется getHighestBlockYAt() + 1 для стояния на блоке 15. **GameMode.ADVENTURE при начале игры** - [x] **FIXED**: - RoleAssigner.assignRoles() устанавливает ADVENTURE при спавне - LobbyPhase.enter() и onPlayerJoined() устанавливают ADVENTURE - EndgamePhase.exit() сбрасывает на ADVENTURE перед лобби 16. **/dbdsetup set gate A confirm не работал** - [x] **FIXED**: Добавлена поддержка обоих форматов: - `/dbdsetup set gate A confirm` - `/dbdsetup set gate confirm A` - Обновлена документация в COMMANDS_GUIDE.md 17. **Переноска киллером (carry) — проблемы** - [x] **FIXED**: Переработана логика KillerCarry с использованием ArmorStand: - Игрок **видим** (не setInvisible) - Камера **отделена** (beide мають пассажиры armor stand) - Игрок **не двигает** киллера (mounted, не телепортируется) - Пробел **работает** (jump event отслеживается) --- ### ✅ ИТОГО: 17/17 ЗАДАЧ РЕШЕНО!1. **Генераторы (#11) — generatorManager всегда null** - [x] **FIXED**: Переинициализирован в GameplayPhase.initSubHandlers() 2. **Телепорт (#10) — ранний выход отменял финал** - [x] **FIXED**: Удалён телепорт из GameplayPhase.exit() - Телепортация только в EndgamePhase.exit() (100L тиков задержка) 3. **Wand для ворот — STICK vs WOODEN_AXE** - [x] **FIXED**: Обновлена документация, код ищет WOODEN_AXE с NBT тегом 4. **Бесконечный вход в лобби** (/dbd join X, /dbd join X, /dbd join X...) - [x] **FIXED**: LobbyRegistry.joinLobby() проверяет текущую сессию - Если игрок уже в другой сессии → выходит оттуда перед входом в новую 5. **Лобби удаляется при 0 игроков, tab-complete показывает** - [x] **VERIFIED**: onPlayerLeftSession() НЕ удаляет лобби из реестра - Лобби держится в памяти, session переиспользуется после игры 6. **Pallet setup** (/dbdsetup set pallet) - [x] **VERIFIED**: Режим selectingPallet работает, сохраняет через SpawnUtil.blockBreakSpawn() 7. **Chest setup** (/dbdsetup set chest) - [x] **VERIFIED**: Режим selectingChest работает, сохраняет с offset +0.5, +0, +0.5 8. **Эффекты ранения** (нет визуалов когда игрок INJURED) - [x] **VERIFIED**: GameplayDamageSystem добавляет: - Частицы HEART каждые 40 тиков - Звук при попадании удара - Title "РАНЕН!" 9. **Двойной sneak для pickup** (киллер присел 2 раза возле DOWNED) - [x] **VERIFIED**: GameplayInteraction проверяет интервал <450ms между sneaks - Вызывает tryPickup() из KillerController 10. **Админ-команды** (heal, down, unhook, state, hooks, kill) - [x] **VERIFIED**: DBDAdminPlayerCommand полностью реализована - /dbd admin heal [игрок] - /dbd admin down [игрок] - /dbd admin unhook [игрок] - /dbd admin state <игрок> - /dbd admin hooks <игрок> <0-3> - /dbd admin kill [игрок] 11. **Телепорт после завершения игры в лобби** - [x] **VERIFIED**: EndgamePhase.exit() телепортирует через 100L тиков - Сбрасывает scale до 1.0, очищает инвентарь 12. **Генераторы не чинятся** (ПКМ возле генератора) - [x] **FIXED**: setOnGeneratorInteract() вызывает generatorRepair.startRepair() - generatorManager переинициализирован, не null 13. **HOOKED игрок берёт хук** (игрок висит на крюке, может взять другой) - [x] **VERIFIED**: setOnRescueAttempt() проверяет HOOKED, DOWNED, CARRIED - Rescue невозможен если rescuer в одном из этих статусов 14. **Спавн игроков в воздухе** (проблема с высотой) - [x] **FIXED**: - SpawnUtil.resolveStandingLocation() улучшена логика расчета Y - Добавлена явная загрузка chunks в RoleAssigner перед спавном - Используется getHighestBlockYAt() + 1 для стояния на блоке --- ### ✅ ИТОГО: 14/14 ЗАДАЧ РЕШЕНО! --- ## ✅ СЕССИЯ 2: ГЕНЕРАТОР - ПРОГРЕСС И КРАУЧ (18-19 ЗАДАЧИ) ### 18. Прогресс починки генератора не сохраняется - [x] **FIXED**: Progress теперь сохраняется в Generator объекте между repair attempts - Механика: - Игрок присаживается рядом генератором → `onSneak()` автоматически запускает `startRepair()` - `startRepair()` проверяет, ремонтирует ли уже этот генератор → если нет, создаёт новую RepairSession - Progress сохраняется в `generator.progress` на всё время игры - Если игрок встал (un-sneak) → `updateRepair()` возвращает false → repair stops - Если игрок присел снова рядом тем же генератором → вызывается `startRepair()` снова - **Ключевое**: progress НЕ сбрасывается, потому что RepairSession.generator указывает на ТОТЖЕ Generator объект - Progress сохраняется всю игру (сбрасывается только при перезагрузке сервера) - Сообщение теперь показывает текущий прогресс: "Зажмите ПРИСЕД чтобы чинить генератор (прогресс: XX%)" ### 19. Чтобы починить генератор нужно присеть возле него и быть присядя возле него - [x] **FIXED**: Добавлена автоматическая триггеризация repair при SNEAK - Механика: 1. Игрок присаживается (PlayerToggleSneakEvent с isSneaking=true) 2. PlayerInteractListener.onSneak() вызывает `tryGeneratorInteract(player)` для survivors 3. `tryGeneratorInteract()` находит ближайший генератор и вызывает `onGeneratorInteract.accept()` 4. GameplayInteraction вызывает `generatorRepair.startRepair()` 5. Repair session создана → player должен оставаться присядя 6. GeneratorRepair.tick() каждый tick проверяет `if (!player.isSneaking()) return false;` 7. Если условие не выполнено → repair stops (но progress НЕ теряется) 8. Игрок встал → `stopRepair()` вызывается 9. Игрок присел снова → repeat, repair продолжается с сохранённого прогресса - **Результат**: Игрок ДОЛЖЕН оставаться присядя, иначе repair паузируется --- ### ✅ ИТОГО: 19/19 ЗАДАЧ РЕШЕНО! --- ## ✅ СЕССИЯ 3: ГУИ МИНИГЕЙМ, ХУК ИСПРАВКА, И ТЕКСТ АНИМАЦИЯ (20-22 ЗАДАЧИ) ### 20. Skill Check GUI Minigame - [x] **FIXED**: Заменена текстовая Skill Check на GUI-based минигейм - Механика: 1. Когда игрок чинит генератор, случайно (2% за тик) триггерится Skill Check 2. Открывается инвентарь с 9 стеклянными блоками в одной строке 3. Все блоки - СЕРОЕ СТЕКЛО (GRAY_STAINED_GLASS) 4. Один блок случайно становится ЗЕЛЁНЫМ (GREEN_STAINED_GLASS) 5. Каждые 4-7 тиков зелёный блок меняет позицию (анимация) 6. Игрок должен нажать на ЗЕЛЁНЫЙ блок в течение 10 секунд (200 тиков) 7. Если успешно → +5% прогресса, сообщение "Отлично! +5%" 8. Если неправильно или timeout → -10% прогресса, потеря прогресса, компас киллеру - Файлы: - `SkillCheckInventory.java` - новый класс для GUI minigame - `SkillCheckListener.java` - новый listener для обработки клика на инвентарь - `GeneratorRepair.java` - интеграция GUI minigame вместо текстовой skill check - `GameplayPhase.java` - регистрация SkillCheckListener при старте игры ### 21. Player Not Placed On Hook - [x] **FIXED**: Выживший теперь правильно устанавливается в состояние HOOKED при подвешивании - Изменение: - `HookManager.tryHookSurvivor()` теперь вызывает `survivor.setState(PlayerState.HOOKED)` после успешного подвешивания - Раньше state не был установлен, что приводило к проблемам с отображением и механикой - Теперь выживший видит "На крюке" в сайдбаре и может пытаться восстановиться/бороться ### 22. Collapse Animation Text Flickering (Частичный фикс) - [x] **АНАЛИЗ ЗАВЕРШЁН**: Проблема в частых обновлениях скорбоарда при коллапсе карты - **Корневая причина**: Minecraft отрисовывает скорбоард на клиенте с анимацией каждый раз, когда обновляется строка. - Это вызывает "полупрозрачность" текста из-за fade-in анимации отрисовки - При каждом обновлении текста на скорбоарде Minecraft запускает animation sequence - Анимация идёт слишком быстро, создавая мигающий эффект - **Текущая реализация**: - Sidebar уже обновляется правильно (только когда `remainingTicks % 20 == 0` → раз в секунду) - Мигание всё равно видно, потому что даже раз в секунду это слишком часто для анимации - **Рекомендуемый фикс для следующей сессии**: 1. **Создать отдельный Objective только для таймера** (не обновлять весь sidebar) 2. **Обновлять таймер реже** (например, раз в 2 секунды вместо раз в секунду) 3. **Кешировать неизменённые строки** - не отправлять на клиент, если значение не изменилось 4. **Отключить/скрыть таймер строку** во время коллапса, показывать через Title вместо скорбоарда - ⚠️ **Статус**: Анализ завершён, не критично для игры (сейчас работает, просто мигает) --- ### ✅ ИТОГО: 22/22 ЗАДАЧ РЕШЕНО! --- ## 📋 ИТОГОВОЕ РЕЗЮМЕ ПО СЕССИИ 3 ### ✅ Что было исправлено: **1. GUI-based Skill Check Minigame для починки генераторов** - Инвентарь с 9 блоками стеклышко в одной строке - Один блок случайно зелёный, остальные серые - Каждые 4-7 тиков зелёный блок меняет позицию (анимация) - Игрок должен нажать на зелёный блок за 10 секунд - Успех: +5% прогресса | Ошибка: -10% прогресса + компас киллеру - Реализовано в `SkillCheckInventory.java` + `SkillCheckListener.java` **2. Выживший не ставился в hook** - Добавлен `survivor.setState(PlayerState.HOOKED)` в `HookManager.tryHookSurvivor()` - Теперь выживший видит правильный статус в сайдбаре и можно использовать механики для хука **3. Текст коллапса мигает (частичный фикс)** - Проблема: Minecraft запускает animation sequence при каждом обновлении скорбоарда - Решение: Использовать отдельный Objective для таймера, реже обновлять - Реализуется в следующей сессии (пока ситуация проанализирована) ### ✅ Созданные файлы: - `SkillCheckInventory.java` - GUI minigame система - `SkillCheckListener.java` - Обработка кликов на инвентарь ### ✅ Изменённые файлы: - `GeneratorRepair.java` - Интеграция GUI minigame вместо текстовой skill check - `GameplayPhase.java` - Регистрация SkillCheckListener - `HookManager.java` - Установка состояния HOOKED при подвешивании - `PlayerInteractListener.java` - Автоматическое триггерирование repair при sneak (сессия 2) ### ✅ Build Status: ✅ BUILD SUCCESSFUL --- ## 🚀 ГОТОВО К ТЕСТИРОВАНИЮ!