# megastructure.surf A Docker-based Counter-Strike: Source surf server with Shavit BHopTimer and community physics fix plugins. ## Overview This repository contains a complete CSS surf server setup using Docker containers. The setup includes: - **CSS Dedicated Server (CSSDS)** - Running on 64-bit binaries for improved performance - **Shavit BHopTimer** - Actively maintained timer system (v4.0.1) with MySQL support - **MariaDB** - Database backend for timer records and player data - **MetaMod:Source** - Plugin loader framework - **SourceMod** - Server administration and plugin platform - **Community Physics Plugins** - Essential surf/bhop fixes and enhancements ## Architecture ### Docker Services #### `cssds` (CSS Dedicated Server) - Based on Debian Bookworm - Runs SteamCMD to download/update CSS DS and TF2 DS (for 64-bit binaries) - Installs MetaMod:Source and SourceMod - Installs surf-specific plugins and timer system - Uses 64-bit server binaries for better performance - Port: 27015 (configurable via `SRCDS_PORT`) #### `mariadb` (Database) - MariaDB 10.11 for timer data persistence - Stores player records, map times, rankings - Port: 3306 (internal) - Data persisted in `./sql:/var/lib/mysql` ### Key Files ``` . ├── docker-compose.yaml # Service orchestration ├── etc/ │ ├── cssds.dockerfile # CSS DS container definition │ ├── mariadb.dockerfile # MariaDB container definition │ ├── run.sh # Main setup and launch script │ ├── update_cssds.txt # SteamCMD script for CSS DS │ ├── update_tf2ds.txt # SteamCMD script for TF2 DS (64-bit libs) │ └── cfg/ │ └── server.cfg # Server configuration └── sql/ # MariaDB data directory (volume mount) ``` ## Installed Plugins ### Timer System **Shavit BHopTimer v4.0.1** ([GitHub](https://github.com/shavitush/bhoptimer)) - Actively maintained (last update: February 2026) - Full surf/bhop timer with MySQL backend - Replays, rankings, zone system, statistics - Better SQL schema design than archived alternatives - Config location: `addons/sourcemod/configs/shavit/` - **Configured to use JSON zones** from [surf-zones](https://github.com/wrldspawn/surf-zones) repository - Zones loaded from `https://wrldspawn.github.io/surf-zones/z/{map}.json` - Includes stripper configurations and mapfixes - Matches KSF (Kreedz Surf Federation) server behavior - Use `!setmaxvel` in-game to configure max velocity per map ### Physics Fix Plugins **MomSurfFix v1.1.5** ([GitHub](https://github.com/GAMMACASE/MomSurfFix)) - Fixes Source engine surf physics to match Momentum Mod behavior - Essential for proper surf mechanics **PushFix Definitive Edition v1.0.0** ([GitHub](https://github.com/GAMMACASE/PushFixDE)) - Fixes player collision and push mechanics - Prevents physics exploits **EventQueue Fix v1.3.2** ([GitHub](https://github.com/hermansimensen/eventqueue-fix)) - Fixes map entity timing issues - Ensures triggers and outputs work correctly **RNGFix v1.1.3** ([GitHub](https://github.com/jason-e/rngfix)) - Fixes Source engine RNG determinism issues - Ensures consistent physics behavior ### Base Plugins SourceMod includes built-in plugins for server administration: - Admin Menu, Basic Commands, Player Commands - Rock The Vote, Map Nominations, MapChooser - Reserved Slots, Basic Bans - And more (see `etc/run.sh` comments for full list) ## Setup & Usage ### Prerequisites - Docker - Docker Compose - ~10GB disk space for server files ### Environment Variables Configure in `docker-compose.yaml`: ```yaml METAMOD_VERSION: "1.11" # MetaMod:Source version SOURCEMOD_VERSION: "1.11" # SourceMod version SRCDS_PORT: 27015 # Server port SRCDS_MAXPLAYERS: 32 # Max player slots SRCDS_STARTMAP: "surf_ski_2" # Starting map ``` ### Building & Running ```bash # Build the containers docker-compose build # Start the services docker-compose up -d # View logs docker-compose logs -f cssds # Stop the services docker-compose down ``` ### First-Time Database Configuration After the first build, configure Shavit to use MariaDB: 1. Edit `addons/sourcemod/configs/databases.cfg`: ``` "Databases" { "shavit" { "driver" "mysql" "host" "mariadb" "database" "shavit" "user" "root" "pass" "your_password" } } ``` 2. Shavit will automatically create tables on first connection ### JSON Zones Configuration The server is **automatically configured** to use JSON zones instead of SQL-based zones. This provides several advantages: **Automatic Setup:** - Zones are loaded from the community-maintained [surf-zones](https://github.com/wrldspawn/surf-zones) repository - Includes 400+ maps with pre-configured zones, stripper configs, and mapfixes - No manual zone creation needed for supported maps - Automatically downloads: `https://wrldspawn.github.io/surf-zones/z/{map}.json` **Configuration Files Created:** - `cfg/sourcemod/plugin.shavit-zones.cfg` - Disables SQL zones (`shavit_zones_usesql "0"`) - `cfg/sourcemod/plugin.shavit-zones-json.cfg` - Sets JSON URL - `addons/stripper/` - Map entity fixes and modifications - `addons/sourcemod/configs/shavit-mapfixes.cfg` - Map-specific settings - `addons/sourcemod/configs/shavit-styles.cfg` - KSF-style configurations **Benefits:** - ✅ No manual zone editing required for popular maps - ✅ Community-maintained and regularly updated - ✅ Includes map fixes for common issues - ✅ Matches KSF server behavior and standards - ✅ Faster deployment (no SQL import needed) **Important Note:** The `sv_maxvelocity` settings in mapfixes won't auto-apply. After loading a map, use the in-game command: ``` !setmaxvel ``` For most surf maps, use `!setmaxvel 3500`. Some maps may require different values (check surf-zones repo for specific maps). ### Server Configuration Edit `etc/cfg/server.cfg` for server settings: - Hostname, rcon password - Game settings (gravity, air accelerate, etc.) - SourceMod configurations ## Development Notes ### Plugin Installation Pattern All plugins follow an idempotent installation pattern in `etc/run.sh`: ```bash if [ ! -f "$CSTRIKE/addons/sourcemod/plugins/plugin.smx" ]; then wget "https://github.com/author/repo/releases/download/version/plugin.zip" unzip "plugin.zip" rm "plugin.zip" echo "Installed Plugin vX.Y.Z" fi ``` This allows safe re-runs without reinstalling existing plugins. ### Version Strategy **Fixed versions are used** (not dynamic `latest` detection) for: - **Stability** - Known working versions prevent unexpected breaks - **Reproducibility** - Docker builds are deterministic - **No API dependencies** - Avoids GitHub API rate limits - **Easy rollback** - Can revert to specific versions if issues arise ### 64-bit Binary Support The server uses 64-bit binaries for improved performance: 1. TF2 DS is downloaded for its 64-bit libraries 2. `libsteam_api.so` and `srcds_linux64` are copied from TF2 to CSS 3. `_srv.so` binaries are symlinked to regular `.so` names 4. `steamclient.so` is located and symlinked to expected paths ### Run Script Flow The `etc/run.sh` script executes in this order: 1. **update_cssds()** - Download/update CSS DS via SteamCMD 2. **update_tf2ds()** - Download/update TF2 DS for 64-bit binaries 3. **copy_64bit()** - Copy 64-bit libraries from TF2 to CSS 4. **symlink_binaries()** - Create symlinks for server binaries 5. **steamclient_binary()** - Locate and symlink steamclient.so 6. **install_metamod()** - Install MetaMod:Source if missing 7. **install_sourcemod()** - Install SourceMod if missing 8. **install_surf()** - Install timer and physics plugins 9. **configure_shavit_zones()** - Download and configure JSON zones, stripper configs, and mapfixes 10. **cfg()** - Copy server configuration 11. **run_cssds()** - Launch the dedicated server ## Verification ### Check Installed Plugins ```bash docker exec -it surf_megastructure-cssds-1 \ ls -la /home/steam/cssds/cstrike/addons/sourcemod/plugins/*.smx ``` ### Check Shavit Configuration ```bash docker exec -it surf_megastructure-cssds-1 \ ls -la /home/steam/cssds/cstrike/addons/sourcemod/configs/shavit/ ``` ### Check JSON Zones Configuration ```bash # Check zone configuration files docker exec -it surf_megastructure-cssds-1 \ cat /home/steam/cssds/cstrike/cfg/sourcemod/plugin.shavit-zones.cfg # Check JSON URL configuration docker exec -it surf_megastructure-cssds-1 \ cat /home/steam/cssds/cstrike/cfg/sourcemod/plugin.shavit-zones-json.cfg # Check stripper configs installed docker exec -it surf_megastructure-cssds-1 \ ls -la /home/steam/cssds/cstrike/addons/stripper/ # Check mapfixes docker exec -it surf_megastructure-cssds-1 \ cat /home/steam/cssds/cstrike/addons/sourcemod/configs/shavit-mapfixes.cfg ``` ### In-Game Verification Connect to the server and run: ``` sm plugins list ``` You should see: - Shavit BHopTimer (multiple modules) - momsurffix2 - pushfix_de - eventqueuefix - rngfix - Standard SourceMod plugins ## Troubleshooting ### Plugins Not Loading 1. Check MetaMod is loaded: `meta list` 2. Check SourceMod is loaded: `sm version` 3. Check plugin errors: `sm plugins list` and look for "Failed" or "Error" 4. Check logs: `addons/sourcemod/logs/` ### Database Connection Issues 1. Verify MariaDB container is running: `docker ps` 2. Check database credentials in `databases.cfg` 3. Check Shavit logs: `addons/sourcemod/logs/shavit/` 4. Test connection: `sm_sql_query shavit "SELECT 1"` ### Zones Not Loading / Map Has No Zones **Symptoms:** Map loads but no start/end zones, timer doesn't work **Solutions:** 1. **Check if map is in surf-zones repository:** - Visit: https://github.com/wrldspawn/surf-zones/tree/main/z - Search for your map name (e.g., `surf_ski_2.json`) - Not all maps have pre-made zones 2. **Verify JSON zones are enabled:** ``` // In console sm_cvar shavit_zones_usesql // Should show: "shavit_zones_usesql" = "0" ``` 3. **Check zone loading errors:** - Check `addons/sourcemod/logs/shavit/` - Look for HTTP errors or JSON parsing failures 4. **Create zones manually (if map not in repo):** ``` // In-game !zones // Open zone editor !start // Create start zone !end // Create end zone ``` - Zones created in-game are saved to the database (not JSON) 5. **Network connectivity:** - Verify container can reach GitHub: `docker exec -it surf_megastructure-cssds-1 curl -I https://wrldspawn.github.io/` - Check firewall/proxy settings **Note:** If a map doesn't exist in the surf-zones repository, you'll need to create zones manually using the in-game zone editor (`!zones`). These will be saved to your MariaDB database. ### Server Won't Start 1. Check logs: `docker-compose logs cssds` 2. Verify port 27015 is available 3. Check disk space for server files 4. Verify SteamCMD downloaded files successfully ## Future Enhancements ### Potential Additions - **FastDL** - Fast map download server (HTTP/Web server for map downloads) - **SourceBans** - Web-based ban management system - **Map rotation** - Automated map cycling configuration - **GOTV** - Source TV for spectating/recording matches - **Workshop maps** - Steam Workshop integration for map downloads - **Backup system** - Automated database and config backups ### Maintenance - Update plugin versions periodically - Monitor Shavit GitHub for new releases - Check for MetaMod/SourceMod updates - Review server logs for errors or exploits ## Credits - **Shavit BHopTimer** - [shavitush](https://github.com/shavitush/bhoptimer) - **MomSurfFix** - [GAMMACASE](https://github.com/GAMMACASE/MomSurfFix) - **PushFix DE** - [GAMMACASE](https://github.com/GAMMACASE/PushFixDE) - **EventQueue Fix** - [hermansimensen](https://github.com/hermansimensen/eventqueue-fix) - **RNGFix** - [jason-e](https://github.com/jason-e/rngfix) - **MetaMod:Source** - [AlliedModders](https://www.metamodsource.net/) - **SourceMod** - [AlliedModders](https://www.sourcemod.net/) ## License This setup configuration is provided as-is. Individual components (Shavit, SourceMod, etc.) retain their original licenses.