Last active
April 27, 2019 22:55
-
-
Save nosoop/688303af4ddb7d193eaf644c6b6bb8f3 to your computer and use it in GitHub Desktop.
ctrl+c, ctrl+v srcds/tf2 but smol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
''' | |
gameinfo cloner for TF2 | |
takes an existing TF2 dedicated server installation and an empty directory and links / copies / | |
modifies files in the latter to create a runnable server | |
''' | |
import os | |
import pathlib | |
import platform | |
import re | |
import sys | |
import shutil | |
ENGINE_PATH = pathlib.Path('..', 'core') | |
GAME_PATH = ENGINE_PATH / 'tf' | |
DEST_ENGINE_PATH = pathlib.Path('.') | |
DEST_GAME_PATH = DEST_ENGINE_PATH / 'tf' | |
DEST_GAME_PATH.mkdir(exist_ok = True) | |
# support absolute paths on linux, windows must use relative paths | |
# might want to use relative for both, but linux generally avoids spaces in file paths anyways | |
if platform.system() == 'Linux': | |
ENGINE_PATH = ENGINE_PATH.resolve() | |
GAME_PATH = GAME_PATH.resolve() | |
DEST_ENGINE_PATH = DEST_ENGINE_PATH.resolve() | |
DEST_GAME_PATH = DEST_GAME_PATH.resolve() | |
# process gameinfo.txt file, rewriting relative paths to point to our existing files | |
with (GAME_PATH / 'gameinfo.txt').open('rt') as input, (DEST_GAME_PATH / 'gameinfo.txt').open('wt') as output: | |
for line in filter(lambda s: not (s.strip().startswith('//') or len(s.strip()) == 0), input): | |
line = re.sub('tf/(.*\.vpk|bin)', r'{gamedir}/\1'.format(gamedir = GAME_PATH.as_posix()), line) | |
line = re.sub('game\+game_write.*$', r'game\t{gamedir}\n\t\t\tgame_write\t\ttf'.format(gamedir = GAME_PATH.as_posix()), line) | |
line = re.sub('\|all_source_engine_paths\|', r'{sedir}/'.format(sedir = ENGINE_PATH.as_posix()), line) | |
output.write(line) | |
# list of required files / directories | |
ENGINE_LINKS = [ "bin" ] | |
GAME_LINKS = [ "steam.inf" ] | |
GAME_COPIES = [ "scripts" ] | |
if platform.system() == 'Linux': | |
shutil.copy2(ENGINE_PATH / 'srcds_run', 'srcds_run') | |
ENGINE_LINKS.append("srcds_linux") | |
elif platform.system() == 'Windows': | |
shutil.copy2(ENGINE_PATH / 'srcds.exe', 'srcds.exe') | |
for link in filter(lambda l: not (DEST_ENGINE_PATH / l).exists(), ENGINE_LINKS): | |
os.symlink(ENGINE_PATH / link, DEST_ENGINE_PATH / link) | |
for link in filter(lambda l: not (DEST_GAME_PATH / l).exists(), GAME_LINKS): | |
# get a proper relative path on windows (os.symlink src is relative to target) | |
link_rel = pathlib.Path(os.path.relpath((GAME_PATH / link).resolve(), DEST_GAME_PATH)) | |
os.symlink(link_rel, DEST_GAME_PATH / link) | |
for file in filter(lambda f: not (DEST_GAME_PATH / f).exists(), GAME_COPIES): | |
shutil.copytree(GAME_PATH / file, DEST_GAME_PATH / file) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# cd into destination directory before running | |
# /path/to/clone_gameinfo.sh "/path/to/installed/tf" | |
TF_PATH=`realpath $1` | |
SOURCE_ENGINE_PATH=`realpath $TF_PATH/..` | |
process_gameinfo() { | |
# rewrite gameinfo, replace relative bin and .vpk paths | |
# also strips comments | |
sed -E "s:tf/(.*\.vpk|bin):${TF_PATH}/\1:" \ | |
| sed -E "s:game\+game_write.*$:game\t${TF_PATH}\n\t\t\tgame_write\t\ttf:" \ | |
| sed "s:|all_source_engine_paths|:${SOURCE_ENGINE_PATH}/:" \ | |
| grep -v '\t*//' | |
} | |
# cat "$1/gameinfo.txt" | process_gameinfo "$1" | |
# exit | |
# list of required directories | |
GAME_LINKS=("scripts") | |
ENGINE_LINKS=("bin" "srcds_linux") | |
if [ ! -d "tf" ]; then | |
mkdir tf | |
fi | |
cp "${SOURCE_ENGINE_PATH}/srcds_run" . | |
for link in "${ENGINE_LINKS[@]}"; do | |
ln -nsf "${SOURCE_ENGINE_PATH}/$link" "$link" | |
done | |
for link in "${GAME_LINKS[@]}"; do | |
# copy instead of symlink, server may update the file themselves | |
cp -r "${TF_PATH}/$link" "tf" | |
done | |
cat "${TF_PATH}/gameinfo.txt" | process_gameinfo > tf/gameinfo.txt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# script to set up a gameinfo-cloning TF2 server | |
# cd into your base directory | |
mkdir -p core/steam | |
pushd core | |
# install steam and install game above | |
wget -qO- "https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz" | tar xzf - -C steam | |
steam/steamcmd.sh +login anonymous +force_install_dir ../ +app_update 232250 +quit | |
popd |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
import os, vdf, subprocess, sys, signal | |
# insert default command line args here, or pass the args to the script | |
base_opts = [ ] | |
GAME_DIR = 'tf' | |
if __name__ == '__main__': | |
src_dir = os.path.dirname(os.path.realpath(__file__)) | |
os.chdir(src_dir) | |
plugins = [] | |
# add plugins from vdf files | |
for f in filter(lambda f: f.path.endswith('.vdf'), os.scandir(os.path.join(GAME_DIR, 'addons'))): | |
with open(f.path) as vdf_file: | |
data = vdf.load(vdf_file) | |
plugin_file = data.get('Plugin', {}).get('file', None) | |
if plugin_file: | |
plugins.append(plugin_file) | |
cmd = [ './srcds_run' ] | |
cmd.extend(base_opts) | |
cmd.extend(sys.argv[1:]) | |
for plugin in plugins: | |
print('Loading detected server plugin', plugin) | |
cmd.extend(['+plugin_load', os.path.join(src_dir, GAME_DIR, plugin)]) | |
# prevent sigint from ruining our day | |
s = signal.signal(signal.SIGINT, signal.SIG_IGN) | |
subprocess.call(cmd) | |
signal.signal(signal.SIGINT, s) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# Wrapper script to load addons. | |
cd "$(dirname "$0")" || return | |
if [ -f "$PWD/tf/addons/metamod.vdf" ]; then | |
echo "MetaMod:Source detected, loading plugin." | |
# TODO you'd want to read the actual locations from the VDF entries | |
LOAD_MMS="+plugin_load $(realpath .)/tf/addons/metamod/bin/server" | |
fi | |
./srcds_run "$@" "${LOAD_MMS}" |
Added a Python version of the wrapper script, which is able to detect plugins that should be automatically loaded in.
Requires vdf
.
Installation instructions
cd
yourself into an empty directory where all the files will go (e.g.,/home/me/tf-servers
)- Run
install-tf-multi.sh
, will install TF2 game files and SteamCMD intocore
andcore/steam
mkdir
andcd
into a new "server instance" directory, runclone_gameinfo.sh ../core/tf
in the new directory to generate the rewritten gameinfo and symlink the necessary files- (Optional) Copy
srcds_wrapper.py
orsrcds_wrapper.sh
into the directory; intended as asrcds_run
wrapper that automatically handles loading Valve server plugins (e.g., MetaMod:Source) - (Optional) Install MM:S, SM, etc., they should work as expected. Source.Python needs the server bin symlinked, so do that if you're installing it as well.
- Run
srcds_run
(orsrcds_wrapper
) as you normally would
For new server instances cd
into the directory created in step 1 then start from step 3
Ported the clone_gameinfo
shell script to Python with support for Windows systems (run as Administrator to get the symlinks working).
Requires Python 3.6+, as we use path-like objects in file operations.
Same installation method as before, though at the moment the Python script takes no arguments and assumes the parent SRCDS installation is ../core
.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Added a wrapper script; copy that to your cloned server's "root" directory and use that in place of
srcds_run
.A more robust solution would extract the paths from
tf/addons/*.vdf
and adding those, but that's left as an exercise for those that care.