From 37ec4349aa89d51b1c7890a86c125835340b23e8 Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Sun, 14 May 2023 10:41:05 +0200 Subject: [PATCH] Make gen init header code shared --- scripts/generate_messages.py | 254 ++++++++++++++++++----------------- 1 file changed, 132 insertions(+), 122 deletions(-) diff --git a/scripts/generate_messages.py b/scripts/generate_messages.py index 8590799..59c22bc 100755 --- a/scripts/generate_messages.py +++ b/scripts/generate_messages.py @@ -79,14 +79,10 @@ class NetMessageJson(TypedDict): members: list[NetMessageMemberJson] attributes: list[Literal['msg_encoding']] -class NetConnlessMemberJson(TypedDict): - name: list[str] - type: NetConnlessMemberTypeJson - class NetConnlessJson(TypedDict): id: Annotated[list[int], 8] name: list[str] - members: list[NetConnlessMemberJson] + members: list[NetMessageMemberJson] class SpecJson(TypedDict): constants: list[ConstantJson] @@ -489,7 +485,7 @@ def gen_pack_return(msg: NetMessageJson) -> str: return f" return {pack_field(members[0])} + \\\n" + \ ' + \\\n'.join(mem_strs) -def pack_field_connless7(member: NetConnlessMemberJson) -> str: +def pack_field_connless7(member: NetMessageMemberJson) -> str: name: str = name_to_snake(member["name"]) field: str = f'self.{name}' packer = 'int' @@ -510,7 +506,7 @@ def pack_field_connless7(member: NetConnlessMemberJson) -> str: return f'pack_{packer}({field})' def gen_pack_return_connless7(msg: NetConnlessJson) -> str: - members: list[NetConnlessMemberJson] = msg['members'] + members: list[NetMessageMemberJson] = msg['members'] if len(members) == 0: return " return b''" if len(members) == 1: @@ -559,6 +555,129 @@ class CodeGenerator(): def __init__(self) -> None: self.game_enums: list[GameEnumJson] = [] + def gen_init_member_header_def( + self, + member: NetMessageMemberJson, + name_snake: str, + message_type: Literal['game', 'system', 'connless'] + ) -> list[str]: + """ + get_init_member_header_def + + given a member field it returns an array of strings + that represent the python code for the content in the + init method parameter list + + def __init__(self, [THIS IS GENERATED]) -> None: + + it might return two fields for members like data + that also introduce a size field + + the returned assignements do not include indentation + """ + args: list[str] = [] + # { + # 'name': ['message'], + # 'type': { + # 'kind': 'string', + # 'disallow_cc': False + # } + # } + ftype = 'int' + default = '-1' + if member['type']['kind'] == 'string': + ftype = 'str' + default = "'default'" + elif member['type']['kind'] == 'packed_addresses': # TODO: packed_addreses default value + ftype = 'list[MastersrvAddr]' + default = '[]' + elif member['type']['kind'] == 'serverinfo_client': # TODO: serverinfo_client + ftype = 'bytes' + default = "b''" + elif member['type']['kind'] == 'be_uint16': + ftype = 'int' + default = '0' + elif member['type']['kind'] == 'uint8': + ftype = 'int' + default = '0' + elif member['type']['kind'] == 'rest': + ftype = 'bytes' + default = "b'\\x00'" + elif member['type']['kind'] == 'sha256': + ftype = 'Annotated[bytes, 32]' + default = "bytes(32)" + elif member['type']['kind'] == 'data': + ftype = 'bytes' + default = "b'\\x00'" + if member['type']['size'] == 'specified_before': + args.append('data_size: Optional[int] = None') + else: + raise ValueError(f"Error: unknown data size {member['type']}") + # {"name": ["mode"], "type": {"kind": "enum", "enum": ["chat"]}}, + elif member['type']['kind'] == 'enum': + enum_name: str = name_to_camel(member['type']['enum']) + ftype = 'int' + default = self.get_default_enum7(enum_name) + default = f"enum7.{default}.value" + elif member['type']['kind'] in ('int32', 'tick'): + ftype = 'int' + default = '0' + elif member['type']['kind'] == 'boolean': + ftype = 'bool' + default = 'False' + elif member['type']['kind'] == 'tune_param': + ftype = 'float' + default = '0.0' + elif member['type']['kind'] == 'snapshot_object': + # TODO: think about snapshot_object + ftype = 'int' + default = '0' + elif member['type']['kind'] == 'array': + size: int = member['type']['count'] + if size is None: + print("Error: size is none for the following member") + print(member) + exit(1) + arr_member: ArrayMemberTypeJson = member['type']['member_type'] + if arr_member['kind'] == 'string': + ftype = f'Annotated[list[str], {size}]' + default = '[' + ', '.join(["''"] * size) + ']' + elif arr_member['kind'] == 'boolean': + ftype = f'Annotated[list[bool], {size}]' + default = '[' + ', '.join(["False"] * size) + ']' + elif arr_member['kind'] in ('int32', 'tick', 'enum'): + ftype = f'Annotated[list[int], {size}]' + default = '[' + ', '.join(["0"] * size) + ']' + else: + raise ValueError( \ + f"Error: unknown array member type {member['type']}") + # Initializing lists with defaults + # And type annotation can get quite long + # So split it in two lines + default = f'\\\n {default}' + elif member['type']['kind'] == 'flags': # TODO: think about flags + ftype = 'int' + default = '0' + elif member['type']['kind'] == 'optional': + if member['type']['inner']['kind'] == 'string': + ftype = 'str' + default = "''" + elif member['type']['inner']['kind'] in ('int32', 'tick'): + ftype = 'int' + default = '0' + else: + raise \ + ValueError( \ + f"Error: unknown optional type {member['type']}") + else: + raise ValueError(f"Error: unknown type {member['type']}") + name = name_to_snake(member["name"]) + manual_default = get_default(f"{message_type}.{name_snake}.{name}") + if manual_default: + default = manual_default + args.append(f'{name}: {ftype} = {default}') + return args + def write_init_method_header_connless7( self, out_file: TextIO, @@ -573,33 +692,9 @@ class CodeGenerator(): f' self{comma}') args: list[str] = [] for member in msg['members']: - ftype = 'int' - default = '-1' - if member['type']['kind'] == 'packed_addresses': # TODO: packed_addreses default value - ftype = 'list[MastersrvAddr]' - default = '[]' - elif member['type']['kind'] == 'serverinfo_client': # TODO: serverinfo_client - ftype = 'bytes' - default = "b''" - elif member['type']['kind'] == 'be_uint16': - ftype = 'int' - default = '0' - elif member['type']['kind'] == 'uint8': - ftype = 'int' - default = '0' - elif member['type']['kind'] == 'int32': - ftype = 'int' - default = '0' - elif member['type']['kind'] == 'string': - ftype = 'str' - default = "'default'" - else: - raise ValueError(f"Error: unknown type {member['type']}") - name = name_to_snake(member["name"]) - manual_default = get_default(f"connless.{name_snake}.{name}") - if manual_default: - default = manual_default - args.append(f' {name}: {ftype} = {default}') + mem_defs: list[str] = self.gen_init_member_header_def(member, name_snake, 'connless') + for mem_def in mem_defs: + args.append(f' {mem_def}') out_file.write(',\n'.join(args) + '\n') out_file.write(' ) -> None:\n') @@ -619,94 +714,9 @@ class CodeGenerator(): f' chunk_header: ChunkHeader = ChunkHeader(){comma}') args: list[str] = [] for member in msg['members']: - # { - # 'name': ['message'], - # 'type': { - # 'kind': 'string', - # 'disallow_cc': False - # } - # } - ftype = 'int' - default = '-1' - if member['type']['kind'] == 'string': - ftype = 'str' - default = "'default'" - elif member['type']['kind'] == 'rest': - ftype = 'bytes' - default = "b'\\x00'" - elif member['type']['kind'] == 'sha256': - ftype = 'Annotated[bytes, 32]' - default = "bytes(32)" - elif member['type']['kind'] == 'data': - ftype = 'bytes' - default = "b'\\x00'" - if member['type']['size'] == 'specified_before': - args.append(' data_size: Optional[int] = None') - else: - raise ValueError(f"Error: unknown data size {member['type']}") - # {"name": ["mode"], "type": {"kind": "enum", "enum": ["chat"]}}, - elif member['type']['kind'] == 'enum': - enum_name: str = name_to_camel(member['type']['enum']) - ftype = 'int' - default = self.get_default_enum7(enum_name) - default = f"enum7.{default}.value" - elif member['type']['kind'] in ('int32', 'tick'): - ftype = 'int' - default = '0' - elif member['type']['kind'] == 'boolean': - ftype = 'bool' - default = 'False' - elif member['type']['kind'] == 'tune_param': - ftype = 'float' - default = '0.0' - elif member['type']['kind'] == 'snapshot_object': - # TODO: think about snapshot_object - ftype = 'int' - default = '0' - elif member['type']['kind'] == 'array': - size: int = member['type']['count'] - if size is None: - print("Error: size is none for the following message") - print(msg) - exit(1) - arr_member: ArrayMemberTypeJson = member['type']['member_type'] - if arr_member['kind'] == 'string': - ftype = f'Annotated[list[str], {size}]' - default = '[' + ', '.join(["''"] * size) + ']' - elif arr_member['kind'] == 'boolean': - ftype = f'Annotated[list[bool], {size}]' - default = '[' + ', '.join(["False"] * size) + ']' - elif arr_member['kind'] in ('int32', 'tick', 'enum'): - ftype = f'Annotated[list[int], {size}]' - default = '[' + ', '.join(["0"] * size) + ']' - else: - raise ValueError( \ - f"Error: unknown array member type {member['type']}") - # Initializing lists with defaults - # And type annotation can get quite long - # So split it in two lines - default = f'\\\n {default}' - elif member['type']['kind'] == 'flags': # TODO: think about flags - ftype = 'int' - default = '0' - elif member['type']['kind'] == 'optional': - if member['type']['inner']['kind'] == 'string': - ftype = 'str' - default = "''" - elif member['type']['inner']['kind'] in ('int32', 'tick'): - ftype = 'int' - default = '0' - else: - raise \ - ValueError( \ - f"Error: unknown optional type {member['type']}") - else: - raise ValueError(f"Error: unknown type {member['type']}") - name = name_to_snake(member["name"]) - manual_default = get_default(f"{game}.{name_snake}.{name}") - if manual_default: - default = manual_default - args.append(f' {name}: {ftype} = {default}') + mem_defs: list[str] = self.gen_init_member_header_def(member, name_snake, game) + for mem_def in mem_defs: + args.append(f' {mem_def}') out_file.write(',\n'.join(args) + '\n') out_file.write(' ) -> None:\n')