5.4 KiB
5.4 KiB
tic-tac-toe — Authoritative Multiplayer Game Server (Nakama + Go)
A production-grade, server-authoritative multiplayer backend built using Nakama 3, Go plugins, and PostgreSQL, deployed via Drone CI/CD and exposed securely through Traefik.
🚀 Overview
This repository contains a fully authoritative Tic-Tac-Toe backend built on Nakama 3.21.0 ARM, using a custom Go plugin to implement game logic, matchmaking, validation, leaderboards, and session management.
The server ensures:
- Zero client trust
- Deterministic gameplay
- Secure matchmaking
- Validated moves
- Authoritative outcomes
Designed for scalability, extensibility, and cloud deployment (GCP, AWS, or ARM homelab environments).
⭐ Key Features
- Authoritative Go match handler (
tictactoe) - Device-ID authentication + JWT session
- Matchmaking queue support
- Deterministic game validation
- Match lifecycle handling
- Disconnect handling & forfeit detection
- Leaderboards creation + scoring
- Production-grade CI/CD with Drone
- Automated ARM Docker builds
- Full Traefik routing (HTTP + WebSocket)
- Compatible with x86/ARM/GCP
🧩 Architecture
High-Level System Diagram
flowchart LR
UI[(React + Vite)] --> Traefik
Traefik --> Nakama[Nakama Server]
Nakama --> Plugin[Go Plugin (main.so)]
Nakama --> Postgres[(PostgreSQL)]
Drone[Drone CI/CD] --> Registry[Private Docker Registry]
Registry --> Nakama
🛠 Tech Stack
Backend
- Nakama 3.21.0 ARM
- Go 1.21.6 (plugin ABI compatible)
- PostgreSQL 16
- Docker / multi-stage builds
- Drone CI/CD
- Traefik reverse proxy
Cloud/Infra
- GCP-ready
- ARM homelab deployments
- Private registry support
📦 Repository Structure
tic-tac-toe/
│── plugins/
│ ├── main.go
│ ├── match.go
│ └── matchmaking.go
│
│── Dockerfile
│── go.mod
│── go.sum
│── README.md
🔌 Registered Server Components
📌 Match Handler
Name: tictactoe
Handles:
- Turn validation
- State updates
- Win/loss/draw
- Disconnect forfeit
- Broadcasting authoritative state
📌 RPCs
| RPC Name | Purpose |
|---|---|
leave_matchmaking |
Allows clients to exit matchmaking queue |
📌 Matchmaker Hook
| Hook | Purpose |
|---|---|
MatchmakerMatched |
Validates matchmaker tickets and instantiates a new match |
🎮 Gameplay Protocol
OpCodes
| OpCode | Direction | Meaning |
|---|---|---|
| 1 | Client → Server | Submit move {x, y} |
| 2 | Server → Client | Full authoritative game state |
🧠 Authoritative Flow Diagram
sequenceDiagram
participant C1 as Client 1
participant C2 as Client 2
participant S as Nakama + Go Plugin
C1->>S: Matchmaker Join
C2->>S: Matchmaker Join
S->>S: MatchmakerMatched()
S-->>C1: Matched
S-->>C2: Matched
C1->>S: OpCode 1 (Move)
S->>S: Validate Move
S-->>C1: OpCode 2 (Updated State)
S-->>C2: OpCode 2 (Updated State)
⚙️ Build & Development
Build Go Plugin
CGO_ENABLED=1 go build \
--trimpath \
--buildmode=plugin \
-o build/main.so \
./plugins
Run Nakama Locally
nakama migrate up --database.address "$DB_ADDR"
nakama \
--database.address "$DB_ADDR" \
--socket.server_key="$SERVER_KEY"
🐳 Docker Build (Multi-Stage)
FROM --platform=linux/arm64 golang:1.21.6 AS plugin_builder
RUN go mod download
COPY . .
RUN CGO_ENABLED=1 go build --buildmode=plugin -o build/main.so ./plugins
FROM heroiclabs/nakama:3.21.0-arm
COPY --from=plugin_builder /workspace/build/main.so /nakama/data/modules/main.so
ENTRYPOINT ...
🤖 CI/CD — Drone Pipeline
Drone performs:
- Fetch latest Git tag
- Check if Docker image already exists
- Build Nakama + plugin
- Push to private registry
- Stop old container
- Deploy new Nakama server automatically
Full pipeline included in repository (.drone.yml).
🌐 Traefik Routing
HTTPS
nakama.aetoskia.com
/ → HTTP API
/ws → WebSocket (real-time)
Includes:
- CORS rules
- WebSocket upgrade headers
- Certificate resolver
- Secure default middlewares
🔧 Environment Variables
| Variable | Description |
|---|---|
DB_ADDR |
PostgreSQL connection string |
SERVER_KEY |
Nakama server key |
REGISTRY_HOST |
Private registry |
📊 Leaderboards
- Created during server start
- Score:
+1on win - Metadata logged (mode, player IDs)
🧪 Testing
- Win/loss/draw simulation
- Invalid move rejection
- Disconnect → forfeit
- Load testing matchmaking
📈 Production Deployment
Supported on:
- ARM homelabs (Raspberry Pi)
- Google Cloud (Compute Engine + Cloud SQL)
- AWS EC2
- Kubernetes (optional)
🤝 Contributing
- Fork repo
- Create feature branch
- Write tests
- Submit PR
Coding style: Go fmt + idiomatic Go; follow Nakama plugin constraints.