Files
Vladyslav Doloman b221645750 Implement UDP protocol with binary compression and 32-player support
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>
2025-10-04 23:50:31 +03:00
..

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