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