Add web client with WebSocket support
Implemented browser-based web client alongside existing pygame desktop client with dual-protocol server architecture supporting both TCP and WebSocket. Backend Changes: - Refactored GameServer for dual-protocol support (TCP + WebSocket) - Added WebSocketHandler for handling WebSocket connections - Added HTTPServer using aiohttp for serving web client files - Updated protocol handling to work with both connection types - Server tracks clients with protocol metadata (TCP/WebSocket) - Protocol-agnostic message sending and broadcasting - Added WebSocket port (8889) and HTTP port (8000) configuration Web Client: - Complete HTML5/CSS/JavaScript implementation - Responsive dark-themed UI - HTML5 Canvas rendering matching pygame visual style - WebSocket connection with auto-detected server URL - Real-time multiplayer gameplay in browser - Player list with scores and status - Mobile-friendly responsive design Deployment Options: - Development: Built-in HTTP server for local testing - Production: Disable HTTP server, use nginx/Apache for static files - Flexible server configuration (--no-http, --no-websocket flags) - Comprehensive nginx/Apache deployment documentation New Files: - src/server/websocket_handler.py - WebSocket connection handler - src/server/http_server.py - Static file server - web/index.html - Web client interface - web/style.css - Responsive styling - web/protocol.js - Protocol implementation - web/game.js - Game client with Canvas rendering - web/README.md - Deployment documentation Updated Files: - requirements.txt - Added websockets and aiohttp dependencies - src/server/game_server.py - Dual-protocol support - src/shared/constants.py - WebSocket and HTTP port constants - run_server.py - Server options for web support - README.md - Web client documentation - CLAUDE.md - Architecture documentation Features: - Web and desktop clients can play together simultaneously - Same JSON protocol for both client types - Independent server components (disable what you don't need) - Production-ready with reverse proxy support 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
241
web/README.md
Normal file
241
web/README.md
Normal file
@@ -0,0 +1,241 @@
|
||||
# Web Client Deployment
|
||||
|
||||
This directory contains the web client for the Multiplayer Snake game.
|
||||
|
||||
## Development Mode
|
||||
|
||||
For local development, use the built-in HTTP server:
|
||||
|
||||
```bash
|
||||
python run_server.py --name "Dev Server"
|
||||
```
|
||||
|
||||
This starts:
|
||||
- TCP server on port 8888 (for pygame clients)
|
||||
- WebSocket server on port 8889 (for web clients)
|
||||
- HTTP server on port 8000 (serving web files)
|
||||
|
||||
Access the web client at: http://localhost:8000
|
||||
|
||||
## Production Deployment with nginx
|
||||
|
||||
For production, disable the built-in HTTP server and use nginx to serve static files and proxy WebSocket connections.
|
||||
|
||||
### Step 1: Run server without HTTP
|
||||
|
||||
```bash
|
||||
python run_server.py --no-http --host 0.0.0.0
|
||||
```
|
||||
|
||||
### Step 2: Configure nginx
|
||||
|
||||
Create an nginx configuration file (e.g., `/etc/nginx/sites-available/snake-game`):
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name snake.example.com;
|
||||
|
||||
# Serve static web files
|
||||
location / {
|
||||
root /path/to/multiplayer-snake/web;
|
||||
try_files $uri $uri/ /index.html;
|
||||
|
||||
# Cache static assets
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
}
|
||||
|
||||
# Proxy WebSocket connections
|
||||
location /ws {
|
||||
proxy_pass http://localhost:8889;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# WebSocket timeouts
|
||||
proxy_read_timeout 86400;
|
||||
proxy_send_timeout 86400;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Enable the site:
|
||||
|
||||
```bash
|
||||
sudo ln -s /etc/nginx/sites-available/snake-game /etc/nginx/sites-enabled/
|
||||
sudo nginx -t
|
||||
sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
### Step 3: Update web client URL
|
||||
|
||||
Users should connect to: `ws://snake.example.com/ws` (or `wss://` for SSL)
|
||||
|
||||
## SSL/TLS Support (HTTPS + WSS)
|
||||
|
||||
For secure connections with Let's Encrypt:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name snake.example.com;
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name snake.example.com;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/snake.example.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/snake.example.com/privkey.pem;
|
||||
|
||||
# SSL configuration
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
|
||||
|
||||
# Static files
|
||||
location / {
|
||||
root /path/to/multiplayer-snake/web;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# Secure WebSocket
|
||||
location /ws {
|
||||
proxy_pass http://localhost:8889;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
proxy_read_timeout 86400;
|
||||
proxy_send_timeout 86400;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Apache Configuration
|
||||
|
||||
For Apache with mod_proxy_wstunnel:
|
||||
|
||||
```apache
|
||||
<VirtualHost *:80>
|
||||
ServerName snake.example.com
|
||||
DocumentRoot /path/to/multiplayer-snake/web
|
||||
|
||||
<Directory /path/to/multiplayer-snake/web>
|
||||
Options -Indexes +FollowSymLinks
|
||||
AllowOverride None
|
||||
Require all granted
|
||||
</Directory>
|
||||
|
||||
# WebSocket proxy
|
||||
ProxyPass /ws ws://localhost:8889
|
||||
ProxyPassReverse /ws ws://localhost:8889
|
||||
|
||||
# Enable WebSocket
|
||||
RewriteEngine On
|
||||
RewriteCond %{HTTP:Upgrade} websocket [NC]
|
||||
RewriteCond %{HTTP:Connection} upgrade [NC]
|
||||
RewriteRule /ws/(.*) ws://localhost:8889/$1 [P,L]
|
||||
</VirtualHost>
|
||||
```
|
||||
|
||||
Enable required modules:
|
||||
|
||||
```bash
|
||||
sudo a2enmod proxy proxy_http proxy_wstunnel rewrite
|
||||
sudo systemctl restart apache2
|
||||
```
|
||||
|
||||
## Caddy Configuration
|
||||
|
||||
Caddy makes it even simpler with automatic HTTPS:
|
||||
|
||||
```
|
||||
snake.example.com {
|
||||
root * /path/to/multiplayer-snake/web
|
||||
file_server
|
||||
|
||||
handle /ws {
|
||||
reverse_proxy localhost:8889
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Systemd Service
|
||||
|
||||
Create `/etc/systemd/system/snake-game.service`:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Snake Game Server
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=www-data
|
||||
WorkingDirectory=/path/to/multiplayer-snake
|
||||
ExecStart=/path/to/multiplayer-snake/venv/bin/python run_server.py --no-http --host 0.0.0.0
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Enable and start:
|
||||
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable snake-game
|
||||
sudo systemctl start snake-game
|
||||
sudo systemctl status snake-game
|
||||
```
|
||||
|
||||
## Firewall Configuration
|
||||
|
||||
Open required ports:
|
||||
|
||||
```bash
|
||||
# HTTP/HTTPS (nginx/Apache)
|
||||
sudo ufw allow 80/tcp
|
||||
sudo ufw allow 443/tcp
|
||||
|
||||
# Game server TCP (if accessed directly)
|
||||
sudo ufw allow 8888/tcp
|
||||
|
||||
# WebSocket (if not behind proxy)
|
||||
sudo ufw allow 8889/tcp
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### WebSocket connection fails
|
||||
|
||||
- Check firewall rules
|
||||
- Verify nginx/Apache WebSocket proxy configuration
|
||||
- Check browser console for errors
|
||||
- Test WebSocket endpoint: `wscat -c ws://your-server:8889`
|
||||
|
||||
### Static files not loading
|
||||
|
||||
- Verify nginx root path is correct
|
||||
- Check file permissions: `chmod -R 755 /path/to/web`
|
||||
- Check nginx error logs: `sudo tail -f /var/log/nginx/error.log`
|
||||
|
||||
### Game server not starting
|
||||
|
||||
- Check if ports are already in use: `sudo netstat -tulpn | grep 8889`
|
||||
- Review server logs
|
||||
- Verify Python dependencies are installed
|
||||
Reference in New Issue
Block a user