From 28b5bebc406f6f79ea0ff99f83d18b6ce14db8f2 Mon Sep 17 00:00:00 2001 From: Von Random Date: Sun, 7 Feb 2021 05:40:59 +0300 Subject: [PATCH] vq3srv: initial commit --- LICENSE | 2 +- vq3srv | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 1 deletion(-) create mode 100755 vq3srv diff --git a/LICENSE b/LICENSE index 204b93d..57ce3a8 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -MIT License Copyright (c) +MIT License Copyright (c) 2021 Von Random Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vq3srv b/vq3srv new file mode 100755 index 0000000..0b4f149 --- /dev/null +++ b/vq3srv @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 +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' +# } + + +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('-b', '--bots', type=int, default=0) + return parser.parse_args() + + +def gen_confline(param, value): + return 'seta {} "{}"\n'.format(param, value) + + +def gen_maplist(maplist): + shuffle(maplist) + num = 1 + stmpl = 'set d{} "map {} ; set nextmap vstr d{}"\n' + script = str() + while maplist: + nextnum = 1 if len(maplist) == 1 else num + 1 + script += stmpl.format(num, maplist.pop(), nextnum) + num += 1 + script += 'vstr d1\n' + return script + + +def gen_addbots(count, level='3', names=list()): + shuffle(names) + btmpl = 'addbot {} {}\n' + script = str() + for bot in names[:count]: + script += btmpl.format(bot, level) + return script + + +def main(): + args = parse_arguments() + cfg_data = str() + try: + assert args.gamemode in MAPLISTS + 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]) + if args.bots: + cfg_data += gen_addbots(args.bots, **BOTS) + + with open(CONF, 'w+') as config: + config.write(cfg_data) + system('sudo -u {} {} {}'.format(USER, BIN, PARAM)) + + +if __name__ == '__main__': + main()