Compare commits
39 Commits
v0.2.0
...
70669fc856
| Author | SHA1 | Date | |
|---|---|---|---|
| 70669fc856 | |||
| 1752bfaed4 | |||
| 74e75de577 | |||
| 7983be56e4 | |||
| e9eb37f665 | |||
| 7a7c6adc47 | |||
| ae5628f370 | |||
| e8e2419537 | |||
| 4ee6027612 | |||
| 389e77e2ae | |||
| 7ce860db96 | |||
| 92f307d33d | |||
| 6e7d2d9f14 | |||
| c91dba475c | |||
| 04d988c584 | |||
| 27abc56a00 | |||
| 333b48ad60 | |||
| 4dee0bfb0a | |||
| 1e91825808 | |||
| c5cb1047ae | |||
| 18f9eed71d | |||
| 02de328bcd | |||
| 31f1a66fed | |||
| 5065145c6f | |||
| 8e0475c8a7 | |||
| 1359a75214 | |||
| 6786547950 | |||
| 17a2caea49 | |||
| 8ff199ca10 | |||
| 62c1f3920b | |||
| 73e3f0a7ac | |||
| 21f6698b89 | |||
| 06904143d6 | |||
| ba05aa7c76 | |||
| bfcf977e13 | |||
| 6eca090046 | |||
| 07cb519f55 | |||
| 840d7701ca | |||
| f1f40f5799 |
163
.drone.yml
Normal file
163
.drone.yml
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
type: docker
|
||||||
|
name: nakama-server
|
||||||
|
|
||||||
|
platform:
|
||||||
|
os: linux
|
||||||
|
arch: arm64
|
||||||
|
|
||||||
|
workspace:
|
||||||
|
path: /drone/src
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- name: dockersock
|
||||||
|
host:
|
||||||
|
path: /var/run/docker.sock
|
||||||
|
|
||||||
|
steps:
|
||||||
|
# -----------------------------------------------------
|
||||||
|
# 1. Fetch latest Tags
|
||||||
|
# -----------------------------------------------------
|
||||||
|
- name: fetch-tags
|
||||||
|
image: docker:24
|
||||||
|
volumes:
|
||||||
|
- name: dockersock
|
||||||
|
path: /var/run/docker.sock
|
||||||
|
commands:
|
||||||
|
- apk add --no-cache git
|
||||||
|
- git fetch --tags
|
||||||
|
- |
|
||||||
|
# Get latest Git tag and trim newline
|
||||||
|
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null | tr -d '\n')
|
||||||
|
echo "Latest Git tag fetched: $LATEST_TAG"
|
||||||
|
|
||||||
|
# Save to file for downstream steps
|
||||||
|
echo "$LATEST_TAG" > /drone/src/LATEST_TAG.txt
|
||||||
|
|
||||||
|
# Read back for verification
|
||||||
|
IMAGE_TAG=$(cat /drone/src/LATEST_TAG.txt | tr -d '\n')
|
||||||
|
echo "Image tag read from file: $IMAGE_TAG"
|
||||||
|
|
||||||
|
# Validate
|
||||||
|
if [ -z "$IMAGE_TAG" ]; then
|
||||||
|
echo "❌ No git tags found! Cannot continue."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# -----------------------------------------------------
|
||||||
|
# 2. Check existing Nakama Docker image
|
||||||
|
# -----------------------------------------------------
|
||||||
|
- name: check-remote-image
|
||||||
|
image: docker:24
|
||||||
|
volumes:
|
||||||
|
- name: dockersock
|
||||||
|
path: /var/run/docker.sock
|
||||||
|
commands:
|
||||||
|
- IMAGE_TAG=$(cat /drone/src/LATEST_TAG.txt | tr -d '\n')
|
||||||
|
|
||||||
|
- echo "Checking if lila-games/nakama-server:$IMAGE_TAG exists on remote Docker..."
|
||||||
|
- echo "Existing Docker tags for lila-games/nakama-server:"
|
||||||
|
- docker images --format "{{.Repository}}:{{.Tag}}" | grep "^lila-games/nakama-server" || echo "(none)"
|
||||||
|
- |
|
||||||
|
if docker image inspect lila-games/nakama-server:$IMAGE_TAG > /dev/null 2>&1; then
|
||||||
|
echo "✅ Docker image lila-games/nakama-server:$IMAGE_TAG already exists — skipping build"
|
||||||
|
exit 78
|
||||||
|
else
|
||||||
|
echo "⚙️ Docker image lila-games/nakama-server:$IMAGE_TAG not found — proceeding to build..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# -----------------------------------------------------
|
||||||
|
# 3. Build Nakama Docker image
|
||||||
|
# -----------------------------------------------------
|
||||||
|
- name: build-image
|
||||||
|
image: docker:24
|
||||||
|
volumes:
|
||||||
|
- name: dockersock
|
||||||
|
path: /var/run/docker.sock
|
||||||
|
commands:
|
||||||
|
- IMAGE_TAG=$(cat /drone/src/LATEST_TAG.txt | tr -d '\n')
|
||||||
|
|
||||||
|
- echo "🔨 Building Nakama image lila-games/nakama-server:latest"
|
||||||
|
- |
|
||||||
|
docker build --network=host \
|
||||||
|
-t lila-games/nakama-server:$IMAGE_TAG \
|
||||||
|
-t lila-games/nakama-server:latest \
|
||||||
|
/drone/src
|
||||||
|
|
||||||
|
# -----------------------------------------------------
|
||||||
|
# 4. Push Nakama Image
|
||||||
|
# -----------------------------------------------------
|
||||||
|
- name: push-image
|
||||||
|
image: docker:24
|
||||||
|
environment:
|
||||||
|
REGISTRY_HOST:
|
||||||
|
from_secret: REGISTRY_HOST
|
||||||
|
REGISTRY_USER:
|
||||||
|
from_secret: REGISTRY_USER
|
||||||
|
REGISTRY_PASS:
|
||||||
|
from_secret: REGISTRY_PASS
|
||||||
|
volumes:
|
||||||
|
- name: dockersock
|
||||||
|
path: /var/run/docker.sock
|
||||||
|
commands:
|
||||||
|
- IMAGE_TAG=$(cat /drone/src/LATEST_TAG.txt | tr -d '\n')
|
||||||
|
|
||||||
|
- echo "🔑 Logging into registry $REGISTRY_HOST ..."
|
||||||
|
- echo "$REGISTRY_PASS" | docker login $REGISTRY_HOST -u "$REGISTRY_USER" --password-stdin
|
||||||
|
- echo "🏷️ Tagging images with registry prefix..."
|
||||||
|
- docker tag lila-games/nakama-server:$IMAGE_TAG $REGISTRY_HOST/lila-games/nakama-server:$IMAGE_TAG
|
||||||
|
- docker tag lila-games/nakama-server:$IMAGE_TAG $REGISTRY_HOST/lila-games/nakama-server:latest
|
||||||
|
- echo "📤 Pushing lila-games/nakama-server:$IMAGE_TAG ..."
|
||||||
|
- docker push $REGISTRY_HOST/lila-games/nakama-server:$IMAGE_TAG
|
||||||
|
- echo "📤 Pushing lila-games/nakama-server:latest ..."
|
||||||
|
- docker push $REGISTRY_HOST/lila-games/nakama-server:latest
|
||||||
|
|
||||||
|
# -----------------------------------------------------
|
||||||
|
# 5. Stop old Nakama container
|
||||||
|
# -----------------------------------------------------
|
||||||
|
- name: stop-old
|
||||||
|
image: docker:24
|
||||||
|
volumes:
|
||||||
|
- name: dockersock
|
||||||
|
path: /var/run/docker.sock
|
||||||
|
commands:
|
||||||
|
- echo "🛑 Stopping old Nakama container..."
|
||||||
|
- docker rm -f nakama-server || true
|
||||||
|
|
||||||
|
# -----------------------------------------------------
|
||||||
|
# 6. Run new Nakama container
|
||||||
|
# -----------------------------------------------------
|
||||||
|
- name: run-container
|
||||||
|
image: docker:24
|
||||||
|
volumes:
|
||||||
|
- name: dockersock
|
||||||
|
path: /var/run/docker.sock
|
||||||
|
environment:
|
||||||
|
DB_ADDR:
|
||||||
|
from_secret: POSTGRES_ADDR
|
||||||
|
SERVER_KEY:
|
||||||
|
from_secret: SERVER_KEY
|
||||||
|
REGISTRY_HOST:
|
||||||
|
from_secret: REGISTRY_HOST
|
||||||
|
commands:
|
||||||
|
- IMAGE_TAG=$(cat /drone/src/LATEST_TAG.txt | tr -d '\n')
|
||||||
|
- echo "🚀 Starting Nakama server..."
|
||||||
|
- |
|
||||||
|
docker run -d \
|
||||||
|
--name nakama-server \
|
||||||
|
-p 7350:7350 \
|
||||||
|
-p 7351:7351 \
|
||||||
|
-p 7349:7349 \
|
||||||
|
--restart always \
|
||||||
|
--add-host private-pi:192.168.1.111 \
|
||||||
|
-e DB_ADDR="$DB_ADDR" \
|
||||||
|
-e SERVER_KEY="$SERVER_KEY" \
|
||||||
|
lila-games/nakama-server:latest
|
||||||
|
|
||||||
|
# -----------------------------------------------------
|
||||||
|
# Pipeline trigger
|
||||||
|
# -----------------------------------------------------
|
||||||
|
trigger:
|
||||||
|
event:
|
||||||
|
- tag
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -2,4 +2,5 @@
|
|||||||
.run
|
.run
|
||||||
.venv
|
.venv
|
||||||
/vendor/
|
/vendor/
|
||||||
/build/
|
/build/
|
||||||
|
.env
|
||||||
|
|||||||
35
Dockerfile
Normal file
35
Dockerfile
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# -----------------------------------------------------
|
||||||
|
# 1. Build the Nakama plugin
|
||||||
|
# -----------------------------------------------------
|
||||||
|
FROM --platform=linux/arm64 golang:1.21.6 AS plugin_builder
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
build-essential \
|
||||||
|
git
|
||||||
|
|
||||||
|
WORKDIR /workspace
|
||||||
|
|
||||||
|
COPY go.mod go.sum ./
|
||||||
|
RUN go mod download
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN mkdir -p build && \
|
||||||
|
CGO_ENABLED=1 go build \
|
||||||
|
--trimpath \
|
||||||
|
--buildmode=plugin \
|
||||||
|
-o build/main.so \
|
||||||
|
./plugins
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------------------------------
|
||||||
|
# 2. Build final Nakama image
|
||||||
|
# -----------------------------------------------------
|
||||||
|
FROM heroiclabs/nakama:3.21.0-arm
|
||||||
|
|
||||||
|
# Copy plugin from builder stage
|
||||||
|
COPY --from=plugin_builder /workspace/build/main.so /nakama/data/modules/main.so
|
||||||
|
#COPY --from=plugin_builder local.yml /nakama/data/config.yml
|
||||||
|
|
||||||
|
# Default Nakama startup (runs migrations + server)
|
||||||
|
ENTRYPOINT exec /bin/sh -ecx "/nakama/nakama migrate up --database.address \"$DB_ADDR\" && exec /nakama/nakama --database.address \"$DB_ADDR\" --socket.server_key=\"$SERVER_KEY\""
|
||||||
319
README.md
319
README.md
@@ -1,191 +1,272 @@
|
|||||||
# ✅ Project Status Report
|
# tic-tac-toe — Authoritative Multiplayer Game Server (Nakama + Go)
|
||||||
## Multiplayer Tic-Tac-Toe Platform
|
|
||||||
|
|
||||||
**To:** CTO & Technical Interview Panel
|
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**.
|
||||||
|
|
||||||
**Date:** November 25, 2025
|
|
||||||
|
|
||||||
**Version:** v0.0.1
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **1. Objective**
|
## 🚀 Overview
|
||||||
|
|
||||||
Design and implement a lightweight, scalable, server-authoritative multiplayer game system using **Nakama + Go plugins**, supporting authentication, matchmaking, real-time gameplay, and leaderboards — deployable to Google Cloud for demonstration.
|
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).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **2. Current Completion Summary**
|
## ⭐ Key Features
|
||||||
|
|
||||||
| Requirement | Status |
|
* **Authoritative Go match handler** (`tictactoe`)
|
||||||
| ---------------------------------------- | -------------------------------- |
|
* Device-ID authentication + JWT session
|
||||||
| Install Nakama + PostgreSQL | ✅ Completed |
|
* Matchmaking queue support
|
||||||
| Custom Go server plugins | ✅ Completed |
|
* Deterministic game validation
|
||||||
| Server-authoritative Tic-Tac-Toe | ✅ Completed |
|
* Match lifecycle handling
|
||||||
| Real-time WebSocket communication | ✅ Completed |
|
* Disconnect handling & forfeit detection
|
||||||
| Device-based authentication | ✅ Completed |
|
* Leaderboards creation + scoring
|
||||||
| JWT-based session management | ✅ Completed |
|
* Production-grade CI/CD with Drone
|
||||||
| Match creation & joining | ✅ Completed |
|
* Automated ARM Docker builds
|
||||||
| Matchmaking queue support | 🟡 Not Started |
|
* Full Traefik routing (HTTP + WebSocket)
|
||||||
| Game state validation & turn enforcement | 🟡 Not Started |
|
* Compatible with x86/ARM/GCP
|
||||||
| Leaderboard/tracking foundation | 🟡 Not Started |
|
|
||||||
| UI Game Client | 🟡 Not Started |
|
|
||||||
| Google Cloud deployment | 🟡 Not Started |
|
|
||||||
|
|
||||||
✅ **Core backend functionality is complete and stable**
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **3. Core Technical Architecture**
|
## 🧩 Architecture
|
||||||
|
|
||||||
* **Backend Framework:** Nakama 3.x
|
### High-Level System Diagram
|
||||||
* **Business Logic:** Custom Go runtime module
|
|
||||||
* **Database:** PostgreSQL 14
|
```mermaid
|
||||||
* **Transport:** WebSockets (real-time)
|
flowchart LR
|
||||||
* **Authentication:** Device-ID based auth → JWT session returned
|
UI[(React + Vite)] --> Traefik
|
||||||
* **State Management:** Server-authoritative, deterministic
|
Traefik --> Nakama[Nakama Server]
|
||||||
* **Protocol:** Nakama RT JSON envelopes
|
Nakama --> Plugin[Go Plugin]
|
||||||
* **Build & Deployment:** Docker-based
|
Nakama --> Postgres[(PostgreSQL)]
|
||||||
|
Drone[Drone CI/CD] --> Registry[Private Docker Registry]
|
||||||
|
Registry --> Nakama
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **4. Authentication**
|
## 🛠 Tech Stack
|
||||||
|
|
||||||
Implemented **Nakama device authentication flow**:
|
**Backend**
|
||||||
|
|
||||||
1. Client provides device UUID
|
* Nakama 3.21.0 ARM
|
||||||
2. Nakama validates & creates account if needed
|
* Go 1.21.6 (plugin ABI compatible)
|
||||||
3. Server responds with **JWT session token**
|
* PostgreSQL 16
|
||||||
4. Client uses JWT for all WebSocket connections
|
* Docker / multi-stage builds
|
||||||
|
* Drone CI/CD
|
||||||
|
* Traefik reverse proxy
|
||||||
|
|
||||||
|
**Cloud/Infra**
|
||||||
|
|
||||||
|
* GCP-ready
|
||||||
|
* ARM homelab deployments
|
||||||
|
* Private registry support
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **5. Game Server Logic**
|
## 📦 Repository Structure
|
||||||
|
|
||||||
Implemented as Go match module:
|
```
|
||||||
|
tic-tac-toe/
|
||||||
* Turn-based validation
|
│── plugins/
|
||||||
* Board occupancy checks
|
│ ├── main.go
|
||||||
* Win/draw/forfeit detection
|
│ ├── match.go
|
||||||
* Automatic broadcast of updated state
|
│ └── matchmaking.go
|
||||||
* Graceful match termination
|
│
|
||||||
* Prevents cheating & client-side manipulation
|
│── Dockerfile
|
||||||
|
│── go.mod
|
||||||
Result:
|
│── go.sum
|
||||||
✅ Entire game lifecycle enforced server-side.
|
│── README.md
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **6. Real-Time Networking**
|
## 🔌 Registered Server Components
|
||||||
|
|
||||||
Clients communicate via:
|
### 📌 Match Handler
|
||||||
|
|
||||||
* `match_create`
|
Name: **`tictactoe`**
|
||||||
* `match_join`
|
|
||||||
* `match_data_send` (OpCode 1) → moves
|
|
||||||
* Broadcast state updates (OpCode 2)
|
|
||||||
|
|
||||||
Python WebSocket simulation confirms:
|
Handles:
|
||||||
✅ Move sequencing
|
|
||||||
✅ Session isolation
|
* Turn validation
|
||||||
✅ Messaging reliability
|
* State updates
|
||||||
✅ Auto-cleanup on disconnect
|
* 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 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **7. Matchmaking**
|
## 🎮 Gameplay Protocol
|
||||||
|
|
||||||
**NOT STARTED**
|
### OpCodes
|
||||||
|
|
||||||
|
| OpCode | Direction | Meaning |
|
||||||
|
| ------ | --------------- | ----------------------------- |
|
||||||
|
| **1** | Client → Server | Submit move `{x, y}` |
|
||||||
|
| **2** | Server → Client | Full authoritative game state |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **8. Testing & Validation**
|
## 🧠 Authoritative Flow Diagram
|
||||||
|
|
||||||
Performed using:
|
```mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
participant C1 as Client 1
|
||||||
|
participant C2 as Client 2
|
||||||
|
participant S as Nakama + Go Plugin
|
||||||
|
|
||||||
* Automated two-client WebSocket game flow - Happy path
|
C1->>S: Matchmaker Join
|
||||||
|
C2->>S: Matchmaker Join
|
||||||
**PENDING STRESS AND EDGE CASE TESTING**
|
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)
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **9. UI Status**
|
## ⚙️ Build & Development
|
||||||
|
|
||||||
Not implemented yet — intentionally deferred.
|
### Build Go Plugin
|
||||||
|
|
||||||
Planned:
|
```
|
||||||
|
CGO_ENABLED=1 go build \
|
||||||
|
--trimpath \
|
||||||
|
--buildmode=plugin \
|
||||||
|
-o build/main.so \
|
||||||
|
./plugins
|
||||||
|
```
|
||||||
|
|
||||||
* Simple browser/mobile client
|
### Run Nakama Locally
|
||||||
* Display board, turns, win state
|
|
||||||
* WebSocket integration
|
|
||||||
* Leaderboard screen
|
|
||||||
|
|
||||||
Estimated time: **6–10 hours**
|
```
|
||||||
|
nakama migrate up --database.address "$DB_ADDR"
|
||||||
|
nakama \
|
||||||
|
--database.address "$DB_ADDR" \
|
||||||
|
--socket.server_key="$SERVER_KEY"
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **10. Leaderboard System**
|
## 🐳 Docker Build (Multi-Stage)
|
||||||
|
|
||||||
Backend-ready but not finalized:
|
```dockerfile
|
||||||
|
FROM --platform=linux/arm64 golang:1.21.6 AS plugin_builder
|
||||||
|
|
||||||
✅ Database & Nakama leaderboard APIs available
|
RUN go mod download
|
||||||
✅ Game result reporting planned
|
COPY . .
|
||||||
🟡 Ranking, ELO, win streak logic pending
|
RUN CGO_ENABLED=1 go build --buildmode=plugin -o build/main.so ./plugins
|
||||||
|
|
||||||
Estimated time: **4–6 hours**
|
FROM heroiclabs/nakama:3.21.0-arm
|
||||||
|
COPY --from=plugin_builder /workspace/build/main.so /nakama/data/modules/main.so
|
||||||
|
ENTRYPOINT ...
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **11. Google Cloud Deployment (Interview-Scope)**
|
## 🤖 CI/CD — Drone Pipeline
|
||||||
|
|
||||||
Goal: **Simple, affordable, demo-ready deployment**
|
Drone performs:
|
||||||
|
|
||||||
### Planned architecture:
|
1. Fetch latest Git tag
|
||||||
|
2. Check if Docker image already exists
|
||||||
|
3. Build Nakama + plugin
|
||||||
|
4. Push to private registry
|
||||||
|
5. Stop old container
|
||||||
|
6. Deploy new Nakama server automatically
|
||||||
|
|
||||||
* Highly subjective as of now
|
Full pipeline included in repository (`.drone.yml`).
|
||||||
|
|
||||||
| Component | GCP Service |
|
|
||||||
| ------------- | ----------------------------- |
|
|
||||||
| Nakama server | Compute Engine VM (Docker) |
|
|
||||||
| PostgreSQL | Cloud SQL (shared tier) |
|
|
||||||
| Game UI | Cloud Run or Firebase Hosting |
|
|
||||||
| Networking | Static IP + HTTPS |
|
|
||||||
| Auth secrets | Secret Manager (optional) |
|
|
||||||
|
|
||||||
Estimated setup time: **6–8 hours**
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **12. Risks & Considerations**
|
## 🌐 Traefik Routing
|
||||||
|
|
||||||
| Risk | Mitigation |
|
### HTTPS
|
||||||
| ------------------------ | ------------------------- |
|
|
||||||
| No UI yet | Prioritized next |
|
|
||||||
| Only happy path tested | In parallel with UI work |
|
|
||||||
| Matchmaking incomplete | Clear implementation plan |
|
|
||||||
| Leaderboard incomplete | Clear implementation plan |
|
|
||||||
|
|
||||||
None block demonstration or evaluation.
|
```
|
||||||
|
nakama.aetoskia.com
|
||||||
|
/ → HTTP API
|
||||||
|
/ws → WebSocket (real-time)
|
||||||
|
```
|
||||||
|
|
||||||
|
Includes:
|
||||||
|
|
||||||
|
* CORS rules
|
||||||
|
* WebSocket upgrade headers
|
||||||
|
* Certificate resolver
|
||||||
|
* Secure default middlewares
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **13. Next Steps**
|
## 🔧 Environment Variables
|
||||||
|
|
||||||
1. Implement browser/mobile UI
|
| Variable | Description |
|
||||||
2. Stress, load and Edge case testing
|
| --------------- | ---------------------------- |
|
||||||
3. Complete match making, leaderboard scoring
|
| `DB_ADDR` | PostgreSQL connection string |
|
||||||
4. Deploy to Google Cloud for public access
|
| `SERVER_KEY` | Nakama server key |
|
||||||
5. Record demo video + documentation
|
| `REGISTRY_HOST` | Private registry |
|
||||||
|
|
||||||
Estimated remaining effort: **1.5–2.5 days**
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **Executive Summary**
|
## 📊 Leaderboards
|
||||||
|
|
||||||
The foundational backend for the multiplayer Tic-Tac-Toe platform is fully implemented, stable, and validated over real-time WebSocket communication. Core features—authentication, session management, game state handling, and authoritative gameplay—are complete and functioning reliably.
|
* Created during server start
|
||||||
|
* Score: `+1` on win
|
||||||
|
* Metadata logged (mode, player IDs)
|
||||||
|
|
||||||
Remaining deliverables, including UI development, matchmaking, extended test coverage, leaderboard logic, and Google Cloud deployment, are intentionally pending to align effort with interview scope and timelines. These are well-defined, low-risk, and can be completed within the estimated timeframe.
|
---
|
||||||
|
|
||||||
**The project is technically strong, progressing as planned, and positioned for successful final delivery and demonstration.**
|
## 🧪 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
|
||||||
|
|
||||||
|
1. Fork repo
|
||||||
|
2. Create feature branch
|
||||||
|
3. Write tests
|
||||||
|
4. Submit PR
|
||||||
|
|
||||||
|
Coding style: Go fmt + idiomatic Go; follow Nakama plugin constraints.
|
||||||
|
|
||||||
|
---
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ services:
|
|||||||
- "/bin/sh"
|
- "/bin/sh"
|
||||||
- "-ecx"
|
- "-ecx"
|
||||||
- >
|
- >
|
||||||
/nakama/nakama migrate up --database.address postgres:localdb@postgres:5432/nakama?sslmode=disable &&
|
/nakama/nakama migrate up --database.address "$DB_ADDR" &&
|
||||||
exec /nakama/nakama --config /nakama/data/local.yml --database.address postgres:localdb@postgres:5432/nakama?sslmode=disable
|
exec /nakama/nakama --database.address "$DB_ADDR" --socket.server_key="$SERVER_KEY"
|
||||||
volumes:
|
volumes:
|
||||||
- ./local.yml:/nakama/data/local.yml
|
- ./local.yml:/nakama/data/local.yml
|
||||||
- ./build:/nakama/data/modules
|
- ./build:/nakama/data/modules
|
||||||
|
|||||||
Reference in New Issue
Block a user