summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.example.yml28
-rwxr-xr-xvq3srv99
2 files changed, 84 insertions, 43 deletions
diff --git a/config.example.yml b/config.example.yml
index 4d8e2b1..e3e79b0 100644
--- a/config.example.yml
+++ b/config.example.yml
@@ -2,14 +2,20 @@ user: quake3
cmd: /opt/ioquake3/ioq3ded.x86_64
exec: /home/quake3/.q3a/baseq3/autoexec.cfg
gamemodes:
- ffa:
+ # names just identifiers, feel free to mix
+ # map types as you see fit
+ default:
+ # the only required option here is maps,
+ # everything else is optional
maps: [
q3dm2, q3dm3, q3dm4, q3dm5, q3dm6,
q3dm7, q3dm8, q3dm9, q3dm10, q3dm11
]
+ # any supported var can be set from here
+ # vars is optional, defaults to these:
vars:
- fraglimit: 30
- timelimit: 15
+ fraglimit: 15
+ timelimit: 5
duel:
maps: [
q3dm1, q3dm2, pro-q3dm6, pro-q3dm13,
@@ -22,12 +28,14 @@ gamemodes:
cpma_duel:
maps: [ q3dm6 ]
vars:
- sv_game: cpma
+ # mods can be used as well
+ fs_game: cpma
fraglimit: 15
timelimit: 15
-bots:
- level: '3'
- names: [
- anarki, angel, crash, doom, hunter,
- klesk, major, mynx, orbb, slash, xaero
- ]
+# defining bots here is optional, defaults
+# are already defined in the script
+bot_level: 3
+bot_names: [
+ anarki, angel, crash, doom, hunter,
+ klesk, major, mynx, orbb, slash, xaero
+]
diff --git a/vq3srv b/vq3srv
index d095f2d..a2cb338 100755
--- a/vq3srv
+++ b/vq3srv
@@ -7,15 +7,30 @@ from sys import exit
from yaml import safe_load
+GDEFAULTS = {
+ 'bots': {
+ 'level': 3,
+ 'names': ['anarki', 'angel', 'crash', 'doom', 'hunter',
+ 'klesk', 'major', 'mynx', 'orbb', 'slash', 'xaero']
+ }
+}
+MDEFAULTS = {
+ 'randomize': True,
+ 'vars': {
+ 'fraglimit': 30,
+ 'timelimit': 15
+ }
+}
+
+
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)
- parser.add_argument('-t', '--timelimit', type=int)
+ parser.add_argument('-m', '--gamemode', default='default')
parser.add_argument('-b', '--bots', type=int, default=0)
parser.add_argument('-c', '--config', default='config.yml')
parser.add_argument('-B', '--bootstrap')
+ parser.add_argument('-d', '--debug', action="store_true")
return parser.parse_args()
@@ -24,11 +39,12 @@ def gen_confline(param, value, archive=False):
return '{} {} "{}"\n'.format(set_cmd, param, value)
-def gen_maplist(maplist):
- shuffle(maplist)
+def gen_maplist(maplist, randomize=True):
num = 1
stmpl = 'set d{} "map {} ; set nextmap vstr d{}"\n'
script = str()
+ if randomize:
+ shuffle(maplist)
while maplist:
nextnum = 1 if len(maplist) == 1 else num + 1
script += stmpl.format(num, maplist.pop(), nextnum)
@@ -37,50 +53,67 @@ def gen_maplist(maplist):
return script
-def gen_addbots(count, level='3', names=list()):
- shuffle(names)
+def gen_addbots(count, level, names):
btmpl = 'addbot {} {}\n'
script = str()
+ shuffle(names)
for bot in names[:count]:
script += btmpl.format(bot, level)
return script
+def gen_exec(gcfg, mcfg, bvars=dict(), bot_count=0, debug=False):
+ cfg_data = str()
+ for param in bvars:
+ cfg_data += gen_confline(param, bvars[param], archive=True)
+ cfg_data += gen_maplist(mcfg['maps'],
+ mcfg.get('randomize', MDEFAULTS['randomize']))
+ if bot_count:
+ bot_level = gcfg.\
+ get('bots', GDEFAULTS['bots']).\
+ get('level', GDEFAULTS['bots']['level'])
+ bot_names = gcfg.\
+ get('bots', GDEFAULTS['bots']).\
+ get('names', GDEFAULTS['bots']['names'])
+ cfg_data += gen_addbots(bot_count, bot_level, bot_names)
+ if debug:
+ print('Debug {} contents:\n{}'.format(gcfg['exec'], cfg_data))
+ return
+ try:
+ with open(gcfg['exec'], 'w+') as config:
+ config.write(cfg_data)
+ except FileNotFoundError as error:
+ exit('Config `{}` not found!'.format(error.filename))
+
+
def main():
args = parse_arguments()
- cfg_data, cmd_vars, bvars, svars = str(), list(), dict(), dict()
+ cfg_data, cmd_list, bvars = str(), list(), dict()
try:
with open(args.config, 'r') as config_file:
- cfg = safe_load(config_file)
+ gcfg = safe_load(config_file)
+ assert {'user', 'exec', 'cmd'} <= gcfg.keys()
+ mcfg = gcfg['gamemodes'][args.gamemode]
+ assert 'maps' in mcfg
if args.bootstrap:
with open(args.bootstrap, 'r') as bootstrap_file:
- bvars.update(safe_load(bootstrap_file))
- assert args.gamemode in cfg['gamemodes']
- exec_filename = basename(cfg['exec'])
+ bvars = safe_load(bootstrap_file)
except FileNotFoundError as error:
exit('Config `{}` not found!'.format(error.filename))
- except AssertionError:
- exit('Wrong game mode `{}` specified!'.format(args.gamemode))
-
- smaps = cfg['gamemodes'][args.gamemode]['maps']
- 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)
+ except (AssertionError, KeyError):
+ exit('Missing required settings in {}!'.format(args.config))
+
+ svars = mcfg.get('vars', MDEFAULTS['vars'])
+ exec_filename = basename(gcfg['exec'])
+
for param in svars:
- cmd_vars.append('+set {} {}'.format(param, svars[param]))
- cmd_vars.append('+exec {}'.format(exec_filename))
- cmd_opts = ' '.join(cmd_vars)
- cfg_data += gen_maplist(smaps)
- if args.bots:
- cfg_data += gen_addbots(args.bots, **cfg['bots'])
-
- with open(cfg['exec'], 'w+') as config:
- config.write(cfg_data)
- system('sudo -u {} {} {}'.format(cfg['user'], cfg['cmd'], cmd_opts))
+ cmd_list.append('+set {} {}'.format(param, svars[param]))
+ cmd_list.append('+exec {}'.format(exec_filename))
+ cmd_opts = ' '.join(cmd_list)
+
+ action = print if args.debug else system
+ gen_exec(gcfg, mcfg, bvars, args.bots, args.debug)
+ action('sudo -u {} {} {}'.format(gcfg['user'], gcfg['cmd'], cmd_opts))
if __name__ == '__main__':