Implement "minimum version" checks into server and clients
This commit is contained in:
parent
6c8d30bbe0
commit
e25a03173b
4
Main.py
4
Main.py
|
@ -363,6 +363,7 @@ def main(args, seed=None):
|
||||||
multidatatags.append("Spoiler")
|
multidatatags.append("Spoiler")
|
||||||
if not args.skip_playthrough:
|
if not args.skip_playthrough:
|
||||||
multidatatags.append("Play through")
|
multidatatags.append("Play through")
|
||||||
|
minimum_versions = {"server": (1,0,0)}
|
||||||
multidata = zlib.compress(json.dumps({"names": parsed_names,
|
multidata = zlib.compress(json.dumps({"names": parsed_names,
|
||||||
# backwards compat for < 2.4.1
|
# backwards compat for < 2.4.1
|
||||||
"roms": [(slot, team, list(name.encode()))
|
"roms": [(slot, team, list(name.encode()))
|
||||||
|
@ -379,7 +380,8 @@ def main(args, seed=None):
|
||||||
"er_hint_data": er_hint_data,
|
"er_hint_data": er_hint_data,
|
||||||
"precollected_items": precollected_items,
|
"precollected_items": precollected_items,
|
||||||
"version": _version_tuple,
|
"version": _version_tuple,
|
||||||
"tags": multidatatags
|
"tags": multidatatags,
|
||||||
|
"minimum_versions" : minimum_versions
|
||||||
}).encode("utf-8"), 9)
|
}).encode("utf-8"), 9)
|
||||||
|
|
||||||
with open(output_path('%s.multidata' % outfilebase), 'wb') as f:
|
with open(output_path('%s.multidata' % outfilebase), 'wb') as f:
|
||||||
|
|
|
@ -112,6 +112,7 @@ class Context(Node):
|
||||||
self.auto_saver_thread = None
|
self.auto_saver_thread = None
|
||||||
self.save_dirty = False
|
self.save_dirty = False
|
||||||
self.tags = ['Berserker']
|
self.tags = ['Berserker']
|
||||||
|
self.minimum_client_versions: typing.Dict[typing.Tuple[int, int], Utils.Version] = {}
|
||||||
|
|
||||||
def load(self, multidatapath: str, use_embedded_server_options: bool = False):
|
def load(self, multidatapath: str, use_embedded_server_options: bool = False):
|
||||||
with open(multidatapath, 'rb') as f:
|
with open(multidatapath, 'rb') as f:
|
||||||
|
@ -121,6 +122,16 @@ class Context(Node):
|
||||||
self.data_filename = multidatapath
|
self.data_filename = multidatapath
|
||||||
|
|
||||||
def _load(self, jsonobj: dict, use_embedded_server_options: bool):
|
def _load(self, jsonobj: dict, use_embedded_server_options: bool):
|
||||||
|
if "minimum_versions" in jsonobj:
|
||||||
|
mdata_ver = tuple(jsonobj["minimum_versions"]["server"])
|
||||||
|
if mdata_ver > Utils._version_tuple:
|
||||||
|
raise RuntimeError(f"Supplied Multidata requires a server of at least version {mdata_ver},"
|
||||||
|
f"however this server is of version {Utils._version_tuple}")
|
||||||
|
clients_ver = jsonobj["minimum_versions"].get("clients", [])
|
||||||
|
self.minimum_client_versions = {}
|
||||||
|
for team, player, version in clients_ver:
|
||||||
|
self.minimum_client_versions[team, player] = Utils.Version(*version)
|
||||||
|
|
||||||
for team, names in enumerate(jsonobj['names']):
|
for team, names in enumerate(jsonobj['names']):
|
||||||
for player, name in enumerate(names, 1):
|
for player, name in enumerate(names, 1):
|
||||||
self.player_names[(team, player)] = name
|
self.player_names[(team, player)] = name
|
||||||
|
@ -996,9 +1007,14 @@ async def process_client_cmd(ctx: Context, client: Client, cmd, args):
|
||||||
client.name = ctx.player_names[(team, slot)]
|
client.name = ctx.player_names[(team, slot)]
|
||||||
client.team = team
|
client.team = team
|
||||||
client.slot = slot
|
client.slot = slot
|
||||||
|
minver = Utils.Version(*(ctx.minimum_client_versions.get((team, slot), (0,0,0))))
|
||||||
|
if minver > tuple(args.get('version', Client.version)):
|
||||||
|
errors.add('IncompatibleVersion')
|
||||||
|
|
||||||
if ctx.compatibility == 1 and "Berserker" not in args.get('tags', Client.tags):
|
if ctx.compatibility == 1 and "Berserker" not in args.get('tags', Client.tags):
|
||||||
errors.add('IncompatibleVersion')
|
errors.add('IncompatibleVersion')
|
||||||
elif ctx.compatibility == 0 and args.get('version', Client.version) != list(_version_tuple):
|
#only exact version match allowed
|
||||||
|
elif ctx.compatibility == 0 and tuple(args.get('version', Client.version)) != _version_tuple:
|
||||||
errors.add('IncompatibleVersion')
|
errors.add('IncompatibleVersion')
|
||||||
if errors:
|
if errors:
|
||||||
logging.info(f"A client connection was refused due to: {errors}")
|
logging.info(f"A client connection was refused due to: {errors}")
|
||||||
|
|
7
Utils.py
7
Utils.py
|
@ -3,7 +3,12 @@ import typing
|
||||||
|
|
||||||
|
|
||||||
def tuplize_version(version: str) -> typing.Tuple[int, ...]:
|
def tuplize_version(version: str) -> typing.Tuple[int, ...]:
|
||||||
return tuple(int(piece, 10) for piece in version.split("."))
|
return Version(*(int(piece, 10) for piece in version.split(".")))
|
||||||
|
|
||||||
|
class Version(typing.NamedTuple):
|
||||||
|
major: int
|
||||||
|
minor: int
|
||||||
|
micro: int
|
||||||
|
|
||||||
|
|
||||||
__version__ = "3.4.2"
|
__version__ = "3.4.2"
|
||||||
|
|
Loading…
Reference in New Issue