mirror of
https://github.com/tiennm99/caro.git
synced 2026-05-20 03:25:48 +00:00
484 lines
17 KiB
Markdown
484 lines
17 KiB
Markdown
# Codebase Summary
|
|
|
|
## Directory Structure
|
|
|
|
```
|
|
caro/
|
|
├── .github/
|
|
│ └── workflows/
|
|
│ ├── build.yml CI: build + test
|
|
│ └── deploy-pages.yml CD: deploy web client to GitHub Pages
|
|
├── landlords-common/ Shared Java library (game logic, entities, protocol)
|
|
│ ├── src/main/java/org/nico/ratel/landlords/
|
|
│ │ ├── channel/ Netty utilities
|
|
│ │ ├── entity/ Data models (Board, Room, GameMove, etc.)
|
|
│ │ ├── enums/ Type definitions (ServerEventCode, ClientEventCode, etc.)
|
|
│ │ ├── exception/ Custom exceptions
|
|
│ │ ├── features/ Feature flags
|
|
│ │ ├── handler/ Protocol codec (Protobuf decoder)
|
|
│ │ ├── helper/ Game logic & utilities
|
|
│ │ ├── print/ Terminal formatting
|
|
│ │ ├── robot/ AI engine (GomokuAI)
|
|
│ │ ├── transfer/ Binary serialization (ByteKit, ByteLink)
|
|
│ │ └── utils/ General utilities (JSON, List, Options, Time)
|
|
│ ├── src/test/java/
|
|
│ │ ├── helper/tests/GomokuHelperTest.java
|
|
│ │ └── robot/tests/GomokuAITest.java
|
|
│ └── pom.xml
|
|
├── landlords-server/ Java Netty server (TCP + WebSocket)
|
|
│ ├── src/main/java/org/nico/ratel/landlords/server/
|
|
│ │ ├── event/ ServerEventListener_* handlers
|
|
│ │ ├── handler/ Netty pipeline handlers
|
|
│ │ ├── proxy/ Message sending (ProtobufProxy, WebsocketProxy)
|
|
│ │ ├── timer/ Background tasks (cleanup, heartbeat)
|
|
│ │ ├── SimpleServer.java Server entry point
|
|
│ │ ├── ServerContains.java Global state container
|
|
│ │ └── ... (event listeners)
|
|
│ ├── src/main/resources/
|
|
│ │ └── static/ Built-in web UI (index.html, CSS, JS, images)
|
|
│ ├── src/test/java/ (if any)
|
|
│ └── pom.xml
|
|
├── landlords-client/ Java CLI client
|
|
│ ├── src/main/java/org/nico/ratel/landlords/client/
|
|
│ │ ├── entity/ Client-specific entities
|
|
│ │ ├── event/ ClientEventListener_* handlers
|
|
│ │ ├── handler/ Protocol handlers
|
|
│ │ ├── proxy/ Message sending
|
|
│ │ └── SimpleClient.java CLI entry point
|
|
│ └── pom.xml
|
|
├── web-client/ Phaser 3 + Vite web client
|
|
│ ├── src/
|
|
│ │ ├── main.js Phaser boot
|
|
│ │ ├── config/
|
|
│ │ │ ├── game-config.js Phaser configuration
|
|
│ │ │ └── protocol-constants.js Event code enums
|
|
│ │ ├── scenes/
|
|
│ │ │ ├── boot-scene.js Initialize, connect to server
|
|
│ │ │ ├── menu-scene.js Menus (overlay DOM)
|
|
│ │ │ └── game-scene.js Main gameplay scene
|
|
│ │ ├── services/
|
|
│ │ │ ├── event-bus.js Pub/sub event dispatcher
|
|
│ │ │ ├── connection-service.js WebSocket client
|
|
│ │ │ └── game-state-service.js Client-side state
|
|
│ │ ├── objects/
|
|
│ │ │ ├── board.js Game board renderer
|
|
│ │ │ └── stone.js Individual stone sprite
|
|
│ │ └── ui/
|
|
│ │ ├── menu-ui.js Menu components
|
|
│ │ └── game-ui.js Game HUD & notifications
|
|
│ ├── index.html
|
|
│ ├── vite.config.js
|
|
│ ├── package.json
|
|
│ └── dist/ (build output)
|
|
├── docs/ (this directory)
|
|
│ ├── project-overview-pdr.md
|
|
│ ├── system-architecture.md
|
|
│ ├── codebase-summary.md
|
|
│ ├── code-standards.md
|
|
│ ├── deployment-guide.md
|
|
│ └── project-roadmap.md
|
|
├── plans/ (implementation plans)
|
|
├── pom.xml Maven parent POM
|
|
├── README.md
|
|
├── LICENSE
|
|
└── .gitignore
|
|
```
|
|
|
|
---
|
|
|
|
## Key Java Modules
|
|
|
|
### landlords-common (Shared Library)
|
|
|
|
**Entities:**
|
|
- `Board.java` — 15x15 game board, move validation, win/draw detection
|
|
- `BOARD_SIZE = 15`
|
|
- `WIN_CONDITION = 5`
|
|
- Methods: `isValidMove()`, `makeMove()`, `checkWin()`, `reset()`
|
|
|
|
- `Room.java` — Game session state
|
|
- `id` (UUID), `type` (PVP/PVE), `status` (WAITING/PLAYING/FINISHED)
|
|
- `players` (2), `spectators`, `board`, `moveHistory`
|
|
|
|
- `GameMove.java` — Single move record
|
|
- `row`, `col`, `piece` (BLACK/WHITE), `timestamp`
|
|
|
|
- `ServerTransferData.java` — Network message from client
|
|
- `code` (ServerEventCode), `data` (payload), `info` (metadata)
|
|
|
|
- `ClientTransferData.java` — Network message from server
|
|
- `code` (ClientEventCode), `data`, `info`
|
|
|
|
- `ClientSide.java` — Player connection state
|
|
- `nickname`, `status` (ONLINE/OFFLINE/PLAYING), `role` (PLAYER/SPECTATOR)
|
|
|
|
**Enums:**
|
|
- `ServerEventCode` (14 codes) — client→server actions
|
|
- `ClientEventCode` (24 codes) — server→client responses
|
|
- `PieceType` — EMPTY, BLACK, WHITE
|
|
- `GameResult` — IN_PROGRESS, BLACK_WIN, WHITE_WIN, DRAW
|
|
- `RoomType` — PVP, PVE
|
|
- `RoomStatus` — WAITING, PLAYING, FINISHED
|
|
- `ClientRole` — PLAYER, SPECTATOR
|
|
- `ClientStatus` — ONLINE, OFFLINE, PLAYING
|
|
|
|
**Game Logic:**
|
|
- `GomokuHelper.java` — Win detection (checks 4 directions)
|
|
- `canWin(Board, row, col, piece)` → boolean
|
|
- `getWinCount(Board, row, col, piece, direction)` → int
|
|
- 37 unit tests in `GomokuHelperTest.java`
|
|
|
|
- `GomokuAI.java` — AI move selection (3 difficulties)
|
|
- `getNextMove(Board, difficulty)` → GameMove
|
|
- `getEasyMove()` — random valid move
|
|
- `getMediumMove()` — find win or block opponent
|
|
- `getHardMove()` — minimax scoring at depth 3
|
|
- 37 unit tests in `GomokuAITest.java`
|
|
|
|
**Utilities:**
|
|
- `JsonUtils.java` — Serialize/deserialize POJO ↔ JSON
|
|
- `ListUtils.java` — List filtering, mapping
|
|
- `OptionsUtils.java` — Command-line argument parsing
|
|
- `StreamUtils.java` — I/O helpers
|
|
- `TimeHelper.java` — Timestamp formatting
|
|
- `I18nHelper.java` — Internationalization (English)
|
|
- `MapHelper.java` — Map utilities
|
|
|
|
**Protocol:**
|
|
- `ByteKit.java` — Byte buffer operations
|
|
- `ByteLink.java` — Byte stream builder
|
|
- `TransferProtocolUtils.java` — Serialize/deserialize messages
|
|
- `DefaultDecoder.java` — Protobuf message decoder
|
|
|
|
---
|
|
|
|
### landlords-server (Netty Server)
|
|
|
|
**Entry Point:**
|
|
- `SimpleServer.java` — Bootstrap
|
|
- Parses args: `-p {port}` (default: 1024)
|
|
- Creates two Netty ServerBootstrap instances (TCP + WebSocket)
|
|
- Registers handlers in pipeline
|
|
|
|
**Event Handlers (ServerEventListener_*):**
|
|
- `CODE_CLIENT_NICKNAME_SET` — Store player nickname
|
|
- `CODE_ROOM_CREATE` / `CODE_ROOM_CREATE_PVE` — Create room, assign players
|
|
- `CODE_GET_ROOMS` — Send room list to client
|
|
- `CODE_ROOM_JOIN` — Add player to existing room
|
|
- `CODE_GAME_STARTING` — Check both players ready, begin game
|
|
- `CODE_GAME_READY` — Mark player ready
|
|
- `CODE_GAME_MOVE` — Validate move, apply to board, broadcast, check win, run AI
|
|
- `CODE_GAME_RESET` — Reset board for rematch
|
|
- `CODE_GAME_WATCH` / `CODE_GAME_WATCH_EXIT` — Spectator join/exit
|
|
- `CODE_CLIENT_EXIT` / `CODE_CLIENT_OFFLINE` — Cleanup disconnection
|
|
|
|
**Network Handlers:**
|
|
- `ProtobufTransferHandler` — TCP/Protobuf codec, encodes/decodes binary messages
|
|
- `WebsocketTransferHandler` — WebSocket JSON codec
|
|
- `StaticFileHandler` — HTTP file serving (index.html, CSS, JS, etc.)
|
|
- Maps `GET /` → `static/index.html`
|
|
- Rejects path traversal (`..`)
|
|
- Supports MIME types: html, css, js, json, mp3, png, jpg, svg, ico
|
|
- Passes `/ratel` requests to WebSocket handler
|
|
|
|
**Message Proxies:**
|
|
- `ProtobufProxy` — Send binary message to TCP client
|
|
- `WebsocketProxy` — Send JSON message to WebSocket client
|
|
- `Proxy` (abstract) — Base interface
|
|
|
|
**Global State:**
|
|
- `ServerContains.java` — Singleton holding all rooms, active connections
|
|
- Methods: `addRoom()`, `removeRoom()`, `getRoomList()`, `findRoom(id)`
|
|
|
|
**Background Tasks:**
|
|
- `RoomClearTask` — Periodic cleanup (remove finished rooms after timeout)
|
|
|
|
---
|
|
|
|
### landlords-client (Java CLI Client)
|
|
|
|
**Entry Point:**
|
|
- `SimpleClient.java` — Bootstrap
|
|
- Parses args: `-h {host} -p {port} -ptl {protocol} -lang {language}`
|
|
- Connects via TCP/Protobuf or WebSocket
|
|
- Reads moves from stdin (`row,col` or `exit`)
|
|
|
|
**Event Handlers (ClientEventListener_*):**
|
|
- `CODE_CLIENT_CONNECT` — Connection successful, display lobby menu
|
|
- `CODE_SHOW_ROOMS` — Display room list
|
|
- `CODE_ROOM_CREATE_SUCCESS` / `CODE_ROOM_JOIN_SUCCESS` — Enter waiting room
|
|
- `CODE_GAME_STARTING` — Display board, wait for moves
|
|
- `CODE_GAME_MOVE_SUCCESS` — Update local board display
|
|
- `CODE_GAME_MOVE_INVALID` / `CODE_GAME_MOVE_OCCUPIED` / etc. — Show error
|
|
- `CODE_GAME_WIN` / `CODE_GAME_LOSE` / `CODE_GAME_DRAW` — Game over
|
|
- `CODE_CLIENT_KICK` — Disconnected by server
|
|
|
|
**Protocol Handlers:**
|
|
- `ProtobufTransferHandler` — TCP codec
|
|
- `WebsocketTransferHandler` — WebSocket codec
|
|
- Same proxy pattern as server
|
|
|
|
---
|
|
|
|
## Web Client (JavaScript/Phaser 3)
|
|
|
|
**Boot:**
|
|
- `main.js` — Create Phaser game instance, start boot scene
|
|
|
|
**Config:**
|
|
- `game-config.js` — Phaser config object
|
|
- Resolution: 800x800
|
|
- Scale mode: Scale.FIT (responsive)
|
|
- Physics: Enabled (for animations)
|
|
- Scene list: [BootScene, MenuScene, GameScene]
|
|
|
|
- `protocol-constants.js` — Export event code enums
|
|
- Maps ServerEventCode and ClientEventCode names to numbers
|
|
|
|
**Scenes (Phaser.Scene subclasses):**
|
|
|
|
- `BootScene` — Initialization
|
|
- Create event bus and services
|
|
- Connect to server (WebSocket)
|
|
- Load assets (images, audio)
|
|
- Transition to menu on connect
|
|
|
|
- `MenuScene` — DOM overlay menus
|
|
- Nickname input form
|
|
- Lobby with room list and create room button
|
|
- Difficulty selector (for PVE)
|
|
- Settings menu
|
|
|
|
- `GameScene` — Main gameplay
|
|
- Render board and stones
|
|
- Handle mouse clicks (place stones)
|
|
- Display move history panel
|
|
- Show turn indicator (whose turn?)
|
|
- Display game over message
|
|
- Handle rematch/exit options
|
|
- Listen to WebSocket events (opponent moves, AI moves)
|
|
|
|
**Services (Singleton-like, event-driven):**
|
|
|
|
- `EventBus.js` — Simple pub/sub
|
|
- `emit(event, data)`
|
|
- `on(event, callback)`
|
|
- Decouples scenes and services
|
|
|
|
- `ConnectionService.js` — WebSocket client
|
|
- `connect(url)` → returns Promise
|
|
- Maintains `ws` connection
|
|
- Heartbeat every 30 seconds (send `CODE_CLIENT_HEAD_BEAT`)
|
|
- Auto-reconnect on close (exponential backoff)
|
|
- `send(code, data)` — send message to server
|
|
|
|
- `GameStateService.js` — Client-side state container
|
|
- `room` object (id, players, board, status)
|
|
- `nickname` string
|
|
- `board` (15x15 array, mirrored from server)
|
|
- Methods: `update()`, `reset()`, `addMove()`
|
|
- Notify listeners on state change
|
|
|
|
**Game Objects (Phaser.GameObjects.*):**
|
|
|
|
- `Board.js` — Game board renderer
|
|
- Create 15x15 grid of cells
|
|
- Wood texture background
|
|
- Cell dimensions: ~50x50 pixels
|
|
- `placeStone(row, col, color)` method
|
|
- Hover effect (highlight hovered cell)
|
|
|
|
- `Stone.js` — Individual stone sprite
|
|
- Phaser.GameObjects.Sprite subclass
|
|
- Gradient fill (black or white)
|
|
- Drop animation (tweens)
|
|
- Glow effect on hover
|
|
|
|
**UI Components (DOM + Phaser):**
|
|
|
|
- `MenuUI.js` — Menu rendering
|
|
- Nickname input, validation
|
|
- Room creation form (PVP/PVE selector, AI difficulty)
|
|
- Room list (with join buttons)
|
|
- Settings panel
|
|
|
|
- `GameUI.js` — Game HUD
|
|
- Move history panel (list of moves: 7,7 Black, 8,8 White, etc.)
|
|
- Turn indicator (waiting for opponent / your turn)
|
|
- Game over modal (winner announcement, rematch button)
|
|
- Toast notifications (connection lost, reconnected, etc.)
|
|
|
|
---
|
|
|
|
## Build Configuration
|
|
|
|
### Maven (Java)
|
|
|
|
**File:** `pom.xml`
|
|
|
|
**Parent:** Spring Boot 2.0.5.RELEASE
|
|
|
|
**Key Plugins:**
|
|
- `maven-compiler-plugin` — Java 8 source/target
|
|
- `maven-surefire-plugin` — Run unit tests
|
|
- `maven-source-plugin` — Generate source JAR
|
|
- `maven-javadoc-plugin` — Generate docs
|
|
|
|
**Dependencies:**
|
|
- Netty (async networking)
|
|
- Protobuf 3.25.5 (binary serialization)
|
|
- Gson (JSON parsing)
|
|
- JUnit (testing)
|
|
|
|
**Modules:**
|
|
- `landlords-common` (library)
|
|
- `landlords-server` (executable JAR)
|
|
- `landlords-client` (executable JAR)
|
|
|
|
**Build Command:**
|
|
```bash
|
|
mvn clean package -DskipTests
|
|
# Produces:
|
|
# landlords-server/target/landlords-server-1.4.0.jar
|
|
# landlords-client/target/landlords-client-1.4.0.jar
|
|
```
|
|
|
|
### Vite (JavaScript)
|
|
|
|
**File:** `web-client/package.json`
|
|
|
|
**Scripts:**
|
|
- `npm run dev` — Start dev server (port 5173, hot reload)
|
|
- `npm run build` — Production build to `dist/`
|
|
- `npm run preview` — Preview production build
|
|
|
|
**Dependencies:**
|
|
- `phaser ^3.87.0` — Game engine
|
|
- `vite ^6.3.1` — Bundler
|
|
|
|
**Output:** `web-client/dist/` (index.html + bundled JS)
|
|
|
|
---
|
|
|
|
## Testing
|
|
|
|
**Test Framework:** JUnit 4
|
|
|
|
**Test Files:**
|
|
1. `GomokuHelperTest.java` (landlords-common)
|
|
- 37+ test cases for win detection
|
|
- Tests all 4 directions (horizontal, vertical, 2 diagonals)
|
|
- Tests edge cases (board edges, corners)
|
|
- Tests draw condition (full board)
|
|
|
|
2. `GomokuAITest.java` (landlords-common)
|
|
- Tests Easy AI (random valid moves)
|
|
- Tests Medium AI (finds winning move, blocks opponent)
|
|
- Tests Hard AI (minimax scoring)
|
|
- Tests move validity after AI selection
|
|
|
|
**Run Tests:**
|
|
```bash
|
|
mvn clean test
|
|
# or
|
|
mvn test -DskipTests=false
|
|
```
|
|
|
|
**Coverage:** ~100% for game logic (Board, GomokuHelper, GomokuAI)
|
|
|
|
---
|
|
|
|
## Dependencies Summary
|
|
|
|
| Module | Dependencies |
|
|
|--------|--------------|
|
|
| **landlords-common** | Netty, Protobuf, Gson, JUnit |
|
|
| **landlords-server** | landlords-common, Netty, Protobuf |
|
|
| **landlords-client** | landlords-common, Netty, Protobuf |
|
|
| **web-client** | Phaser 3, Vite (dev-only) |
|
|
|
|
---
|
|
|
|
## Important Files by Feature
|
|
|
|
### Game Logic
|
|
- `landlords-common/src/main/java/.../entity/Board.java` — Board state
|
|
- `landlords-common/src/main/java/.../helper/GomokuHelper.java` — Win detection
|
|
- `landlords-common/src/main/java/.../robot/GomokuAI.java` — AI engine
|
|
|
|
### Networking
|
|
- `landlords-server/src/main/.../handler/StaticFileHandler.java` — HTTP file serving
|
|
- `landlords-server/src/main/.../handler/WebsocketTransferHandler.java` — WS codec
|
|
- `landlords-server/src/main/.../handler/ProtobufTransferHandler.java` — TCP codec
|
|
- `web-client/src/services/connection-service.js` — WebSocket client
|
|
|
|
### Game Flow
|
|
- `landlords-server/src/main/.../event/ServerEventListener_CODE_GAME_MOVE.java` — Move processing
|
|
- `landlords-server/src/main/.../event/ServerEventListener_CODE_GAME_STARTING.java` — Game start
|
|
- `web-client/src/scenes/game-scene.js` — Game rendering & input
|
|
|
|
### UI
|
|
- `web-client/src/objects/board.js` — Board renderer
|
|
- `web-client/src/ui/game-ui.js` — HUD & notifications
|
|
- `web-client/src/ui/menu-ui.js` — Menus & forms
|
|
|
|
---
|
|
|
|
## Code Quality
|
|
|
|
**Metrics:**
|
|
- **Lines of Code:** ~5,000 Java, ~1,500 JavaScript
|
|
- **Test Coverage:** Game logic 100%, server 80%+, client varies
|
|
- **File Size:** Most Java files < 200 lines, JavaScript < 300 lines
|
|
- **Linting:** No major violations (follow code-standards.md)
|
|
|
|
**Documentation:**
|
|
- Javadoc on public methods (Java)
|
|
- JSDoc on exported functions (JavaScript)
|
|
- Inline comments for complex logic
|
|
|
|
---
|
|
|
|
## Build Artifacts
|
|
|
|
| Artifact | Location | Purpose |
|
|
|----------|----------|---------|
|
|
| Server JAR | `landlords-server/target/landlords-server-1.4.0.jar` | Executable server |
|
|
| Client JAR | `landlords-client/target/landlords-client-1.4.0.jar` | Executable CLI client |
|
|
| Web dist | `web-client/dist/` | Static files for web UI |
|
|
| Source JAR | `landlords-*/target/*-sources.jar` | Source code archive |
|
|
|
|
---
|
|
|
|
## Continuous Integration
|
|
|
|
**GitHub Actions:**
|
|
|
|
1. **build.yml**
|
|
- Trigger: Push to any branch
|
|
- Steps:
|
|
- Checkout code
|
|
- Setup Java 8
|
|
- Run `mvn clean test`
|
|
- Run `npm install && npm run build` (web-client)
|
|
|
|
2. **deploy-pages.yml**
|
|
- Trigger: Push to `master`
|
|
- Steps:
|
|
- Build web-client
|
|
- Deploy to GitHub Pages (`https://tiennm99.github.io/caro/`)
|
|
|
|
---
|
|
|
|
## Version & Release
|
|
|
|
**Current Version:** 1.4.0
|
|
|
|
**Release Process:**
|
|
1. Tag commit: `git tag v1.4.0`
|
|
2. Push tag: `git push origin v1.4.0`
|
|
3. Create GitHub Release with JAR artifacts
|
|
4. Auto-deploy web-client to Pages
|
|
|
|
**Versioning:** Semantic versioning (MAJOR.MINOR.PATCH)
|