Major networking overhaul to reduce latency and bandwidth: UDP Protocol Implementation: - Created UDP server handler with sequence number tracking (uint32 with wrapping support) - Implemented 1000-packet window for reordering tolerance - Packet structure: [seq_num(4) + msg_type(1) + update_id(2) + payload] - Handles 4+ billion packets without sequence number issues - Auto-fallback to TCP on >20% packet loss Binary Codec with Schema Versioning: - Extensible field-based format with version negotiation - Position encoding: 11-bit packed (6-bit x + 5-bit y for 40x30 grid) - Delta encoding for snake bodies: 2 bits per segment direction - Variable-length integers for compact numbers - String encoding: up to 16 chars with 4-bit length prefix - Player ID hashing: CRC32 for compact representation - zlib compression for payload reduction Partial Update System: - Splits large game states into independent packets <1280 bytes (IPv6 MTU) - Each packet is self-contained (packet loss affects only subset of snakes) - Smart snake segmenting for very long snakes (>100 segments) - Player name caching: sent once per player, then omitted - Metadata (food, game_running) separated from snake data 32-Player Support: - Extended COLOR_SNAKES array to 32 distinct colors - Server enforces MAX_PLAYERS=32 limit - Player names limited to MAX_PLAYER_NAME_LENGTH=16 - Name validation and sanitization - Color assignment with rotation through 32 colors Desktop Client Components: - UDP client with automatic TCP fallback - Partial state reassembly and tracking - Sequence validation and duplicate detection - Statistics tracking for fallback decisions Web Client Components: - 32-color palette matching Python colors - JavaScript binary codec (mirrors Python implementation) - Partial state tracker for reassembly - WebRTC DataChannel transport skeleton (for future use) - Graceful fallback to WebSocket Server Integration: - UDP server on port 8890 (configurable via --udp-port) - Integrated with existing TCP (8888) and WebSocket (8889) servers - Proper cleanup on shutdown - Command-line argument: --udp-port (0 to disable, default 8890) Performance Improvements: - ~75% bandwidth reduction (binary + compression vs JSON) - All packets guaranteed <1280 bytes (safe for all networks) - UDP eliminates TCP head-of-line blocking for lower latency - Independent partial updates gracefully handle packet loss - Delta encoding dramatically reduces snake body size Comprehensive Testing: - 46 tests total, all passing (100% success rate) - 15 UDP protocol tests (sequence wrapping, packet parsing, compression) - 20 binary codec tests (encoding, delta compression, strings, varint) - 11 partial update tests (splitting, reassembly, packet loss resilience) Files Added: - src/shared/binary_codec.py: Extensible binary serialization - src/shared/udp_protocol.py: UDP packet handling with sequence numbers - src/server/udp_handler.py: Async UDP server - src/server/partial_update.py: State splitting logic - src/client/udp_client.py: Desktop UDP client with TCP fallback - src/client/partial_state_tracker.py: Client-side reassembly - web/binary_codec.js: JavaScript binary codec - web/partial_state_tracker.js: JavaScript reassembly - web/webrtc_transport.js: WebRTC transport (ready for future use) - tests/test_udp_protocol.py: UDP protocol tests - tests/test_binary_codec.py: Binary codec tests - tests/test_partial_updates.py: Partial update tests 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
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:
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
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):
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:
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:
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:
<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:
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:
[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:
sudo systemctl daemon-reload
sudo systemctl enable snake-game
sudo systemctl start snake-game
sudo systemctl status snake-game
Firewall Configuration
Open required ports:
# 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