#!/usr/bin/env python3 """ Comprehensive Game Server Documentation Generator for GSP Generates PHP documentation files for all games in the "todo" category Based on the Minecraft template structure """ import os import sys import json import yaml import re from pathlib import Path from datetime import datetime import xml.etree.ElementTree as ET class GameDocGenerator: def __init__(self, docs_dir, config_dir, knowledgepack_path): self.docs_dir = Path(docs_dir) self.config_dir = Path(config_dir) self.knowledgepack_path = Path(knowledgepack_path) self.knowledgepack_data = None self.xml_configs = {} def load_knowledgepack(self): """Load the YAML knowledgepack with game information""" try: with open(self.knowledgepack_path, 'r', encoding='utf-8') as f: data = yaml.safe_load(f) self.knowledgepack_data = data.get('games', []) print(f"Loaded knowledgepack with {len(self.knowledgepack_data)} games") return True except Exception as e: print(f"Error loading knowledgepack: {e}") return False def load_xml_configs(self): """Load all XML configuration files""" xml_files = list(self.config_dir.glob("*.xml")) for xml_file in xml_files: try: tree = ET.parse(xml_file) root = tree.getroot() game_key = root.find('game_key') if game_key is not None and game_key.text: self.xml_configs[game_key.text] = { 'file': xml_file.name, 'tree': root } except Exception as e: print(f"Error parsing {xml_file}: {e}") print(f"Loaded {len(self.xml_configs)} XML configurations") def get_game_info_from_knowledgepack(self, game_name): """Find game info in knowledgepack by name""" if not self.knowledgepack_data: return None # Try exact match first for game in self.knowledgepack_data: if game.get('name', '').lower() == game_name.lower(): return game # Try partial match for game in self.knowledgepack_data: if game_name.lower() in game.get('name', '').lower(): return game return None def get_xml_config(self, folder_name): """Find matching XML config for a folder""" # Try exact match for key, config in self.xml_configs.items(): if key.lower() == folder_name.lower() or key.lower().replace('_', '') == folder_name.lower(): return config['tree'] # Try partial match for key, config in self.xml_configs.items(): if folder_name.lower() in key.lower() or key.lower() in folder_name.lower(): return config['tree'] return None def extract_ports_from_xml(self, xml_root): """Extract port information from XML config""" ports = [] # Look for replace_texts with port keys replace_texts = xml_root.find('replace_texts') if replace_texts is not None: for text in replace_texts.findall('text'): key = text.get('key', '') if 'port' in key.lower(): filepath = text.find('filepath') if filepath is not None: ports.append({ 'key': key, 'file': filepath.text }) # Look for custom_fields with port information custom_fields = xml_root.find('custom_fields') if custom_fields is not None: for field in custom_fields.findall('field'): key = field.get('key', '') if 'port' in key.lower(): default_value = field.find('default_value') desc = field.find('desc') ports.append({ 'key': key, 'default': default_value.text if default_value is not None else None, 'description': desc.text if desc is not None else None }) return ports def extract_config_files_from_xml(self, xml_root): """Extract configuration file paths from XML""" config_files = [] config_files_elem = xml_root.find('configuration_files') if config_files_elem is not None: for file_elem in config_files_elem.findall('file'): desc = file_elem.get('description', 'Configuration file') path = file_elem.text if file_elem.text else '' config_files.append({ 'description': desc, 'path': path }) return config_files def generate_php_doc(self, folder_name, metadata): """Generate comprehensive PHP documentation for a game""" game_name = metadata.get('name', folder_name.replace('_', ' ').title()) # Get additional data kb_info = self.get_game_info_from_knowledgepack(game_name) xml_config = self.get_xml_config(folder_name) # Extract ports and configs ports_info = [] config_files = [] if xml_config is not None: ports_info = self.extract_ports_from_xml(xml_config) config_files = self.extract_config_files_from_xml(xml_config) # Build the PHP document php_content = self.build_php_content(game_name, folder_name, kb_info, xml_config, ports_info, config_files) return php_content def build_php_content(self, game_name, folder_name, kb_info, xml_config, ports_info, config_files): """Build the complete PHP documentation content""" # Extract data from various sources default_port = "Check server configuration" protocol = "TCP/UDP" min_ram = "1GB" engine = "Various" startup_cmd = "" if kb_info: network = kb_info.get('network', {}) default_ports = network.get('default_ports', []) if default_ports: port_info = default_ports[0] port_str = port_info.get('port', '') if '/' in port_str: default_port = port_str.split('/')[0] protocol = port_str.split('/')[1].upper() else: default_port = port_str requirements = kb_info.get('requirements', {}) min_ram = requirements.get('ram', '1GB') engine = kb_info.get('engine', 'Various') startup = kb_info.get('typical_startup', {}) startup_cmd = startup.get('linux', '') or startup.get('windows', '') php_doc = '''

📚 Quick Navigation

Quick Info 🔌 Ports Installation Configuration ⚙️ Startup Parameters 🔧 Troubleshooting Performance Security

''' + game_name + ''' Server Hosting Guide

Overview

''' + game_name + ''' is a multiplayer game server that can be hosted on a VPS or dedicated server. This comprehensive guide covers everything you need to know about hosting a ''' + game_name + ''' server for your community.

Quick Info

🔌 Network Ports

Required Ports

''' # Add port information if kb_info and kb_info.get('network', {}).get('default_ports'): php_doc += ''' ''' for port_info in kb_info['network']['default_ports']: port_str = port_info.get('port', '') purpose = port_info.get('purpose', 'Game server') port_num = port_str.split('/')[0] if '/' in port_str else port_str proto = port_str.split('/')[1].upper() if '/' in port_str else 'TCP/UDP' php_doc += f''' ''' # Add additional ports if available additional_ports = kb_info['network'].get('additional_ports', []) for port_info in additional_ports: port_str = port_info.get('port', '') purpose = port_info.get('purpose', 'Additional functionality') port_num = port_str.split('/')[0] if '/' in port_str else port_str proto = port_str.split('/')[1].upper() if '/' in port_str else 'TCP/UDP' php_doc += f''' ''' php_doc += '''
Port Protocol Purpose
{port_num} {proto} {purpose}
{port_num} {proto} {purpose} (Optional)
''' else: php_doc += '''

The ''' + game_name + ''' server typically uses a configurable port. Check your server configuration files for the specific port settings.

''' php_doc += '''

Firewall Configuration

Allow server ports through your firewall:

# UFW (Ubuntu/Debian)
sudo ufw allow [PORT]/tcp
sudo ufw allow [PORT]/udp
sudo ufw reload

# FirewallD (CentOS/RHEL)
sudo firewall-cmd --permanent --add-port=[PORT]/tcp
sudo firewall-cmd --permanent --add-port=[PORT]/udp
sudo firewall-cmd --reload

# Windows Firewall
netsh advfirewall firewall add rule name="''' + game_name + ''' Server" dir=in action=allow protocol=TCP localport=[PORT]
netsh advfirewall firewall add rule name="''' + game_name + ''' Server" dir=in action=allow protocol=UDP localport=[PORT]

⚠️ Port Security Notes

Installation & Setup

System Requirements

''' # Add dependencies if available if kb_info and kb_info.get('requirements', {}).get('dependencies'): dependencies = kb_info['requirements']['dependencies'] php_doc += '''

Required Dependencies

''' php_doc += '''

Installation Steps

Linux (Ubuntu/Debian)

# Update system packages
sudo apt update && sudo apt upgrade -y

# Create server directory
mkdir -p ~/gameserver
cd ~/gameserver

# Download server files (method varies by game)
# Check official documentation for download links
''' if startup_cmd: php_doc += f'''

Starting the Server

{startup_cmd}
''' php_doc += '''

Windows Server

Download the server files from the official game website or through Steam (if applicable). Extract to a dedicated folder and run the server executable.

Using SteamCMD (if applicable)

Many game servers can be installed via SteamCMD:

# Install SteamCMD (Ubuntu/Debian)
sudo apt install lib32gcc-s1 steamcmd

# Run SteamCMD
steamcmd

# Login and download (use your Steam credentials or anonymous)
login anonymous
force_install_dir /path/to/server
app_update [APP_ID] validate
quit

Server Configuration

After installation, configure your server through the configuration files typically located in the server directory.

Essential Settings

''' # Add config files section if available if config_files: php_doc += '''

Configuration Files

Important configuration files for this server:

''' php_doc += '''

Server Commands

Common administrative commands (access via console or RCON):

# Kick player
kick [player_name]

# Ban player
ban [player_name]

# Change map/level (syntax varies by game)
changelevel [map_name]

# Set admin password (if supported)
setadminpassword [password]

⚙️ Startup Parameters

Basic Startup

''' if startup_cmd: php_doc += f'''
{startup_cmd}
''' else: php_doc += '''
# Generic startup command structure
./server_executable [parameters]
''' php_doc += '''

Common Parameters

Creating a Start Script

Linux (start.sh):

#!/bin/bash
cd /path/to/server
./server_executable [parameters] 2>&1 | tee server.log
chmod +x start.sh
./start.sh

Windows (start.bat):

@echo off
cd /d "%~dp0"
server_executable.exe [parameters]
pause

Running as a Service

Linux (systemd):

# Create service file: /etc/systemd/system/gameserver.service
[Unit]
Description=''' + game_name + ''' Server
After=network.target

[Service]
Type=simple
User=gameserver
WorkingDirectory=/home/gameserver/server
ExecStart=/home/gameserver/server/start.sh
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
# Enable and start service
sudo systemctl daemon-reload
sudo systemctl enable gameserver
sudo systemctl start gameserver
sudo systemctl status gameserver

🔧 Troubleshooting

Server Won't Start

''' # Add troubleshooting from knowledgepack if available if kb_info and kb_info.get('troubleshooting', {}).get('common_issues'): issues = kb_info['troubleshooting']['common_issues'] for issue_item in issues: issue = issue_item.get('issue', '') fix = issue_item.get('fix', '') php_doc += f'''

{issue}

{fix}

''' else: php_doc += '''

Check Server Logs

# View recent log entries
tail -f server.log

# Or check system logs
journalctl -u gameserver -f

Port Already in Use

# Find what's using the port
sudo lsof -i :[PORT]
sudo netstat -tulpn | grep [PORT]

# Kill the process or change server port

Missing Dependencies

Ensure all required dependencies are installed. Check the error messages for missing libraries or packages.

''' php_doc += '''

Connection Issues

Can't Connect to Server

  1. Verify server is running: ps aux | grep server
  2. Check port is listening: netstat -an | grep [PORT]
  3. Verify firewall rules (see Ports section above)
  4. Check server IP: Use external IP, not localhost
  5. Router/NAT: Ensure port forwarding is configured

High Latency/Lag

Performance Issues

Server Lag

  1. Monitor resources: Use htop or top
  2. Check disk I/O: Use iotop
  3. Review server logs for errors or warnings
  4. Reduce player count or increase server resources
  5. Optimize configuration based on server capacity

Memory Leaks

# Monitor memory usage
free -h
top -p $(pgrep -f server)

# Restart server regularly via cron if needed
0 4 * * * /home/gameserver/restart.sh

Performance Optimization

Server Tuning

Operating System Optimization

# Increase file descriptor limits
echo "* soft nofile 65536" >> /etc/security/limits.conf
echo "* hard nofile 65536" >> /etc/security/limits.conf

# Network tuning
sysctl -w net.core.rmem_max=16777216
sysctl -w net.core.wmem_max=16777216
sysctl -w net.ipv4.tcp_rmem="4096 87380 16777216"
sysctl -w net.ipv4.tcp_wmem="4096 87380 16777216"

Monitoring

Set up monitoring to track server health:

Backup Strategy

#!/bin/bash
# backup.sh - Run via cron
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backups/gameserver"
SERVER_DIR="/home/gameserver/server"

# Create backup
tar -czf $BACKUP_DIR/backup_$DATE.tar.gz -C $SERVER_DIR .

# Keep only last 7 days
find $BACKUP_DIR -name "backup_*.tar.gz" -mtime +7 -delete

Security Best Practices

Firewall Configuration

# Minimal firewall - only allow necessary ports
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow [SERVER_PORT]/tcp
sudo ufw allow [SERVER_PORT]/udp
sudo ufw allow 22/tcp  # SSH
sudo ufw enable

Strong Passwords

Regular Updates

Access Control

DDoS Protection

Additional Resources

''' # Add references from knowledgepack if available if kb_info and kb_info.get('references'): php_doc += '''

External References

''' php_doc += '''

Important Notes

Last updated: ''' + datetime.now().strftime("%B %Y") + ''' | For ''' + game_name + ''' server hosting

''' return php_doc def process_todo_folders(self): """Process all folders with category 'todo' """ processed = 0 errors = [] # Find all todo folders for folder in self.docs_dir.iterdir(): if not folder.is_dir(): continue metadata_file = folder / 'metadata.json' index_file = folder / 'index.php' if not metadata_file.exists(): continue try: # Read metadata with open(metadata_file, 'r', encoding='utf-8') as f: content = f.read() # Remove BOM if present content = content.lstrip('\ufeff') metadata = json.loads(content) # Check if it's a todo category if metadata.get('category', '').lower() != 'todo': continue print(f"Processing: {folder.name}") # Generate new documentation php_content = self.generate_php_doc(folder.name, metadata) # Write the new index.php with open(index_file, 'w', encoding='utf-8') as f: f.write(php_content) # Update metadata category from 'todo' to 'game' metadata['category'] = 'game' with open(metadata_file, 'w', encoding='utf-8') as f: json.dump(metadata, f, indent=4, ensure_ascii=False) processed += 1 print(f" ✓ Generated documentation for {folder.name}") except Exception as e: error_msg = f"Error processing {folder.name}: {e}" print(f" ✗ {error_msg}") errors.append(error_msg) return processed, errors def main(): docs_dir = "/home/runner/work/GSP/GSP/modules/billing/docs" config_dir = "/home/runner/work/GSP/GSP/modules/config_games/server_configs" knowledgepack = "/home/runner/work/GSP/GSP/modules/billing/docs/gameserver_knowledgepack_v2.yaml" generator = GameDocGenerator(docs_dir, config_dir, knowledgepack) print("Loading data sources...") generator.load_knowledgepack() generator.load_xml_configs() print("\nProcessing TODO folders...") processed, errors = generator.process_todo_folders() print(f"\n{'='*60}") print(f"Documentation generation complete!") print(f" Total processed: {processed}") print(f" Errors: {len(errors)}") if errors: print("\nErrors encountered:") for error in errors[:10]: # Show first 10 errors print(f" - {error}") return 0 if not errors else 1 if __name__ == "__main__": sys.exit(main())