Compare commits
30 Commits
v0.2.0.3b
...
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 |
59
.drone.yml
59
.drone.yml
@@ -17,7 +17,7 @@ volumes:
|
||||
|
||||
steps:
|
||||
# -----------------------------------------------------
|
||||
# 1. Fetch latest Git tag
|
||||
# 1. Fetch latest Tags
|
||||
# -----------------------------------------------------
|
||||
- name: fetch-tags
|
||||
image: docker:24
|
||||
@@ -28,34 +28,43 @@ steps:
|
||||
- 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: $LATEST_TAG"
|
||||
echo "Latest Git tag fetched: $LATEST_TAG"
|
||||
|
||||
# Save to file for downstream steps
|
||||
echo "$LATEST_TAG" > /drone/src/LATEST_TAG.txt
|
||||
if [ -z "$LATEST_TAG" ]; then
|
||||
echo "❌ No git tags found. Cannot continue."
|
||||
|
||||
# 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 if remote image already exists
|
||||
# 2. Check existing Nakama Docker image
|
||||
# -----------------------------------------------------
|
||||
- name: check-remote-image
|
||||
image: docker:24
|
||||
volumes:
|
||||
- name: dockersock
|
||||
path: /var/run/docker.sock
|
||||
environment:
|
||||
REGISTRY_HOST:
|
||||
from_secret: REGISTRY_HOST
|
||||
commands:
|
||||
- IMAGE_TAG=$(cat /drone/src/LATEST_TAG.txt | tr -d '\n')
|
||||
- echo "Checking if $REGISTRY_HOST/lila-games/nakama-server:$IMAGE_TAG exists..."
|
||||
|
||||
- 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 pull $REGISTRY_HOST/lila-games/nakama-server:$IMAGE_TAG > /dev/null 2>&1; then
|
||||
echo "✅ Image already exists: $REGISTRY_HOST/lila-games/nakama-server:$IMAGE_TAG"
|
||||
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 "⚙️ Image does not exist. Will build."
|
||||
echo "⚙️ Docker image lila-games/nakama-server:$IMAGE_TAG not found — proceeding to build..."
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------
|
||||
@@ -68,22 +77,19 @@ steps:
|
||||
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:$IMAGE_TAG"
|
||||
|
||||
- echo "🔨 Building Nakama image lila-games/nakama-server:latest"
|
||||
- |
|
||||
docker build \
|
||||
--network=host \
|
||||
docker build --network=host \
|
||||
-t lila-games/nakama-server:$IMAGE_TAG \
|
||||
-t lila-games/nakama-server:latest \
|
||||
/drone/src
|
||||
|
||||
# -----------------------------------------------------
|
||||
# 4. Push Nakama image to registry
|
||||
# 4. Push Nakama Image
|
||||
# -----------------------------------------------------
|
||||
- name: push-image
|
||||
image: docker:24
|
||||
volumes:
|
||||
- name: dockersock
|
||||
path: /var/run/docker.sock
|
||||
environment:
|
||||
REGISTRY_HOST:
|
||||
from_secret: REGISTRY_HOST
|
||||
@@ -91,15 +97,20 @@ steps:
|
||||
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..."
|
||||
|
||||
- echo "🔑 Logging into registry $REGISTRY_HOST ..."
|
||||
- echo "$REGISTRY_PASS" | docker login $REGISTRY_HOST -u "$REGISTRY_USER" --password-stdin
|
||||
- echo "🏷️ Tagging images..."
|
||||
- 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 images..."
|
||||
- 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
|
||||
|
||||
# -----------------------------------------------------
|
||||
@@ -142,9 +153,7 @@ steps:
|
||||
--add-host private-pi:192.168.1.111 \
|
||||
-e DB_ADDR="$DB_ADDR" \
|
||||
-e SERVER_KEY="$SERVER_KEY" \
|
||||
-v /mnt/omnissiah-vault/data/nakama/modules:/nakama/data/modules \
|
||||
-v /mnt/omnissiah-vault/data/nakama/storage:/nakama/data \
|
||||
$REGISTRY_HOST/lila-games/nakama-server:$IMAGE_TAG
|
||||
lila-games/nakama-server:latest
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Pipeline trigger
|
||||
|
||||
17
Dockerfile
17
Dockerfile
@@ -1,21 +1,19 @@
|
||||
# -----------------------------------------------------
|
||||
# 1. Build the Nakama plugin (ARM64)
|
||||
# 1. Build the Nakama plugin
|
||||
# -----------------------------------------------------
|
||||
FROM golang:1.22-alpine AS plugin_builder
|
||||
FROM --platform=linux/arm64 golang:1.21.6 AS plugin_builder
|
||||
|
||||
# Install dependencies needed for CGO plugin build
|
||||
RUN apk add --no-cache git build-base
|
||||
RUN apt-get update && apt-get install -y \
|
||||
build-essential \
|
||||
git
|
||||
|
||||
WORKDIR /workspace
|
||||
|
||||
# Download module deps first (better caching)
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download
|
||||
|
||||
# Copy source code
|
||||
COPY . .
|
||||
|
||||
# Build plugin
|
||||
RUN mkdir -p build && \
|
||||
CGO_ENABLED=1 go build \
|
||||
--trimpath \
|
||||
@@ -25,12 +23,13 @@ RUN mkdir -p build && \
|
||||
|
||||
|
||||
# -----------------------------------------------------
|
||||
# 2. Build final Nakama image (ARM64)
|
||||
# 2. Build final Nakama image
|
||||
# -----------------------------------------------------
|
||||
FROM --platform=linux/arm64 heroiclabs/nakama:3.21.0 AS nakama
|
||||
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\""
|
||||
|
||||
403
README.md
403
README.md
@@ -1,287 +1,272 @@
|
||||
# ✅ Project Status Report
|
||||
# tic-tac-toe — Authoritative Multiplayer Game Server (Nakama + Go)
|
||||
|
||||
## Multiplayer Tic-Tac-Toe Platform
|
||||
|
||||
**To:** CTO & Technical Interview Panel
|
||||
|
||||
**Date:** November 28, 2025
|
||||
|
||||
**Version:** v0.2.0
|
||||
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**.
|
||||
|
||||
---
|
||||
|
||||
## **1. Objective**
|
||||
## 🚀 Overview
|
||||
|
||||
Design and implement a lightweight, scalable, server-authoritative multiplayer game system using **Nakama + Go plugins
|
||||
**, supporting authentication, matchmaking, authoritative gameplay, leaderboards, and a functional UI — 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 |
|
||||
|----------------------------------------------|--------------------------|
|
||||
| Install Nakama + PostgreSQL | ✅ Completed |
|
||||
| Custom Go server plugins | ✅ Completed |
|
||||
| Server-authoritative Tic-Tac-Toe | ✅ Completed |
|
||||
| Real-time WebSocket communication | ✅ Completed |
|
||||
| Device-based authentication | ✅ Completed |
|
||||
| JWT-based session management | ✅ Completed |
|
||||
| Match creation & joining | ✅ Completed |
|
||||
| **Matchmaking queue support** | ✅ Completed |
|
||||
| **Game state validation & turn enforcement** | ✅ Completed |
|
||||
| **Leaderboard system** | ✅ Completed |
|
||||
| **UI Game Client** | 🟡 Partially Implemented |
|
||||
| Google Cloud deployment | 🟡 Not Started |
|
||||
|
||||
✅ **Backend is fully authoritative and complete**
|
||||
🟡 **UI functional but missing polish, UX, and failure handling**
|
||||
* **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
|
||||
|
||||
---
|
||||
|
||||
## **3. Core Technical Architecture**
|
||||
## 🧩 Architecture
|
||||
|
||||
* **Backend Framework:** Nakama 3.x
|
||||
* **Business Logic:** Custom Go runtime module
|
||||
* **Frontend:** React + Vite + Nakama JS
|
||||
* **Database:** PostgreSQL 14
|
||||
* **Transport:** WebSockets (real-time)
|
||||
* **Authentication:** Device-ID based auth → JWT session returned
|
||||
* **State Management:** Fully server-authoritative
|
||||
* **Build & Deployment:** Docker-based
|
||||
### High-Level System Diagram
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
UI[(React + Vite)] --> Traefik
|
||||
Traefik --> Nakama[Nakama Server]
|
||||
Nakama --> Plugin[Go Plugin]
|
||||
Nakama --> Postgres[(PostgreSQL)]
|
||||
Drone[Drone CI/CD] --> Registry[Private Docker Registry]
|
||||
Registry --> Nakama
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## **4. Authentication**
|
||||
## 🛠 Tech Stack
|
||||
|
||||
### Backend
|
||||
**Backend**
|
||||
|
||||
* Device authentication, auto-account creation
|
||||
* JWT returned and used for RT connections
|
||||
* Nakama 3.21.0 ARM
|
||||
* Go 1.21.6 (plugin ABI compatible)
|
||||
* PostgreSQL 16
|
||||
* Docker / multi-stage builds
|
||||
* Drone CI/CD
|
||||
* Traefik reverse proxy
|
||||
|
||||
### UI
|
||||
**Cloud/Infra**
|
||||
|
||||
* Generates a device UUID and authenticates via `client.authenticateDevice()`
|
||||
* Stores and manages session state in React context
|
||||
* GCP-ready
|
||||
* ARM homelab deployments
|
||||
* Private registry support
|
||||
|
||||
---
|
||||
|
||||
## **5. Game Server Logic (Go)**
|
||||
## 📦 Repository Structure
|
||||
|
||||
Significant enhancements made:
|
||||
|
||||
### **✔ Initial State Broadcast**
|
||||
|
||||
* When the second player joins, the server immediately sends the full authoritative state.
|
||||
|
||||
### **✔ Complete Turn + Move Validation**
|
||||
|
||||
Rejects:
|
||||
|
||||
* out-of-bounds moves
|
||||
* occupied cells
|
||||
* wrong player's turn
|
||||
* invalid payloads
|
||||
|
||||
### **✔ Forfeit Handling**
|
||||
|
||||
* When a user disconnects or leaves, match ends in `forfeit`
|
||||
* Final state broadcast to remaining player
|
||||
|
||||
### **✔ Authoritative State Updates**
|
||||
|
||||
* Only broadcasts when state actually changes
|
||||
* Robust structured logging
|
||||
|
||||
Result:
|
||||
**Absolute server authority, zero trust in client.**
|
||||
```
|
||||
tic-tac-toe/
|
||||
│── plugins/
|
||||
│ ├── main.go
|
||||
│ ├── match.go
|
||||
│ └── matchmaking.go
|
||||
│
|
||||
│── Dockerfile
|
||||
│── go.mod
|
||||
│── go.sum
|
||||
│── README.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## **6. Real-Time Networking**
|
||||
## 🔌 Registered Server Components
|
||||
|
||||
Communication validated end-to-end:
|
||||
### 📌 Match Handler
|
||||
|
||||
* `match_create`
|
||||
* `match_join`
|
||||
* `matchmaker_add` / `matchmaker_matched`
|
||||
* `match_data_send` for moves (OpCode 1)
|
||||
* Server broadcasts state (OpCode 2)
|
||||
Name: **`tictactoe`**
|
||||
|
||||
Python simulators and UI both confirm:
|
||||
Handles:
|
||||
|
||||
* move ordering
|
||||
* correct enforcement of turn rules
|
||||
* correct state sync
|
||||
* stable WebSocket behavior
|
||||
* 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 |
|
||||
|
||||
---
|
||||
|
||||
## **7. Matchmaking System (Go + UI)**
|
||||
## 🎮 Gameplay Protocol
|
||||
|
||||
### **Backend (Go)**
|
||||
### OpCodes
|
||||
|
||||
* Implements `MatchmakerMatched` hook
|
||||
* Ensures both players:
|
||||
|
||||
* have valid `mode`
|
||||
* match modes
|
||||
* exactly two players
|
||||
* Creates authoritative matches server-side
|
||||
* RPC `leave_matchmaking` added
|
||||
|
||||
### **UI**
|
||||
|
||||
* Integrates matchmaking: mode selection → queue → ticket → matched → auto-join
|
||||
* Uses Nakama JS `socket.addMatchmaker()`
|
||||
|
||||
**Status:** Fully functional end-to-end
|
||||
| OpCode | Direction | Meaning |
|
||||
| ------ | --------------- | ----------------------------- |
|
||||
| **1** | Client → Server | Submit move `{x, y}` |
|
||||
| **2** | Server → Client | Full authoritative game state |
|
||||
|
||||
---
|
||||
|
||||
## **8. Leaderboard System (Go + UI)**
|
||||
## 🧠 Authoritative Flow Diagram
|
||||
|
||||
### **Backend (Go)**
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant C1 as Client 1
|
||||
participant C2 as Client 2
|
||||
participant S as Nakama + Go Plugin
|
||||
|
||||
* Leaderboard auto-created on startup
|
||||
* On win:
|
||||
C1->>S: Matchmaker Join
|
||||
C2->>S: Matchmaker Join
|
||||
S->>S: MatchmakerMatched()
|
||||
S-->>C1: Matched
|
||||
S-->>C2: Matched
|
||||
|
||||
* winner identified
|
||||
* username resolved
|
||||
* score incremented (+1 win)
|
||||
* metadata logged
|
||||
|
||||
### **UI**
|
||||
|
||||
* Implements leaderboard view using `client.listLeaderboardRecords()`
|
||||
* Read-only UI display works
|
||||
|
||||
### **Remaining**
|
||||
|
||||
* UI sorting, layout, styling
|
||||
* No leaderboard write actions needed from UI
|
||||
C1->>S: OpCode 1 (Move)
|
||||
S->>S: Validate Move
|
||||
S-->>C1: OpCode 2 (Updated State)
|
||||
S-->>C2: OpCode 2 (Updated State)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## **9. UI Implementation Status (React + Vite)**
|
||||
## ⚙️ Build & Development
|
||||
|
||||
### **What Is Implemented**
|
||||
### Build Go Plugin
|
||||
|
||||
- ✔ Authentication flow (device auth)
|
||||
- ✔ WebSocket session handling
|
||||
- ✔ Matchmaking (classic/blitz modes)
|
||||
- ✔ Automatic match join
|
||||
- ✔ Move sending (OpCode 1)
|
||||
- ✔ State updates (OpCode 2)
|
||||
- ✔ Board rendering and interactive cells
|
||||
- ✔ End-of-game messaging
|
||||
- ✔ Leaderboard display
|
||||
```
|
||||
CGO_ENABLED=1 go build \
|
||||
--trimpath \
|
||||
--buildmode=plugin \
|
||||
-o build/main.so \
|
||||
./plugins
|
||||
```
|
||||
|
||||
### **Partially Implemented**
|
||||
### Run Nakama Locally
|
||||
|
||||
- 🟡 Match mode UI selection wired but not visually emphasized
|
||||
- 🟡 Context handles all RT states but missing error handling
|
||||
|
||||
### **Not Implemented / Missing**
|
||||
|
||||
- 🔴 Reconnect flow (UI does not recover session after WS drop)
|
||||
- 🔴 No error UI for: matchmaking failure, move rejection, disconnects
|
||||
- 🔴 No UI for leaving match or returning to lobby
|
||||
- 🔴 No rematch button / flow
|
||||
- 🔴 No transitions, animations, or mobile layout
|
||||
- 🔴 No global app shell (Routing, Home Screen, etc.)
|
||||
|
||||
**Summary:** UI is *functional* and capable of playing full authoritative games, but lacks UX polish and failure
|
||||
handling.
|
||||
```
|
||||
nakama migrate up --database.address "$DB_ADDR"
|
||||
nakama \
|
||||
--database.address "$DB_ADDR" \
|
||||
--socket.server_key="$SERVER_KEY"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## **10. Testing & Validation**
|
||||
## 🐳 Docker Build (Multi-Stage)
|
||||
|
||||
### Backend
|
||||
```dockerfile
|
||||
FROM --platform=linux/arm64 golang:1.21.6 AS plugin_builder
|
||||
|
||||
* Extensive scenario tests: draws, wins, illegal moves, disconnects
|
||||
* Matchmaking simulation across N clients
|
||||
RUN go mod download
|
||||
COPY . .
|
||||
RUN CGO_ENABLED=1 go build --buildmode=plugin -o build/main.so ./plugins
|
||||
|
||||
### UI
|
||||
|
||||
* Verified:
|
||||
|
||||
* matchmaking
|
||||
* game correctness
|
||||
* leaderboard retrieval
|
||||
* state sync
|
||||
* Missing:
|
||||
|
||||
* stress testing
|
||||
* reconnection scenarios
|
||||
* mobile layout testing
|
||||
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**
|
||||
## 🤖 CI/CD — Drone Pipeline
|
||||
|
||||
Planned architecture remains:
|
||||
Drone performs:
|
||||
|
||||
| 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) |
|
||||
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
|
||||
|
||||
Estimated setup time: **6–8 hours**
|
||||
Full pipeline included in repository (`.drone.yml`).
|
||||
|
||||
---
|
||||
|
||||
## **12. Risks & Considerations**
|
||||
## 🌐 Traefik Routing
|
||||
|
||||
| Risk | Mitigation |
|
||||
|--------------------------------|--------------------------------|
|
||||
| UI lacks error/reconnect logic | Add retry + reconnection flows |
|
||||
| No rematch or lobby UX | Add match lifecycle UI |
|
||||
| No mobile layout | Add responsive CSS |
|
||||
| Cloud deployment pending | Prioritize after UI polish |
|
||||
| Matchmaking UX is minimal | Add feedback, loading states |
|
||||
### HTTPS
|
||||
|
||||
None of these affect core backend stability.
|
||||
```
|
||||
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
|
||||
|
||||
### **UI Tasks**
|
||||
|
||||
1. Add reconnect + error-handling UI
|
||||
2. Create lobby → gameplay → results, flow
|
||||
3. Add rematch capability
|
||||
4. Add responsive + polished UI
|
||||
5. Add loading indicators & animations
|
||||
|
||||
Estimated remaining effort: **6 to 8 hours**
|
||||
| Variable | Description |
|
||||
| --------------- | ---------------------------- |
|
||||
| `DB_ADDR` | PostgreSQL connection string |
|
||||
| `SERVER_KEY` | Nakama server key |
|
||||
| `REGISTRY_HOST` | Private registry |
|
||||
|
||||
---
|
||||
|
||||
## **Executive Summary**
|
||||
## 📊 Leaderboards
|
||||
|
||||
### Issues faced
|
||||
Several unexpected integration challenges during UI setup contributed to the additional day of work. These included:
|
||||
- Aligning the UI’s matchmaking flow with the new authoritative Go-based matchmaking logic.
|
||||
- Handling Nakama JS WebSocket behaviors, especially around session timing, matchmaker ticket handling, and match join events.
|
||||
- Ensuring OpCode handling and server-produced state updates matched the server’s authoritative model.
|
||||
- Resolving environment-related issues (Vite dev server, Node version mismatches, and WebSocket URL configuration).
|
||||
- Debugging cross-origin and connection-reset issues during early WebSocket initialization.
|
||||
* Created during server start
|
||||
* Score: `+1` on win
|
||||
* Metadata logged (mode, player IDs)
|
||||
|
||||
These challenges required deeper synchronization between the backend and frontend layers, resulting in an additional **+1 day** of engineering time.
|
||||
---
|
||||
|
||||
### Project Progress
|
||||
The system now features a fully authoritative backend with matchmaking, gameplay logic, and leaderboards implemented
|
||||
completely in Go. The UI is functional and integrates correctly with all backend systems, supporting end-to-end
|
||||
matchmaking and gameplay.
|
||||
## 🧪 Testing
|
||||
|
||||
Key remaining work involves UI polish, recovery/error handling, and deployment setup. No major architectural risks
|
||||
remain.
|
||||
* Win/loss/draw simulation
|
||||
* Invalid move rejection
|
||||
* Disconnect → forfeit
|
||||
* Load testing matchmaking
|
||||
|
||||
**The project is now fully playable, technically solid, and ready for final UI enhancements and cloud deployment.**
|
||||
---
|
||||
|
||||
## 📈 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.
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user