From 3e8932a4f2e9a243b45223581a3546625a27dd6d Mon Sep 17 00:00:00 2001 From: Von Random Date: Sun, 7 Feb 2021 18:37:53 +0300 Subject: vq3srv: remade to support a config; other: initial commt, some housekeeping --- .gitignore | 3 ++ bootstrap.example.yml | 14 ++++++++ config.example.yml | 31 +++++++++++++++++ vq3srv | 96 +++++++++++++++++++-------------------------------- 4 files changed, 83 insertions(+), 61 deletions(-) create mode 100644 .gitignore create mode 100644 bootstrap.example.yml create mode 100644 config.example.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1efc1fe --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.vscode +config.yml +bootstrap.yml \ No newline at end of file diff --git a/bootstrap.example.yml b/bootstrap.example.yml new file mode 100644 index 0000000..5a87522 --- /dev/null +++ b/bootstrap.example.yml @@ -0,0 +1,14 @@ +# these are saved to the q3config_server.cfg, so -B should only be used once really +# add any config variable with value here as needed, +# defaults are mostly sensible, so here is a rather small list +sv_pure: '0' +sv_maxclients: '8' +sv_hostname: 'myhost.tld' + +# this will let your server send maps to clients +# the downloads are attempted from http://%sv_dlURL%/baseq3/mapname.pk3 +# note the protocol - no support for https, +# as well as the need to have baseq3 as a part of the path +# note that clients have to seta cl_allowDownload 1 for that to work +sv_dlURL: 'anyhost.tld/q3' +sv_allowDownloads: '1' \ No newline at end of file diff --git a/config.example.yml b/config.example.yml new file mode 100644 index 0000000..0b82330 --- /dev/null +++ b/config.example.yml @@ -0,0 +1,31 @@ +user: quake3 +cmd: /opt/ioquake3/ioq3ded.x86_64 +exec autoexec.cfg +autoexec: /home/quake3/.q3a/baseq3/autoexec.cfg +gamemodes: + any: + vars: + fraglimit: 100 + timelimit: 10 + ffa: + maps: [ + q3dm2, q3dm3, q3dm4, q3dm5, q3dm6, + q3dm7, q3dm8, q3dm9, q3dm10, q3dm11 + ] + vars: + fraglimit: 30 + timelimit: 15 + duel: + maps: [ + q3dm1, q3dm2, pro-q3dm6, pro-q3dm13, + q3tourney1, q3tourney3, q3tourney5, q3tourney6, + pro-q3tourney2, pro-q3tourney4 + ] + vars: + fraglimit: 15 + timelimit: 5 +bots: + level: '3' + names: [ + anarki, angel, crash, doom, hunter, + klesk, major, mynx, orbb, slash, xaero + ] \ No newline at end of file diff --git a/vq3srv b/vq3srv index 0b4f149..aea9a25 100755 --- a/vq3srv +++ b/vq3srv @@ -3,64 +3,24 @@ from argparse import ArgumentParser from os import system from random import shuffle from sys import exit - -# TODO: move this shit to a yaml config somewhere in /etc -USER = 'quake3' # linux user, for sudo -u -BIN = '/usr/bin/q3ded' -CONF = '/srv/q3/.q3a/baseq3/autoexec.cfg' -PARAM = '+exec autoexec.cfg' - -MAPLISTS = { - 'ffa': [ - 'q3dm2', 'q3dm3', 'q3dm4', 'q3dm5', 'q3dm6', - 'q3dm7', 'q3dm8', 'q3dm9', 'q3dm10', 'q3dm11' - ], - 'duel': [ - 'q3dm1', 'q3dm2', 'pro-q3dm6', 'pro-q3dm13', - 'q3tourney1', 'q3tourney3', 'q3tourney5', 'q3tourney6', - 'pro-q3tourney2', 'pro-q3tourney4' - ], - 'ctf': list() -} -BOTS = { - 'level': '3', - 'names': [ - 'Anarki', 'Angel', 'Crash', 'Doom', 'Hunter', - 'Klesk', 'Major', 'Mynx', 'Orbb', 'Slash', 'Xaero' - ] -} - - -# these are saved to the q3config_server.cfg on the first run -# no point in keeping them here afterwards -BOOTSTRAP_OPTS = dict() -# BOOTSTRAP_OPTS = { -# 'sv_pure': '0', # enable client side mods, like better fonts or graphics -# 'sv_maxclients': '8', -# 'sv_hostname': 'myhost.tld' -# -# # this will let your server send maps to clients -# # the downloads are attempted from http://%sv_dlURL%/baseq3/mapname.pk3 -# # note the protocol - no support for https, -# # as well as the need to have baseq3 as a part of the path -# # note that clients have to seta cl_allowDownload 1 for that to work -# 'sv_dlURL': 'anyhost.tld/q3', -# 'sv_allowDownloads': '1' -# } +from yaml import safe_load def parse_arguments(): desc = 'host a q3 server' parser = ArgumentParser(description=desc) parser.add_argument('-m', '--gamemode', default='ffa') - parser.add_argument('-f', '--fraglimit', type=int, default=15) - parser.add_argument('-t', '--timelimit', type=int, default=10) + parser.add_argument('-f', '--fraglimit', type=int) + parser.add_argument('-t', '--timelimit', type=int) parser.add_argument('-b', '--bots', type=int, default=0) + parser.add_argument('-c', '--config', default='config.yml') + parser.add_argument('-B', '--bootstrap') return parser.parse_args() -def gen_confline(param, value): - return 'seta {} "{}"\n'.format(param, value) +def gen_confline(param, value, archive=False): + set_cmd = 'seta' if archive else 'set' + return '{} {} "{}"\n'.format(set_cmd, param, value) def gen_maplist(maplist): @@ -87,24 +47,38 @@ def gen_addbots(count, level='3', names=list()): def main(): args = parse_arguments() - cfg_data = str() + cfg_data, bvars, svars = str(), dict(), dict() try: - assert args.gamemode in MAPLISTS + with open(args.config, 'r') as config_file: + cfg = safe_load(config_file) + if args.bootstrap: + with open(args.bootstrap, 'r') as bootstrap_file: + bvars.update(safe_load(bootstrap_file)) + assert args.gamemode != 'any' and args.gamemode in cfg['gamemodes'] + except FileNotFoundError as error: + exit('Config `{}` not found!'.format(error.filename)) except AssertionError: - exit('Wrong game mode specified!') - - for param in BOOTSTRAP_OPTS: - cfg_data += gen_confline(param, BOOTSTRAP_OPTS[param]) - cfg_data += gen_confline('fraglimit', args.fraglimit) - cfg_data += gen_confline('timelimit', args.timelimit) - # this should be last since it launches the actual maplist - cfg_data += gen_maplist(MAPLISTS[args.gamemode]) + exit('Wrong game mode `{}` specified!'.format(args.gamemode)) + + smaps = cfg['gamemodes'][args.gamemode]['maps'] + svars.update(cfg['gamemodes']['any']['vars']) + svars.update(cfg['gamemodes'][args.gamemode]['vars']) + if args.fraglimit: + svars.update({'fraglimit': args.fraglimit}) + if args.timelimit: + svars.update({'timelimit': args.timelimit}) + + for param in bvars: + cfg_data += gen_confline(param, bvars[param], archive=True) + for param in svars: + cfg_data += gen_confline(param, svars[param]) + cfg_data += gen_maplist(smaps) if args.bots: - cfg_data += gen_addbots(args.bots, **BOTS) + cfg_data += gen_addbots(args.bots, **cfg['bots']) - with open(CONF, 'w+') as config: + with open(cfg['autoexec'], 'w+') as config: config.write(cfg_data) - system('sudo -u {} {} {}'.format(USER, BIN, PARAM)) + system('sudo -u {} {}'.format(cfg['user'], cfg['cmd'])) if __name__ == '__main__': -- cgit v1.2.3