Complete Stage 1: Core Game Loop

- Add GameState enum (LOBBY, ROLE_ASSIGN, IN_GAME, ENDING)
- Add Phase interface with enter/tick/exit/isComplete
- Add GameSession with tick-based phase machine
- Add GameEventBus for internal events
- Add GameManager for session lifecycle
- Add all phases: LobbyPhase, RoleAssignPhase, GameplayPhase, EndgamePhase
- Add role assignment: RoleAssigner, RoleQueue, SpawnPosition
- Add BasePlayer, Survivor, Killer, PlayerState
- Add DBDCommand with /dbd join/leave/create/forcestart/stop
- Update mdbd.java with GameManager and command registration
- Add command definition to paper-plugin.yml
- Mark Stage 1 complete in PLAN.md
This commit is contained in:
loki5512344 2026-05-31 20:43:40 +02:00
parent 53f3f6e9da
commit 82ed455cd2
20 changed files with 884 additions and 8 deletions

View file

@ -0,0 +1,31 @@
package dev.loki.phase;
import dev.loki.core.GameSession;
public class EndgamePhase implements Phase {
private int collapseTicks;
private boolean complete;
@Override
public void enter(GameSession session) {
collapseTicks = session.getConfig().getGame().getInt("endgame.collapse-seconds", 120) * 20;
complete = false;
}
@Override
public void tick(GameSession session) {
collapseTicks--;
if (collapseTicks <= 0) {
complete = true;
}
}
@Override
public void exit(GameSession session) {
}
@Override
public boolean isComplete() {
return complete;
}
}

View file

@ -0,0 +1,36 @@
package dev.loki.phase;
import dev.loki.core.GameSession;
import org.bukkit.Bukkit;
public class GameplayPhase implements Phase {
private int gameTicks;
private boolean shouldEnd;
@Override
public void enter(GameSession session) {
Bukkit.broadcastMessage("[DBD] Игра началась! Выжившие, чините генераторы!");
gameTicks = 0;
shouldEnd = false;
}
@Override
public void tick(GameSession session) {
gameTicks++;
// TODO: Check endgame conditions
}
@Override
public void exit(GameSession session) {
Bukkit.broadcastMessage("[DBD] Игра завершена!");
}
@Override
public boolean isComplete() {
return shouldEnd;
}
public void forceEnd() {
shouldEnd = true;
}
}

View file

@ -0,0 +1,74 @@
package dev.loki.phase;
import dev.loki.config.GameConfig;
import dev.loki.core.GameSession;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit;
public class LobbyPhase implements Phase {
private final GameConfig config;
private int countdown;
private int secondsLeft;
private boolean started;
public LobbyPhase(GameConfig config) {
this.config = config;
this.secondsLeft = config.getLobbyCountdown();
this.countdown = 0;
this.started = false;
}
@Override
public void enter(GameSession session) {
Bukkit.broadcast(Component.text("[DBD] Лобби открыто! Используйте /dbd join", NamedTextColor.GREEN));
}
@Override
public void tick(GameSession session) {
int playerCount = session.getPlayerCount();
int minPlayers = config.getMinPlayers();
if (playerCount < minPlayers) {
secondsLeft = config.getLobbyCountdown();
countdown = 0;
started = false;
return;
}
countdown++;
if (countdown >= 20) {
countdown = 0;
secondsLeft--;
if (secondsLeft <= 5 || secondsLeft % 10 == 0) {
Bukkit.broadcast(Component.text(
"[DBD] До начала: " + secondsLeft + " сек. (" + playerCount + "/" + minPlayers + ")",
NamedTextColor.YELLOW));
}
}
if (secondsLeft <= 0) {
started = true;
}
}
@Override
public void exit(GameSession session) {
Bukkit.broadcast(Component.text("[DBD] Игра начинается!", NamedTextColor.GREEN));
}
@Override
public boolean isComplete() {
return started;
}
public void forceStart() {
secondsLeft = 0;
started = true;
}
public int getSecondsLeft() {
return secondsLeft;
}
}

View file

@ -0,0 +1,10 @@
package dev.loki.phase;
import dev.loki.core.GameSession;
public interface Phase {
void enter(GameSession session);
void tick(GameSession session);
void exit(GameSession session);
boolean isComplete();
}

View file

@ -0,0 +1,40 @@
package dev.loki.phase;
import dev.loki.core.GameSession;
import dev.loki.role.RoleAssigner;
import org.bukkit.Bukkit;
public class RoleAssignPhase implements Phase {
private final RoleAssigner assigner;
private int ticksLeft;
private boolean complete;
public RoleAssignPhase(RoleAssigner assigner) {
this.assigner = assigner;
this.complete = false;
}
@Override
public void enter(GameSession session) {
ticksLeft = session.getConfig().getRoleAssignDelay() * 20;
assigner.assignRoles(session);
}
@Override
public void tick(GameSession session) {
ticksLeft--;
if (ticksLeft <= 0) {
complete = true;
}
}
@Override
public void exit(GameSession session) {
Bukkit.broadcastMessage("[DBD] Роли назначены!");
}
@Override
public boolean isComplete() {
return complete;
}
}