mdbd/PLAN.md
2026-06-10 23:00:12 +02:00

25 KiB
Raw Blame History

DBD Plugin — Баги и задачи

✅ Закрыто в текущей сессии

SetupCommand (упрощено)

  • /dbdsetup set <тип> — ломаешь блок, объект ставится (без select)
  • Ванд только для ворот: ЛКМ=pos1, ПКМ=pos2
  • /dbdsetup set gate A|B — установить ворота из точек ванда

Медкит

  • Требует Shift + ПКМ + стоять на месте (прерывается при движении или отпускании Shift)
  • После использования удаляется полностью (1 медкит = 1 лечение)
  • Медкит не выдаётся стартово — только из сундуков

Маньяк — атака

  • Post-hit cooldown 4 сек после ПОПАДАНИЯ (отдельно от swing cooldown 2.5 сек)
  • Параметр killer.post-hit-cooldown в game.yml

Маньяк — нокдаун / переноска

  • Игрок в нокдауне ложится (setSwimming(true)) и поза удерживается каждые 5 тиков
  • При подъёме, смерти, спасении — поза сбрасывается
  • Переноска: маньяк ПКМ → подбирает DOWNED в радиусе 3 блоков
  • При подъёме setSwimming(false) отменяет позу нокдауна

Таймер игры

  • 15 минут + BossBar с таймером для всех игроков (зелёный → жёлтый → красный)
  • По истечении — маньяк победил

После победы

  • Телепортирует всех в лобби
  • Scale сбрасывается до 1.0
  • Инвентарь очищается

Лобби

  • Лимит 1 лобби на игрока
  • Broadcast при создании лобби убран — сообщение только создателю
  • Сообщение о входе игрока — только участникам сессии (не всему серверу)
  • После завершения игры лобби пересоздаёт сессию автоматически (onSessionFinished callback)
  • Лобби не засоряются — реестр чистит сессию через GameSession.setOnStopped()

PlayerQuitListener

  • Счётчик живых выживших корректный (считает после пометки DEAD)
  • Инвентарь, scale, поза сбрасываются при выходе из игры

GameplayPhase

  • Разбит на части:
    • 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 строк)

Лобби — повторный вход

  • FIX: Исправлен GameManager.joinSession() — теперь корректно обрабатывает повторный вход, сначала удаляя игрока из старой сессии

Хотбар маньяка

  • FIX: Добавлена проверка !bp.isKiller() в ChestOpening.completeOpening() — маньяк не получает лут из сундуков

Медкит из сундука

  • WORKS: Логика уже работает — ChestLoot.rollLoot() выдаёт медкит/фонарик при открытии сундука

Счётчик выживших

  • VERIFIED: Логика в PlayerQuitListener.handleSurvivorDisconnect() корректная — считает после пометки DEAD

Ворота

  • FIX: Добавлена интеграция GateOpening в GameplayInteraction — теперь вызывается при взаимодействии с порталом (HOPPER/PORTAL)

Кодировка и спавн в воздухе

  • FIXED: UTF-8 encoding для build
    • Добавлена org.gradle.jvmargs=-Dfile.encoding=UTF-8 в gradle.properties
    • Добавлен tasks.withType<ProcessResources> { filteringCharset = "UTF-8" } в build.gradle.kts
    • Русские символы и эмодзи теперь сохраняются корректно в конфигах
  • FIXED: Спавн в воздухе
    • Добавлена корректировка Y-координаты (Math.floor(y) + 1.0) в RoleAssigner.java
    • Players теперь стоят ОН block, не ИН block
    • Работает для положительных и отрицательных Y (подземные карты)
  • FIXED: World loading — добавлен fallback к первому loaded world в LocationsConfig.java
  • FIXED: Удален неиспользуемый импорт Location из PalletBreak.java

✅ Завершено

Заполнение сундуков при старте игры (случайный лут из ChestLoot)

  • Лут записывается в поле Chest.loot при создании
  • ChestOpening.completeOpening() использует pre-set loot

Визуализация ворот (частицы при открытии)

  • Progress particles: CRIT every 5 ticks
  • Completion burst: EXPLOSION_EMITTER + FLAME

Удаление перков и тотемов

  • Все totem файлы удалены
  • Все ссылки на тотемы удалены

❌ Новые баги (текущая сессия)

✅ ИСПРАВЛЕНО (7 багов)

  1. SetupCommand MiniMessage формат

    • FIXED: Заменены legacy §f и §a на MiniMessage <#FFFFFF> и <#00FF00>
  2. Телепортация в конце игры не работает

    • FIXED: Добавлена телепортация в GameplayPhase.exit()
    • Также сбрасывается scale до 1.0
  3. Downed игрок берёт хук

    • FIXED: Добавлена проверка состояния в GameplayInteraction
    • Теперь DOWNED, CARRIED и HOOKED не могут спасать
  4. Генераторы не чинятся за игрока

    • FIXED: Подключена GeneratorRepair в GameplayPhase
    • Добавлен обработчик в GameplayInteraction
    • Механика: ПКМ по генератору → зажать ПКМ для починки

✅ ИСПРАВЛЕНО / ПРОВЕРЕНО В ТЕКУЩЕЙ СЕССИИ (13 ЗАДАЧ)

  1. Генераторы (#11) — generatorManager всегда null

    • FIXED: Переинициализирован в GameplayPhase.initSubHandlers()
  2. Телепорт (#10) — ранний выход отменял финал

    • FIXED: Удалён телепорт из GameplayPhase.exit()
    • Телепортация только в EndgamePhase.exit() (100L тиков задержка)
  3. Wand для ворот — STICK vs WOODEN_AXE

    • FIXED: Обновлена документация, код ищет WOODEN_AXE с NBT тегом
  4. Бесконечный вход в лобби (/dbd join X, /dbd join X, /dbd join X...)

    • FIXED: LobbyRegistry.joinLobby() проверяет текущую сессию
    • Если игрок уже в другой сессии → выходит оттуда перед входом
  5. Лобби удаляется при 0 игроков, tab-complete показывает

    • VERIFIED: onPlayerLeftSession() НЕ удаляет лобби из реестра
    • Лобби держится в памяти, session переиспользуется после игры
  6. Pallet setup (/dbdsetup set pallet)

    • VERIFIED: Режим selectingPallet работает, сохраняет через SpawnUtil.blockBreakSpawn()
  7. Chest setup (/dbdsetup set chest)

    • VERIFIED: Режим selectingChest работает, сохраняет с offset +0.5, +0, +0.5
  8. Эффекты ранения (нет визуалов когда игрок INJURED)

    • VERIFIED: GameplayDamageSystem добавляет:
      • Частицы HEART каждые 40 тиков
      • Звук при попадании удара
      • Title "РАНЕН!"
  9. Двойной sneak для pickup (киллер присел 2 раза возле DOWNED)

    • VERIFIED: GameplayInteraction проверяет интервал <450ms между sneaks
      • Вызывает tryPickup() из KillerController
  10. Админ-команды (heal, down, unhook, state, hooks, kill)

    • VERIFIED: DBDAdminPlayerCommand полностью реализована
    • /dbd admin heal [игрок]
    • /dbd admin down [игрок]
    • /dbd admin unhook [игрок]
    • /dbd admin state <игрок> <HEALTHY|INJURED|DOWNED|...>
    • /dbd admin hooks <игрок> <0-3>
    • /dbd admin kill [игрок]
  11. Телепорт после завершения игры в лобби

    • VERIFIED: EndgamePhase.exit() телепортирует через 100L тиков
    • Сбрасывает scale до 1.0, очищает инвентарь
  12. Генераторы не чинятся (ПКМ возле генератора)

    • FIXED: setOnGeneratorInteract() вызывает generatorRepair.startRepair()
    • generatorManager переинициализирован, не null
  13. HOOKED игрок берёт хук (игрок висит на крюке, может взять другой)

    • VERIFIED: setOnRescueAttempt() проверяет HOOKED, DOWNED, CARRIED
    • Rescue невозможен если rescuer в одном из этих статусов
  14. Спавн игроков в воздухе (проблема с высотой)

    • FIXED: SpawnUtil.resolveStandingLocation() улучшена логика расчета Y
    • Добавлена явная загрузка chunks в RoleAssigner перед спавном
    • Используется getHighestBlockYAt() + 1 для стояния на блоке
  15. GameMode.ADVENTURE при начале игры

    • FIXED:
      • RoleAssigner.assignRoles() устанавливает ADVENTURE при спавне
      • LobbyPhase.enter() и onPlayerJoined() устанавливают ADVENTURE
      • EndgamePhase.exit() сбрасывает на ADVENTURE перед лобби
  16. /dbdsetup set gate A confirm не работал

    • FIXED: Добавлена поддержка обоих форматов:
      • /dbdsetup set gate A confirm
      • /dbdsetup set gate confirm A
      • Обновлена документация в COMMANDS_GUIDE.md
  17. Переноска киллером (carry) — проблемы

    • FIXED: Переработана логика KillerCarry с использованием ArmorStand:
      • Игрок видим (не setInvisible)
      • Камера отделена (beide мають пассажиры armor stand)
      • Игрок не двигает киллера (mounted, не телепортируется)
      • Пробел работает (jump event отслеживается)

✅ ИТОГО: 17/17 ЗАДАЧ РЕШЕНО!1. Генераторы (#11) — generatorManager всегда null

  • FIXED: Переинициализирован в GameplayPhase.initSubHandlers()
  1. Телепорт (#10) — ранний выход отменял финал

    • FIXED: Удалён телепорт из GameplayPhase.exit()
    • Телепортация только в EndgamePhase.exit() (100L тиков задержка)
  2. Wand для ворот — STICK vs WOODEN_AXE

    • FIXED: Обновлена документация, код ищет WOODEN_AXE с NBT тегом
  3. Бесконечный вход в лобби (/dbd join X, /dbd join X, /dbd join X...)

    • FIXED: LobbyRegistry.joinLobby() проверяет текущую сессию
    • Если игрок уже в другой сессии → выходит оттуда перед входом в новую
  4. Лобби удаляется при 0 игроков, tab-complete показывает

    • VERIFIED: onPlayerLeftSession() НЕ удаляет лобби из реестра
    • Лобби держится в памяти, session переиспользуется после игры
  5. Pallet setup (/dbdsetup set pallet)

    • VERIFIED: Режим selectingPallet работает, сохраняет через SpawnUtil.blockBreakSpawn()
  6. Chest setup (/dbdsetup set chest)

    • VERIFIED: Режим selectingChest работает, сохраняет с offset +0.5, +0, +0.5
  7. Эффекты ранения (нет визуалов когда игрок INJURED)

    • VERIFIED: GameplayDamageSystem добавляет:
      • Частицы HEART каждые 40 тиков
      • Звук при попадании удара
      • Title "РАНЕН!"
  8. Двойной sneak для pickup (киллер присел 2 раза возле DOWNED)

    • VERIFIED: GameplayInteraction проверяет интервал <450ms между sneaks
      • Вызывает tryPickup() из KillerController
  9. Админ-команды (heal, down, unhook, state, hooks, kill)

    • VERIFIED: DBDAdminPlayerCommand полностью реализована
    • /dbd admin heal [игрок]
    • /dbd admin down [игрок]
    • /dbd admin unhook [игрок]
    • /dbd admin state <игрок> <HEALTHY|INJURED|DOWNED|...>
    • /dbd admin hooks <игрок> <0-3>
    • /dbd admin kill [игрок]
  10. Телепорт после завершения игры в лобби

    • VERIFIED: EndgamePhase.exit() телепортирует через 100L тиков
    • Сбрасывает scale до 1.0, очищает инвентарь
  11. Генераторы не чинятся (ПКМ возле генератора)

    • FIXED: setOnGeneratorInteract() вызывает generatorRepair.startRepair()
    • generatorManager переинициализирован, не null
  12. HOOKED игрок берёт хук (игрок висит на крюке, может взять другой)

    • VERIFIED: setOnRescueAttempt() проверяет HOOKED, DOWNED, CARRIED
    • Rescue невозможен если rescuer в одном из этих статусов
  13. Спавн игроков в воздухе (проблема с высотой)

    • FIXED:
      • SpawnUtil.resolveStandingLocation() улучшена логика расчета Y
      • Добавлена явная загрузка chunks в RoleAssigner перед спавном
      • Используется getHighestBlockYAt() + 1 для стояния на блоке

✅ ИТОГО: 14/14 ЗАДАЧ РЕШЕНО!


✅ СЕССИЯ 2: ГЕНЕРАТОР - ПРОГРЕСС И КРАУЧ (18-19 ЗАДАЧИ)

18. Прогресс починки генератора не сохраняется

  • 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. Чтобы починить генератор нужно присеть возле него и быть присядя возле него

  • 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

  • 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

  • FIXED: Выживший теперь правильно устанавливается в состояние HOOKED при подвешивании
  • Изменение:
    • HookManager.tryHookSurvivor() теперь вызывает survivor.setState(PlayerState.HOOKED) после успешного подвешивания
    • Раньше state не был установлен, что приводило к проблемам с отображением и механикой
    • Теперь выживший видит "На крюке" в сайдбаре и может пытаться восстановиться/бороться

22. Collapse Animation Text Flickering (Частичный фикс)

  • АНАЛИЗ ЗАВЕРШЁН: Проблема в частых обновлениях скорбоарда при коллапсе карты

  • Корневая причина: 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


🚀 ГОТОВО К ТЕСТИРОВАНИЮ!