mdbd/PLAN.md
loki5512344 53f3f6e9da Complete Stage 0: Project scaffold
- Fix build.gradle.kts: Java 21, Paper 1.20.6, ProtocolLib 5.3.0
- Add permissions to paper-plugin.yml
- Add ConfigManager with safe yaml loading (no overwrite)
- Add LocationsConfig for all game object coordinates
- Add GameConfig with all balance values
- Update mdbd.java with onEnable/onDisable + ConfigManager
- Mark Stage 0 complete in PLAN.md
2026-05-31 20:37:36 +02:00

332 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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<UUID, BasePlayer>
├── 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
- [ ] `GameState` enum
- [ ] `GameSession` — хранит игроков, фазу, таймер
- [ ] `Phase` interface
- [ ] `LobbyPhase` — ожидание, минимум 5 игроков, таймер 60сек
- [ ] `RoleAssigner` + `RoleQueue` — кто киллер
- [ ] `RoleAssignPhase` — телепорты, задержка 5сек
- [ ] `GameplayPhase` — заглушка
- [ ] `/dbd join`, `/dbd leave`, `/dbd forcestart`
### Этап 2: Игроки и состояния
- [ ] `BasePlayer`, `Survivor`, `Killer`
- [ ] `PlayerState` enum: HEALTHY, INJURED, DOWNED, HOOKED, DEAD, ESCAPED
- [ ] `StateMachine` — переходы с валидацией
- [ ] `PlayerManager` — map UUID -> BasePlayer
- [ ] `SpawnPosition` — телепорт из конфига
### Этап 3: Киллер (базовый)
- [ ] `KillerController` — основной класс
- [ ] `KillerAttack` — ЛКМ, кулдаун 2.5с, hitbox
- [ ] `HitValidator` — line of sight, расстояние
- [ ] `DamageHandler` — Healthy->Injured, Injured->Downed
- [ ] `KillerCarry` — подъём, перенос, wiggle progress
- [ ] `KillerMovement` — скорость 115%, замедление после удара
### Этап 4: Выживший (базовый)
- [ ] `SurvivorController`
- [ ] `SurvivorMovement` — sprint, exhaustion 3сек/5сек кулдаун
- [ ] `SurvivorHealing` — аптечка 10сек, другие 16сек, прогресс-бар
- [ ] Downed movement — crawl 30% скорости
### Этап 5: Генераторы
- [ ] `Generator` класс — прогресс, статус
- [ ] `GeneratorManager` — 7 штук, 5 нужно
- [ ] `GeneratorRepair` — зажать ПКМ, прогресс в ActionBar
- [ ] `SkillCheck` — логика QTE, успех/провал
- [ ] `SkillCheckUI` — Title-анимация, круг (текстом или картинкой)
- [ ] `GeneratorRegression` — откат 0.25%/сек, Kick 2.5%/сек 30сек
### Этап 6: Крюки
- [ ] `Hook` класс
- [ ] `HookManager` — все крюки, подвал
- [ ] `HookStage` — Stage 1 (60с), Stage 2 (60с)
- [ ] `HookStruggle` — skill check каждые 2с
- [ ] `HookRescue` — снятие 2сек
- [ ] `HookSacrifice` — смерть
- [ ] Счётчик крюков — 3 раза макс
### Этап 7: UI
- [ ] `ActionBar` — статус, прогресс-бары
- [ ] `ProgressBar` — [████░░░░░░] формат
- [ ] `Sidebar` — генераторы, живые
- [ ] `TitleUI` — начало игры, skill check, победа/поражение
- [ ] `StatusIcons` — ❤ 🩸 💀
### Этап 8: Паллеты и окна
- [ ] `Pallet` — standing/dropped/broken
- [ ] `PalletDrop` — ПКМ выжившим
- [ ] `PalletStun` — 2.5сек стан киллеру
- [ ] `PalletBreak` — зажать ПКМ 3сек
- [ ] `Window` — класс
- [ ] `WindowVault` — 1сек выживший, 1.5сек киллер
### Этап 9: Эндгейм
- [ ] `ExitGate` — открытие 20сек
- [ ] `GateManager` — 2 ворота
- [ ] `Hatch` — условие появления
- [ ] `HatchCondition` — формула: живые < починенные гены
- [ ] `HatchEscape` — прыжок = побег
- [ ] `EndgamePhase` — коллапс 120сек
### Этап 10: Предметы
- [ ] `ItemType` enum
- [ ] `BaseItem` interface
- [ ] `ItemMedkit`, `ItemFlashlight`, `ItemToolbox`, `ItemKey`, `ItemMap`
- [ ] `Chest` — 3сек открытие
- [ ] `ChestLoot` — весовая таблица
### Этап 11: Звуки и Terror Radius
- [ ] `SoundManager`
- [ ] `TerrorRadiusSound` — 3 уровня по расстоянию
- [ ] `KillerVision` — red stain частицы
- [ ] Звуки генераторов, взрывы
### Этап 12: Data (YAML -> SQLite)
- [ ] `DataStorage` interface
- [ ] `YamlStorage` — реализация
- [ ] `PlayerStats` — сохранение BP, матчей
- [ ] Статистика после матча
### Этап 13: Перки (отложено до стабильности)
- [ ] `IPerk` interface: onEquip, onTrigger, onRemove
- [ ] `PerkRegistry` — фабрика перков
- [ ] 4 перка выжившего (Self-Care, Dead Hard, Sprint Burst, Borrowed Time)
- [ ] 3 перка киллера (Hex: Ruin, Corrupt Intervention, BBQ)
- [ ] `Totem` + `TotemManager` — только с Hex
### Этап 14: Полировка
- [ ] Обработка дисконнекта
- [ ] Баланс скоростей
- [ ] Тест-раунды
- [ ] Оптимизация (проверка не каждый тик)
## Правила <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);
}
```