4.8 KiB
ZP1 Minimal Migration Plan
Goal
Rewrite zp1 into zp2, keeping only: room management, map loading, player movement, and minimal frontend display. Same tech stack (Java + Vite/Three.js), ECS architecture, client prediction.
Scope
- Keep: Room system, map loading/rendering, player movement (WASD), client prediction, WebSocket communication
- Strip: Zombies, weapons/bullets, turrets, fire zones, loots, explosions/effects, HUD, settings, map designer, template system, object pool
Phase 1: Backend Skeleton
1.1 Project structure
zp2/backend/
├── pom.xml
└── src/main/java/com/zombie/game/
├── GameServerMain.java
├── model/
│ ├── Constants.java
│ ├── Room.java
│ ├── PlayerInfo.java
│ ├── GameMap.java
│ ├── MapData.java
│ └── StaticWall.java
├── server/
│ ├── GameWebSocketServer.java
│ ├── RoomManager.java
│ ├── GameService.java
│ ├── GameLoop.java
│ ├── MessageUtils.java
│ └── MapStorage.java
├── ecs/
│ ├── ECSWorld.java
│ ├── System.java
│ └── components/
│ ├── Position.java
│ ├── PlayerInput.java
│ ├── Health.java
│ ├── Collision.java
│ └── RenderInfo.java
└── systems/
├── PlayerInputSystem.java
└── StateSyncSystem.java
1.2 Key changes
Constants.java — Keep GRID_SIZE, TICK_RATE, PLAYER_SIZE, PLAYER_SPEED, MSG_*. Remove zombie/weapon/loot constants.
GameMap.java — Keep loadFromJson(), isWall(), isWalkable(), getCells(), getSpawnPoints(). Remove FlowField entirely.
ECSWorld.java — Keep entities, players, playerIdToEntity, map, systems, lock. Remove zombies/bullets/loots/turrets/fireZones. Remove object pools. Keep createPlayerEntity() only.
GameService.java — Register only PlayerInputSystem + StateSyncSystem.
StateSyncSystem.java — Broadcast {players: [{id, x, y, angle, health}], gameTime} only.
GameWebSocketServer.java — Keep room CRUD + player input + state broadcast.
1.3 Map data
- Copy
maps/d540209a.json(walls + playerSpawns + zombieSpawns)
Phase 2: Frontend Skeleton
2.1 Project structure
zp2/frontend/
├── package.json
├── vite.config.js
├── index.html
└── src/
├── main.js
├── style.css
├── game/
│ ├── engine.js
│ └── scene.js
├── network/
│ └── client.js
├── ui/
│ └── lobby.js
└── utils/
├── constants.js
├── grid.js
└── input.js
2.2 Key changes
constants.js — Keep GRID_SIZE, PLAYER_SIZE, TICK_RATE, TICK_INTERVAL, PLAYER_CONFIG, MSG_TYPE. Remove WEAPONS, WEAPON_CONFIG, ZOMBIE_CONFIG.
grid.js — Keep Grid class (parseMap, isWall, worldToGrid, gridToWorld, isWalkable). Remove findPath, getSpawnPoints.
input.js — Keep attach/detach, getMovement, buildInputState (movement + aim only). Remove weapon bindings.
engine.js (~666→~250 lines) — Keep connect, loop, tick, local prediction, reconciliation. Strip zombie/bullet/loot/turret processing.
scene.js (~1331→~250 lines) — Keep constructor, lighting, buildMap, player rendering, camera, getMouseGroundPos. Remove zombie/bullet/effect/turret/loot rendering.
lobby.js — Keep as-is.
main.js — Keep lobby wiring + game transition. Remove HUD/settings.
style.css — Keep lobby + room + canvas styles. Remove HUD/weapon/kill-feed styles.
Phase 3: Cleanup & Verification
3.1 Message protocol
CREATE_ROOM/JOIN_ROOM/LEAVE_ROOM/READY/START_GAMEROOM_LIST/ROOM_STATE/GAME_STARTED/ERRORPLAYER_INPUT(dx, dy, aimX, aimY, seq)GAME_STATE(players only)
3.2 Test flow
mvn package && java -jar target/*.jarnpm run dev- Open two tabs → Create room → Join room → Start game
- Both players see each other move, WASD responsive, wall collision works
Files to Create (36 total)
| # | File | Source |
|---|---|---|
| 1-23 | Backend Java files (see 1.1) | Simplified from zp1 |
| 24-35 | Frontend JS/HTML/CSS (see 2.1) | Simplified from zp1 |
| 36 | maps/d540209a.json |
Copy from zp1 |
Key Decisions
| Decision | Choice | Reason |
|---|---|---|
| Tech stack | Java 17 + Vite + Three.js | Same as zp1 |
| ECS | Keep | Structure preserved |
| Client prediction | Keep | Better movement feel |
| Flow field | Remove | Zombie-only feature |
| HUD/Settings | Remove | Not in scope |