Files
caro/docs/codebase-summary.md
tiennm99 cbad690565 docs,chore: single-port 1999 websocket protobuf
Phase 05 — sync infrastructure and documentation with the typed-protobuf
refactor:
- docker-compose.yml: drop 1024/1025 mappings, single "1999:1999"
- server/Dockerfile: EXPOSE 1999, -p 1999 entrypoint
- README.md: rewrite transport description, architecture diagram, protocol
  section, server options, project structure, add proto:gen script note
- docs/project-overview.md: update transport + dependencies sections
- docs/system-architecture.md: rewrite diagrams + pipeline + file inventory
  for the WebSocket-only typed-dispatch path
- docs/codebase-summary.md: refresh file tree, java package inventory,
  gradle deps, vite deps, networking and game-flow sections
- docs/deployment-guide.md: single-port walkthrough for local / docker /
  systemd / nginx; remove all 1024/1025 firewall and troubleshooting
- docs/code-standards.md: replace dead ServerEventListener_CODE_* class-name
  example, fix sample ws:// URL to port 1999
2026-04-11 08:33:46 +07:00

13 KiB

Codebase Summary

Directory Structure

caro/
├── .github/
│   └── workflows/
│       └── build.yml                    CI: build + test (Java 25 + Node 22)
├── server/                              Standalone Netty server (Java 25, Gradle)
│   ├── src/main/java/com/miti99/caro/
│   │   ├── common/
│   │   │   ├── channel/                 Netty utilities (ChannelUtils)
│   │   │   ├── entity/                  Data models (Board, Room, GameMove, ClientSide)
│   │   │   ├── enums/                   ClientEventCode, PieceType, GameResult, RoomType, etc.
│   │   │   ├── exception/               LandlordException
│   │   │   ├── features/                Feature flags
│   │   │   ├── helper/                  GomokuHelper (win detection)
│   │   │   ├── print/                   SimplePrinter
│   │   │   ├── robot/                   AI engine (GomokuAI)
│   │   │   └── utils/                   ListUtils, OptionsUtils, StreamUtils
│   │   └── server/
│   │       ├── event/
│   │       │   ├── request/             ClientRequest sealed interface + record variants (14 types)
│   │       │   ├── handler/             14 typed request handlers (*Handler.java)
│   │       │   ├── RequestConverter.java Protobuf→ClientRequest conversion
│   │       │   └── RequestDispatcher.java Pattern-match dispatch logic
│   │       ├── handler/                 Netty pipeline (WebsocketTransferHandler)
│   │       ├── timer/                   RoomClearTask
│   │       ├── SimpleServer.java        Server entry point
│   │       └── ServerContains.java      Global state container
│   ├── src/main/proto/
│   │   ├── request.proto                Client→server typed message definitions
│   │   └── response.proto               Server→client typed message definitions
│   ├── src/test/java/com/miti99/caro/common/
│   │   ├── helper/tests/GomokuHelperTest.java    29 JUnit 5 tests
│   │   └── robot/tests/GomokuAITest.java          8 JUnit 5 tests
│   ├── gradle/wrapper/                  Gradle wrapper (9.2.1)
│   ├── gradlew, gradlew.bat             Wrapper launchers
│   ├── settings.gradle.kts              Root project name
│   ├── build.gradle.kts                 Standalone build (Kotlin DSL) with Shadow plugin
│   └── Dockerfile                       Multi-stage (eclipse-temurin:25-jdk, eclipse-temurin:25-jre-alpine)
├── client/                              Phaser 3 + Vite 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
│   ├── Dockerfile                       Nginx-based static server
│   ├── index.html
│   ├── vite.config.js
│   └── package.json                     caro-client 0.0.1
├── docs/                                (this directory)
│   ├── project-overview.md
│   ├── system-architecture.md
│   ├── codebase-summary.md
│   ├── code-standards.md
│   └── deployment-guide.md
├── plans/                               Implementation plans
├── docker-compose.yml                   services: server, client
├── README.md
├── LICENSE
└── .gitignore

Key Java Packages

com.miti99.caro.common (Shared code)

Entities:

  • Board.java — 15x15 game board, move validation, win/draw detection (BOARD_SIZE=15, WIN_CONDITION=5)
  • Room.java — Game session state (id, type, status, players, board, moveHistory)
  • GameMove.java — Single move (row, col, piece, playerId, timestamp)
  • ClientSide.java — Player connection state (nickname, status, role)
  • Generated proto messages — Request, Response oneof wrappers (in server/build/generated/sources/proto/main/java/)

Enums:

  • ServerEventCode — client→server action codes
  • ClientEventCode — server→client response codes
  • PieceType — EMPTY, BLACK, WHITE
  • GameResult — IN_PROGRESS, BLACK_WIN, WHITE_WIN, DRAW
  • RoomType, RoomStatus, ClientRole, ClientStatus

Game Logic:

  • GomokuHelper.java — Win detection (4 directions), board rendering
  • GomokuAI.java — AI move selection (Easy/Medium/Hard)

Utilities:

  • ListUtils, OptionsUtils, StreamUtils

Dispatch (typed records):

  • ClientRequest — Sealed interface representing all possible client requests (14 variants)
  • Record types: SetNicknameRequest, CreateRoomRequest, CreatePveRoomRequest, GetRoomsRequest, JoinRoomRequest, GameStartingRequest, GameReadyRequest, GameMoveRequest, GameResetRequest, WatchGameRequest, WatchGameExitRequest, ClientExitRequest, ClientOfflineRequest, SetClientInfoRequest

com.miti99.caro.server (Server code)

Entry Point:

  • SimpleServer.java — Bootstrap (WebSocket server defaults to port 1999 at /ratel)
  • ServerContains.java — Singleton global state (rooms, client sides, channel map)

*Event Handlers (14 Handler classes):

  • SetNicknameHandler, CreateRoomHandler, CreatePveRoomHandler, GetRoomsHandler, JoinRoomHandler
  • GameStartingHandler, GameReadyHandler, GameMoveHandler, GameResetHandler
  • WatchGameHandler, WatchGameExitHandler, ClientExitHandler, ClientOfflineHandler, SetClientInfoHandler

Request Processing:

  • RequestConverter — Decodes Request oneof from binary wire format → typed ClientRequest variant
  • RequestDispatcher — Pattern-matches ClientRequest variant → dispatches to corresponding handler

Network Handler:

  • WebsocketTransferHandler — Netty pipeline handler: decodes binary frame to Request protobuf message

Background Tasks:

  • RoomClearTask — Periodic cleanup

Client (JavaScript/Phaser 3)

Boot:

  • main.js — Create Phaser game instance, start boot scene

Config:

  • game-config.js — Phaser config (800x800, Scale.FIT, scenes: [BootScene, MenuScene, GameScene])
  • protocol-constants.js — Export event code enums matching server

Scenes:

  • BootScene — Create services, connect WebSocket, load assets, transition to menu
  • MenuScene — Nickname input, lobby, room list, difficulty selector
  • GameScene — Board + stones, click handling, move history, turn indicator, game over

Services:

  • EventBus — Pub/sub decoupling scenes and services
  • ConnectionService — WebSocket client with heartbeat + auto-reconnect
  • GameStateService — Client-side state container

Game Objects:

  • Board — 15x15 wood-textured grid
  • Stone — Gradient stone sprite with drop animation

UI:

  • MenuUI — Nickname form, room list, settings
  • GameUI — HUD, move history, game over modal, toasts

Build Configuration

Gradle (Java)

Files:

  • server/build.gradle.kts — standalone Gradle build script (Kotlin DSL)
  • server/settings.gradle.kts — root project name (caro-server)
  • server/gradle/wrapper/ — committed wrapper (Gradle 9.2.1)
  • server/gradlew / server/gradlew.bat — wrapper launchers

Coordinates: com.miti99.caro:caro-server:0.0.1

Plugins:

  • java — standard Java plugin
  • com.google.protobuf:0.9.6 — protobuf code generation
  • com.gradleup.shadow:8.3.8 — fat jar packaging

Toolchain: JavaLanguageVersion.of(25) — Gradle auto-provisions Java 25 if missing.

Dependencies:

  • io.netty:netty-all:4.1.128.Final — async networking
  • com.google.protobuf:protobuf-java:3.25.5 — binary serialization, generated code
  • com.google.protobuf:protoc:3.25.5 — protobuf compiler (build time)
  • org.junit:junit-bom:5.11.4 (platform) + org.junit.jupiter:junit-jupiter — testing

Shadow jar config:

  • Main class: com.miti99.caro.server.SimpleServer
  • No special command-line args (server defaults to port 1999)
  • mergeServiceFiles() — preserve Netty SPIs
  • Excludes signing metadata (*.SF, *.DSA, *.RSA)

Build Command:

./server/gradlew -p server clean build
# Produces: server/build/libs/caro-server-0.0.1.jar (shaded fat jar)

Vite (JavaScript)

File: client/package.json

Package: caro-client 0.0.1

Scripts:

  • npm run dev — Dev server (port 5173, hot reload)
  • npm run build — Production build to dist/
  • npm run preview — Preview production build
  • npm run proto:gen — Regenerate protobuf code from server .proto files (uses pbjs + pbts)

Dependencies:

  • phaser ^3.87.0 — Game engine
  • protobufjs ^7.5.4 — JavaScript protobuf codec
  • vite ^6.3.1 — Bundler (dev-only)
  • @protobufjs/cli ^1.1.3 — Protobuf code generator (dev-only)

Output: client/dist/ (index.html + bundled JS, ~1.5 MB / 346 KB gzipped)


Testing

Test Framework: JUnit 5 (org.junit.jupiter.api)

Test Files:

  1. server/src/test/java/com/miti99/caro/common/helper/tests/GomokuHelperTest.java — 29 tests (win detection, edges, draw, game flow)
  2. server/src/test/java/com/miti99/caro/common/robot/tests/GomokuAITest.java — 8 tests (Easy/Medium/Hard AI)

Run Tests:

./server/gradlew -p server clean test

Coverage: ~100% for game logic (Board, GomokuHelper, GomokuAI)


Dependencies Summary

Scope Dependencies
server runtime Netty 4.1.128, Protobuf 3.25.5 (generated code)
server test JUnit Jupiter 5.11.4
server build Gradle 9.2.1, Protobuf Gradle plugin 0.9.6, Shadow 8.3.8
client runtime Phaser 3.87, protobufjs 7.5.4
client build Vite 6.3, protobufjs-cli 1.1.3

Important Files by Feature

Game Logic

  • server/src/main/java/com/miti99/caro/common/entity/Board.java
  • server/src/main/java/com/miti99/caro/common/helper/GomokuHelper.java
  • server/src/main/java/com/miti99/caro/common/robot/GomokuAI.java

Networking

  • server/src/main/java/com/miti99/caro/server/handler/WebsocketTransferHandler.java — Binary decoder
  • server/src/main/java/com/miti99/caro/server/event/RequestConverter.java — Protobuf→record conversion
  • server/src/main/java/com/miti99/caro/server/event/RequestDispatcher.java — Dispatch logic
  • server/src/main/java/com/miti99/caro/common/channel/ChannelUtils.java — Response encoder/sender
  • client/src/services/connection-service.js — WebSocket client (binary mode)
  • server/src/main/proto/*.proto — Message definitions

Game Flow

  • server/src/main/java/com/miti99/caro/server/event/handler/GameMoveHandler.java
  • server/src/main/java/com/miti99/caro/server/event/handler/GameStartingHandler.java
  • client/src/scenes/game-scene.js

UI

  • client/src/objects/board.js
  • client/src/ui/game-ui.js
  • client/src/ui/menu-ui.js

Code Quality

Metrics:

  • Lines of Code: ~5,000 Java, ~1,500 JavaScript
  • Test Coverage: Game logic ~100%, server flow ~80%, client varies
  • File Size: Most Java files < 200 lines, JavaScript < 300 lines

Java 25 features in use:

  • record for immutable DTOs (Msg)
  • Switch expressions (GomokuHelper.getWinnerMessage, GomokuAI.getNextMove)
  • var for obvious local types

Build Artifacts

Artifact Location Purpose
Server jar server/build/libs/caro-server-0.0.1.jar Shaded executable fat jar
Client dist client/dist/ Static files for web UI

Continuous Integration

GitHub Actions:

build.yml

  • Trigger: push/PR on master (ignores .md and .gitignore)
  • Jobs:
    • build-server — Setup Java 25 (Temurin) + gradle/actions/setup-gradle, run ./gradlew -p server --no-daemon clean build
    • build-client — Setup Node 22, npm ci, npm run build

Deployment is handled via Docker Compose from this repo; there is no hosted deployment pipeline.


Version & Release

Current Version: 0.0.1 (both caro-server and caro-client)

Versioning: Semantic versioning (MAJOR.MINOR.PATCH).