git clone https://molodetz.nl/retoor/city.git
Raw source file available here .
# WARP.md
This file provides guidance to WARP (warp.dev) when working with code in this repository.
Development Commands
Quick Start
# Create virtual environment and install dependencies
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
# Run the game server
python run.py
# Or directly:
python -m uvicorn server.main:app --host 127.0.0.1 --port 9901 --reload
# Access the game at http://127.0.0.1:9901
Development Commands
# Start in development mode (auto-reload)
python -m uvicorn server.main:app --host 127.0.0.1 --port 9901 --reload
# Check database state (SQLite browser or CLI)
sqlite3 data/game.db
# Reset game state (delete database)
rm data/game.db
# Monitor logs (server runs with debug logging)
# Logs are printed to stdout
Dependencies
- Backend : FastAPI 0.118.0, uvicorn, websockets, pydantic
- Frontend : Three.js (via CDN), vanilla JavaScript ES6 modules
- Database : SQLite (built-in Python)
Architecture Overview
System Architecture
This is a real-time multiplayer city building game with a FastAPI backend and Three.js frontend, using WebSockets for live communication.
Key architectural patterns:
- Real-time multiplayer : WebSocket-based with instant synchronization
- Component-based UI : Web Components extending HTMLElement
- ES6 Module system : No bundling required, direct module imports
- Persistent game state : SQLite with auto-save every 10 seconds
- Hybrid economy system : Instant updates on player actions + timed background processing
Backend Architecture (
server/
directory)
Core Components:
-
main.py- FastAPI app with WebSocket endpoints and game lifecycle -
websocket_manager.py- Connection management, broadcasting, player sessions -
game_state.py- Building placement, road connectivity (flood-fill), validation -
economy.py- Economy calculations with connectivity bonuses -
database.py- SQLite persistence layer -
models.py- Data models (13 building types, player stats)
Key algorithms:
- Road connectivity : Flood-fill algorithm to calculate connected road zones
- Economy bonuses : Buildings connected to roads get 5% bonus per road in the zone
- Offline processing : Players earn 10% income when offline
Frontend Architecture (
static/js/
directory)
Main Classes:
-
App.js- Central coordinator, manages all systems -
GameRenderer.js- Three.js orthographic rendering, viewport culling -
WebSocketClient.js- Real-time communication with auto-reconnect -
InputHandler.js- Mouse/keyboard input, camera controls -
UIManager.js- Coordinates Web Components
UI Components
(
static/js/components/
):
-
LoginScreen.js- Nickname entry -
StatsDisplay.js- Money and population -
BuildingToolbox.js- Building selection with affordability checks -
ChatBox.js- IRC-style multiplayer chat -
ContextMenu.js- Right-click building actions
Game Logic
Building System:
- 13 building types across 5 categories (Residential, Commercial, Industrial, Infrastructure, Special)
- Complex requirement system (population, power, affordability)
- Player ownership with edit/delete permissions
Economy System:
- Tick-based (every 10 seconds)
- Road connectivity creates economic zones
- Offline players continue at 10% power
- Instant updates on building placement/removal
Multiplayer Features:
- Nickname-based authentication (no passwords)
- Real-time cursor synchronization (throttled to 100ms)
- Building synchronization across all clients
- Player-specific colors
- Live chat system
Development Guidelines
When modifying game mechanics:
-
Update
BUILDING_CONFIGSinmodels.pyfor building properties -
Modify
economy.pyfor income/cost calculations -
Road connectivity logic is in
game_state.py(_update_connected_zones)
When adding UI features:
- Create new Web Components extending HTMLElement
-
Register components in
UIManager.js - Follow the pattern of existing components for consistency
When modifying multiplayer:
-
WebSocket message types are defined in
websocket_manager.py - All state changes should broadcast to other players
-
Client-side optimistic updates in
App.js
Performance considerations:
- Renderer uses viewport culling (only renders visible tiles)
- Economy calculations are batched per tick
- WebSocket messages are throttled appropriately
- Database saves every 10 seconds (not on every action)
Database schema:
- Players: player_id, nickname, money, population, color, last_online
- Buildings: type, x, y, owner_id, name, placed_at
-
Auto-migration handled in
database.py
Game State Management
Critical state synchronization points:
- Building placement - Validates requirements, deducts money, broadcasts to all clients
- Economy ticks - Updates player money/population, triggers UI updates
- Player connections - Manages online/offline status, session resumption
- Road network changes - Recalculates connected zones for economy bonuses
Testing multiplayer:
- Open multiple browser tabs with different nicknames
- Verify building synchronization across clients
- Test chat functionality
- Verify cursor movement synchronization
- Test offline/online player transitions
File Structure Context
server/ # Python FastAPI backend
βββ main.py # App entry, WebSocket endpoints, game loop
βββ websocket_manager.py # Connection management
βββ game_state.py # Building logic, road connectivity
βββ economy.py # Economic calculations
βββ database.py # SQLite persistence
βββ models.py # Data structures, building configs
static/ # Frontend (served statically)
βββ index.html # Single-page app
βββ js/
β βββ App.js # Main coordinator
β βββ GameRenderer.js # Three.js rendering
β βββ WebSocketClient.js # Real-time communication
β βββ InputHandler.js # Input management
β βββ UIManager.js # Component coordination
β βββ components/ # Web Components
βββ css/style.css # Transport Tycoon-inspired styling
data/game.db # SQLite database (auto-created)
run.py # Convenience startup script
This is a complete, production-ready multiplayer game with persistent state, real-time communication, and sophisticated game mechanics. The codebase follows modern patterns and is well-structured for maintenance and feature additions.
Testing Framework
Test Commands
# Install test dependencies (if not already installed)
pip install -r requirements.txt
# Run all tests
pytest
# Run specific test categories
pytest tests/test_economy.py # Economy system tests
pytest tests/test_multiplayer.py # Multiplayer interaction tests
pytest tests/test_game_state.py # Game state and persistence tests
pytest tests/test_integration.py # End-to-end integration tests
# Run with verbose output
pytest -v
# Run specific test
pytest tests/test_economy.py::TestEconomySystem::test_building_costs -v
# Run tests with coverage (if coverage installed)
pytest --cov=server
Test Architecture
Test Client Utility
(
tests/test_client.py
):
-
TestWebSocketClient- Simulates real WebSocket connections -
test_clients()context manager for multiple simultaneous clients - Full API coverage: building placement, chat, cursor movement, etc.
Test Categories:
-
Economy Tests
(
test_economy.py) - Building costs, income calculations, road bonuses -
Multiplayer Tests
(
test_multiplayer.py) - Chat, cursor sync, building synchronization -
Game State Tests
(
test_game_state.py) - Database persistence, validation, state management -
Integration Tests
(
test_integration.py) - End-to-end scenarios, stress testing
Running Tests with Game Server
Important
: Tests require the game server to be running on
127.0.0.1:9901
.
# Terminal 1: Start the server
python run.py
# Terminal 2: Run tests (in separate terminal)
pytest
Test Coverage
WebSocket API Coverage:
- Building placement/removal with validation
- Chat message broadcasting
- Cursor movement synchronization
- Player join/leave notifications
- Error handling and edge cases
Economy System Coverage:
- Building cost deduction
- Income/expense calculations
- Road connectivity bonuses (5% per road in network)
- Offline player processing (10% income)
- Population and power requirements
Multiplayer Scenarios:
- Multiple simultaneous connections
- Real-time synchronization between clients
- Building ownership and permissions
- Competitive and collaborative gameplay
Database Persistence:
- Save/load complete game state
- Player reconnection with preserved data
- Building persistence across sessions
Testing Guidelines
When adding new features:
- Add unit tests for core logic
- Add WebSocket integration tests for client interactions
- Update integration tests for end-to-end scenarios
- Test multiplayer synchronization
Test Database:
- Tests use temporary databases to avoid affecting game data
- Database operations are tested with isolated fixtures
- Game state persistence is validated through reconnection tests
Async Test Patterns:
-
All WebSocket tests use
@pytest.mark.asyncio -
Tests simulate real timing with
asyncio.sleep() - Message collection uses timeouts to handle async communication
Stress Testing
The test suite includes stress tests for:
- Rapid building placement (20+ simultaneous actions)
- Chat message floods (30+ messages)
- Mixed action types (building + chat + cursor movement)
- Multiple player scenarios (4+ simultaneous clients)