# DBD Plugin — План разработки ## Архитектурные принципы - **KISS**: Нет абстракций ради абстракций. Простые классы с одной ответственностью. - **DRY**: Общая логика в утилитах, не копипаста. - **SOLID**: - SRP: Один класс = одна задача (StateManager только состояния, DamageHandler только урон) - OCP: Перки через интерфейс, не if-else везде - LSP: KillerController и SurvivorController наследуются от PlayerController корректно - ISP: Маленькие интерфейсы (IRepairable, IHealable, IHookable) - DIP: Высокоуровневые модули зависят от абстракций, не от имплементаций - max 150 строк/файл ## Структура папок (max 150 строк/файл) ``` src/main/java/com/dbd/plugin/ ├── DBDPlugin.java # Точка входа (max 50 строк) ├── config/ │ ├── ConfigManager.java # Загрузка всех yaml │ ├── LocationsConfig.java # Координаты объектов │ └── GameConfig.java # Балансные цифры ├── core/ │ ├── GameManager.java # Главный контроллер игр │ ├── GameSession.java # Одна игра (lobby -> end) │ ├── GameState.java # Enum: LOBBY, IN_GAME, ENDING │ └── GameEventBus.java # Внутренние события игры ├── phase/ │ ├── Phase.java # Interface: enter(), tick(), exit() │ ├── LobbyPhase.java # Ожидание игроков │ ├── RoleAssignPhase.java # Назначение ролей, таймер 5сек │ ├── GameplayPhase.java # Основная игра │ └── EndgamePhase.java # Эндгейм коллапс + результаты ├── player/ │ ├── BasePlayer.java # UUID, Player объект │ ├── Survivor.java # Данные выжившего │ ├── Killer.java # Данные киллера │ ├── PlayerState.java # Enum: HEALTHY, INJURED, DOWNED... │ └── PlayerManager.java # Map ├── state/ │ ├── StateMachine.java # Машина состояний игрока │ ├── StateTransition.java # Проверка можно ли перейти │ └── StateHandler.java # Обработчик изменений ├── role/ │ ├── RoleAssigner.java # Логика выбора кто киллер │ ├── RoleQueue.java # Очередь на киллера │ └── SpawnPosition.java # Спавн-точки из конфига ├── survivor/ │ ├── SurvivorController.java # Действия выжившего │ ├── SurvivorMovement.java # Sprint, Exhaustion │ ├── SurvivorHealing.java # Лечение себя/других │ └── SurvivorInventory.java # Предметы в руках ├── killer/ │ ├── KillerController.java # Действия киллера │ ├── KillerAttack.java # ЛКМ, кулдаун, hit detection │ ├── KillerCarry.java # Подъём, перенос, wiggle │ └── KillerVision.java # Terror radius, red stain ├── damage/ │ ├── DamageHandler.java # Нанесение урона (Healthy->Injured...) │ ├── AttackListener.java # Слушатель ЛКМ киллера │ └── HitValidator.java # Line of sight, range check ├── objective/ │ ├── Generator.java # Один генератор │ ├── GeneratorManager.java # Все 7 генераторов │ ├── GeneratorRepair.java # Логика починки │ ├── GeneratorRegression.java # Откат прогресса │ ├── SkillCheck.java # QTE система │ └── SkillCheckUI.java # Title-анимация ├── hook/ │ ├── Hook.java # Один крюк │ ├── HookManager.java # Все крюки │ ├── HookStage.java # Stage 1, Stage 2 │ ├── HookStruggle.java # Skill checks на Stage 2 │ ├── HookRescue.java # Спасание с крюка │ └── HookSacrifice.java # Смерть после Stage 2 ├── pallet/ │ ├── Pallet.java # Один паллет │ ├── PalletManager.java # Все паллеты │ ├── PalletDrop.java # Выживший бросает │ ├── PalletStun.java # Стан киллера │ └── PalletBreak.java # Киллер ломает ├── window/ │ ├── Window.java # Одно окно │ ├── WindowManager.java # Все окна │ ├── WindowVault.java # Прыжок через окно │ └── WindowFastVault.java # Быстрый/медленный волт ├── gate/ │ ├── ExitGate.java # Одни ворота │ ├── GateManager.java # 2 ворота │ └── GateOpening.java # 20 сек открытие ├── hatch/ │ ├── Hatch.java # Люк │ ├── HatchCondition.java # Условие появления │ └── HatchEscape.java # Прыжок в люк ├── item/ │ ├── ItemType.java # Enum: MEDKIT, FLASHLIGHT... │ ├── BaseItem.java # Interface предмета │ ├── ItemMedkit.java # Аптечка │ ├── ItemFlashlight.java # Фонарик │ ├── ItemToolbox.java # Ящик инструментов │ ├── ItemKey.java # Ключ от люка │ ├── ItemMap.java # Карта │ └── ChestLoot.java # Лут из сундуков ├── chest/ │ ├── Chest.java # Сундук │ ├── ChestManager.java # Все сундуки │ └── ChestOpening.java # 3 сек открытие ├── totem/ │ ├── Totem.java # Тотем │ ├── TotemManager.java # 5 тотемов │ ├── DullTotem.java # Обычный тотем │ └── HexTotem.java # Проклятый (с перком) ├── perk/ │ ├── IPerk.java # Интерфейс перка │ ├── PerkType.java # Enum: SURVIVOR, KILLER │ ├── PerkRegistry.java # Map всех перков │ ├── survivor/ │ │ ├── SelfCarePerk.java │ │ ├── DeadHardPerk.java │ │ ├── SprintBurstPerk.java │ │ └── BorrowedTimePerk.java │ └── killer/ │ ├── HexRuinPerk.java │ ├── CorruptInterventionPerk.java │ └── BBQChiliPerk.java ├── ui/ │ ├── ActionBar.java # Нижняя полоска │ ├── Sidebar.java # Scoreboard │ ├── TitleUI.java # Title/Subtitle │ ├── ProgressBar.java # [████░░░░░░] 40% │ └── StatusIcons.java # ❤ 🩸 💀 ├── sound/ │ ├── SoundManager.java # Воспроизведение звуков │ ├── TerrorRadiusSound.java # Сердцебиение │ ├── GeneratorSound.java # Звуки генератора │ └── SoundLevels.java # 3 уровня громкости ├── util/ │ ├── LocationUtil.java # Dist, line of sight │ ├── PlayerUtil.java # Is sneaking, sprinting │ ├── TimeUtil.java # Форматирование секунд │ ├── MathUtil.java # Clamp, lerp │ └── ParticleUtil.java # Спавн частиц ├── command/ │ ├── DBDCommand.java # /dbd главная │ ├── JoinSubcommand.java # /dbd join │ ├── LeaveSubcommand.java # /dbd leave │ ├── SetupSubcommand.java # /dbd setgen, sethook... │ ├── AdminSubcommand.java # /dbd forcestart, stop │ └── StatsSubcommand.java # /dbd stats ├── listener/ │ ├── PlayerQuitListener.java # Дисконнект во время игры │ ├── PlayerInteractListener.java # ПКМ, ЛКМ │ ├── PlayerMoveListener.java # Движение, ползание │ └── DamageListener.java # Отмена ванильного урона ├── data/ │ ├── DataStorage.java # Interface: save(), load() │ ├── YamlStorage.java # YAML реализация │ ├── SQLiteStorage.java # SQLite реализация (позже) │ ├── PlayerStats.java # Статистика игрока │ └── MatchResult.java # Результат матча └── exception/ ├── DBDException.java # Базовое исключение ├── InvalidLocationException.java └── InvalidStateException.java ``` ## TODO (по порядку) ### Этап 0: Скелет проекта - [x] Создать `build.gradle` (Paper 1.20.6, Java 21, ProtocolLib) - [x] `plugin.yml` с пермишнами - [x] `DBDPlugin.java` — onEnable/onDisable - [x] `ConfigManager` — загрузка yaml без перезаписи - [x] `LocationsConfig` — структура для всех координат - [x] `GameConfig` — балансные цифры ### Этап 1: Core Game Loop - [x] `GameState` enum - [x] `GameSession` — хранит игроков, фазу, таймер - [x] `Phase` interface - [x] `LobbyPhase` — ожидание, минимум 5 игроков, таймер 60сек - [x] `RoleAssigner` + `RoleQueue` — кто киллер - [x] `RoleAssignPhase` — телепорты, задержка 5сек - [x] `GameplayPhase` — заглушка - [x] `/dbd join`, `/dbd leave`, `/dbd forcestart` ### Этап 2: Игроки и состояния - [x] `BasePlayer`, `Survivor`, `Killer` - [x] `PlayerState` enum: HEALTHY, INJURED, DOWNED, HOOKED, DEAD, ESCAPED - [x] `StateMachine` — переходы с валидацией - [x] `PlayerManager` — map UUID -> BasePlayer - [x] `SpawnPosition` — телепорт из конфига ### Этап 3: Киллер (базовый) - [x] `KillerController` — основной класс - [x] `KillerAttack` — ЛКМ, кулдаун 2.5с, hitbox - [x] `HitValidator` — line of sight, расстояние - [x] `DamageHandler` — Healthy->Injured, Injured->Downed - [x] `KillerCarry` — подъём, перенос, wiggle progress - [x] `KillerMovement` — скорость 115%, замедление после удара ### Этап 4: Выживший (базовый) - [x] `SurvivorController` - [x] `SurvivorMovement` — sprint, exhaustion 3сек/5сек кулдаун - [x] `SurvivorHealing` — аптечка 10сек, другие 16сек, прогресс-бар - [x] Downed movement — crawl 30% скорости ### Этап 5: Генераторы - [x] `Generator` класс — прогресс, статус - [x] `GeneratorManager` — 7 штук, 5 нужно - [x] `GeneratorRepair` — зажать ПКМ, прогресс в ActionBar - [x] `SkillCheck` — логика QTE, успех/провал - [x] `SkillCheckUI` — Title-анимация, круг (текстом или картинкой) - [x] `GeneratorRegression` — откат 0.25%/сек, Kick 2.5%/сек 30сек ### Этап 6: Крюки - [x] `Hook` класс - [x] `HookManager` — все крюки, подвал - [x] `HookStage` — Stage 1 (60с), Stage 2 (60с) - [x] `HookStruggle` — skill check каждые 2с - [x] `HookRescue` — снятие 2сек - [x] `HookSacrifice` — смерть - [x] Счётчик крюков — 3 раза макс ### Этап 7: UI - [x] `ActionBar` — статус, прогресс-бары - [x] `ProgressBar` — [████░░░░░░] формат - [x] `Sidebar` — генераторы, живые - [x] `TitleUI` — начало игры, skill check, победа/поражение - [x] `StatusIcons` — ❤ 🩸 💀 ### Этап 8: Паллеты и окна - [x] `Pallet` — standing/dropped/broken - [x] `PalletDrop` — ПКМ выжившим - [x] `PalletStun` — 2.5сек стан киллеру - [x] `PalletBreak` — зажать ПКМ 3сек - [x] `Window` — класс - [x] `WindowVault` — 1сек выживший, 1.5сек киллер ### Этап 9: Эндгейм - [x] `ExitGate` — открытие 20сек - [x] `GateManager` — 2 ворота - [x] `Hatch` — условие появления - [x] `HatchCondition` — формула: живые < починенные гены - [x] `HatchEscape` — прыжок = побег - [x] `EndgamePhase` — коллапс 120сек ### Этап 10: Предметы - [x] `ItemType` enum - [x] `BaseItem` interface - [x] `ItemMedkit`, `ItemFlashlight`, `ItemToolbox`, `ItemKey`, `ItemMap` - [x] `Chest` — 3сек открытие - [x] `ChestLoot` — весовая таблица ### Этап 11: Звуки и Terror Radius - [x] `SoundManager` - [x] `TerrorRadiusSound` — 3 уровня по расстоянию - [x] `KillerVision` — red stain частицы - [x] Звуки генераторов, взрывы ### Этап 12: Data (YAML -> SQLite) - [x] `DataStorage` interface - [x] `YamlStorage` — реализация - [x] `SQLiteStorage` — заглушка - [x] `PlayerStats` — сохранение BP, матчей - [x] `MatchResult` — результат матча ### Этап 13: Перки (отложено до стабильности) - [x] `IPerk` interface: onEquip, onTrigger, onRemove - [x] `PerkRegistry` — фабрика перков - [x] 4 перка выжившего (Self-Care, Dead Hard, Sprint Burst, Borrowed Time) - [x] 3 перка киллера (Hex: Ruin, Corrupt Intervention, BBQ) - [x] `Totem` + `TotemManager` — только с Hex ### Этап 14: Полировка - [x] Обработка дисконнекта - [x] Баланс скоростей - [x] Утилиты (LocationUtil, PlayerUtil, TimeUtil, MathUtil, ParticleUtil) - [x] Оптимизация (проверка не каждый тик) ## Правила <150 строк на файл ```java // ✅ Правильно: Controller делегирует public class KillerController { private final KillerAttack attack; private final KillerCarry carry; private final KillerMovement movement; public void onLeftClick(Player target) { attack.tryAttack(target); } } // ❌ Неправильно: всё в одном классе public class KillerController { // 500 строк логики атаки, переноса, движения... } ``` ## Ключевые интерфейсы ### IPerk ```java public interface IPerk { String getId(); String getName(); PerkType getType(); // SURVIVOR or KILLER void onEquip(BasePlayer player); void onTrigger(BasePlayer player, PerkTrigger trigger); void onRemove(BasePlayer player); } ``` ### Phase ```java public interface Phase { void enter(GameSession session); void tick(GameSession session); // каждую секунду void exit(GameSession session); boolean isComplete(); } ``` ### DataStorage ```java public interface DataStorage { void saveStats(UUID player, PlayerStats stats); PlayerStats loadStats(UUID player); void saveMatch(MatchResult result); } ```