diff --git a/scripts/generate_messages.py b/scripts/generate_messages.py index 3efc1f9..097e830 100755 --- a/scripts/generate_messages.py +++ b/scripts/generate_messages.py @@ -3,7 +3,8 @@ import os import json -from typing import TypedDict, Literal, Optional, Dict, Union +from typing import \ + TypedDict, Literal, Optional, Dict, Union, TextIO KIND = Literal[ \ 'int32', \ @@ -398,6 +399,108 @@ class CodeGenerator(): def __init__(self) -> None: self.game_enums: list[GameEnumJson] = [] + def write_init_method_header( + self, + out_file: TextIO, + msg: NetMessageJson, + game: Literal['system', 'game'], + name_snake: str + ) -> None: + out_file.write(' def __init__(\n') + out_file.write(' self,\n') + 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': + ftype = 'int' + enum_name: str = name_to_snake(member['type']['enum']) + default = self.get_default_enum7(enum_name) + default = f"enum7.{default}" + 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}') + out_file.write(',\n'.join(args) + '\n') + out_file.write(' ) -> None:\n') + def generate_msg( self, msg: NetMessageJson, @@ -424,100 +527,10 @@ class CodeGenerator(): out_file.write(get_dependencies(msg)) out_file.write('\n') out_file.write(f'class Msg{name_camel}(PrettyPrint):\n') - out_file.write(' def __init__(\n') - out_file.write(' self,\n') - 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': - ftype = 'int' - enum_name: str = name_to_snake(member['type']['enum']) - default = self.get_default_enum7(enum_name) - default = f"enum7.{default}" - 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}') - out_file.write(',\n'.join(args) + '\n') - out_file.write(' ) -> None:\n') + if len(msg['members']) > 0: + self.write_init_method_header(out_file, msg, game, name_snake) + else: + out_file.write(' def __init__(self) -> None:\n') out_file.write(f" self.message_name = '{name_snake}'\n") sys: str = 'True' if game == 'system' else 'False' out_file.write(f" self.system_message = {sys}\n") diff --git a/twnet_parser/messages7/game/cl_kill.py b/twnet_parser/messages7/game/cl_kill.py index 89baf10..cef7447 100644 --- a/twnet_parser/messages7/game/cl_kill.py +++ b/twnet_parser/messages7/game/cl_kill.py @@ -4,10 +4,7 @@ from twnet_parser.pretty_print import PrettyPrint from twnet_parser.chunk_header import ChunkHeader class MsgClKill(PrettyPrint): - def __init__( - self, - - ) -> None: + def __init__(self) -> None: self.message_name = 'cl_kill' self.system_message = False self.header: ChunkHeader diff --git a/twnet_parser/messages7/game/cl_ready_change.py b/twnet_parser/messages7/game/cl_ready_change.py index 3602395..6bc7512 100644 --- a/twnet_parser/messages7/game/cl_ready_change.py +++ b/twnet_parser/messages7/game/cl_ready_change.py @@ -4,10 +4,7 @@ from twnet_parser.pretty_print import PrettyPrint from twnet_parser.chunk_header import ChunkHeader class MsgClReadyChange(PrettyPrint): - def __init__( - self, - - ) -> None: + def __init__(self) -> None: self.message_name = 'cl_ready_change' self.system_message = False self.header: ChunkHeader diff --git a/twnet_parser/messages7/game/sv_game_msg.py b/twnet_parser/messages7/game/sv_game_msg.py index c9f03ae..30e6dc5 100644 --- a/twnet_parser/messages7/game/sv_game_msg.py +++ b/twnet_parser/messages7/game/sv_game_msg.py @@ -4,10 +4,7 @@ from twnet_parser.pretty_print import PrettyPrint from twnet_parser.chunk_header import ChunkHeader class MsgSvGameMsg(PrettyPrint): - def __init__( - self, - - ) -> None: + def __init__(self) -> None: self.message_name = 'sv_game_msg' self.system_message = False self.header: ChunkHeader diff --git a/twnet_parser/messages7/game/sv_ready_to_enter.py b/twnet_parser/messages7/game/sv_ready_to_enter.py index a678590..da7c37d 100644 --- a/twnet_parser/messages7/game/sv_ready_to_enter.py +++ b/twnet_parser/messages7/game/sv_ready_to_enter.py @@ -4,10 +4,7 @@ from twnet_parser.pretty_print import PrettyPrint from twnet_parser.chunk_header import ChunkHeader class MsgSvReadyToEnter(PrettyPrint): - def __init__( - self, - - ) -> None: + def __init__(self) -> None: self.message_name = 'sv_ready_to_enter' self.system_message = False self.header: ChunkHeader diff --git a/twnet_parser/messages7/game/sv_vote_clear_options.py b/twnet_parser/messages7/game/sv_vote_clear_options.py index 4bdb3d5..43c238e 100644 --- a/twnet_parser/messages7/game/sv_vote_clear_options.py +++ b/twnet_parser/messages7/game/sv_vote_clear_options.py @@ -4,10 +4,7 @@ from twnet_parser.pretty_print import PrettyPrint from twnet_parser.chunk_header import ChunkHeader class MsgSvVoteClearOptions(PrettyPrint): - def __init__( - self, - - ) -> None: + def __init__(self) -> None: self.message_name = 'sv_vote_clear_options' self.system_message = False self.header: ChunkHeader diff --git a/twnet_parser/messages7/game/sv_vote_option_list_add.py b/twnet_parser/messages7/game/sv_vote_option_list_add.py index 0ad869c..14311f2 100644 --- a/twnet_parser/messages7/game/sv_vote_option_list_add.py +++ b/twnet_parser/messages7/game/sv_vote_option_list_add.py @@ -4,10 +4,7 @@ from twnet_parser.pretty_print import PrettyPrint from twnet_parser.chunk_header import ChunkHeader class MsgSvVoteOptionListAdd(PrettyPrint): - def __init__( - self, - - ) -> None: + def __init__(self) -> None: self.message_name = 'sv_vote_option_list_add' self.system_message = False self.header: ChunkHeader diff --git a/twnet_parser/messages7/system/con_ready.py b/twnet_parser/messages7/system/con_ready.py index cead895..12c8abc 100644 --- a/twnet_parser/messages7/system/con_ready.py +++ b/twnet_parser/messages7/system/con_ready.py @@ -4,10 +4,7 @@ from twnet_parser.pretty_print import PrettyPrint from twnet_parser.chunk_header import ChunkHeader class MsgConReady(PrettyPrint): - def __init__( - self, - - ) -> None: + def __init__(self) -> None: self.message_name = 'con_ready' self.system_message = True self.header: ChunkHeader diff --git a/twnet_parser/messages7/system/enter_game.py b/twnet_parser/messages7/system/enter_game.py index cd1dbb7..a5f0fb1 100644 --- a/twnet_parser/messages7/system/enter_game.py +++ b/twnet_parser/messages7/system/enter_game.py @@ -4,10 +4,7 @@ from twnet_parser.pretty_print import PrettyPrint from twnet_parser.chunk_header import ChunkHeader class MsgEnterGame(PrettyPrint): - def __init__( - self, - - ) -> None: + def __init__(self) -> None: self.message_name = 'enter_game' self.system_message = True self.header: ChunkHeader diff --git a/twnet_parser/messages7/system/ping.py b/twnet_parser/messages7/system/ping.py index 2319805..1610d9d 100644 --- a/twnet_parser/messages7/system/ping.py +++ b/twnet_parser/messages7/system/ping.py @@ -4,10 +4,7 @@ from twnet_parser.pretty_print import PrettyPrint from twnet_parser.chunk_header import ChunkHeader class MsgPing(PrettyPrint): - def __init__( - self, - - ) -> None: + def __init__(self) -> None: self.message_name = 'ping' self.system_message = True self.header: ChunkHeader diff --git a/twnet_parser/messages7/system/ping_reply.py b/twnet_parser/messages7/system/ping_reply.py index ee3d9e3..2145e25 100644 --- a/twnet_parser/messages7/system/ping_reply.py +++ b/twnet_parser/messages7/system/ping_reply.py @@ -4,10 +4,7 @@ from twnet_parser.pretty_print import PrettyPrint from twnet_parser.chunk_header import ChunkHeader class MsgPingReply(PrettyPrint): - def __init__( - self, - - ) -> None: + def __init__(self) -> None: self.message_name = 'ping_reply' self.system_message = True self.header: ChunkHeader diff --git a/twnet_parser/messages7/system/rcon_auth_off.py b/twnet_parser/messages7/system/rcon_auth_off.py index ed800d5..67bd4da 100644 --- a/twnet_parser/messages7/system/rcon_auth_off.py +++ b/twnet_parser/messages7/system/rcon_auth_off.py @@ -4,10 +4,7 @@ from twnet_parser.pretty_print import PrettyPrint from twnet_parser.chunk_header import ChunkHeader class MsgRconAuthOff(PrettyPrint): - def __init__( - self, - - ) -> None: + def __init__(self) -> None: self.message_name = 'rcon_auth_off' self.system_message = True self.header: ChunkHeader diff --git a/twnet_parser/messages7/system/rcon_auth_on.py b/twnet_parser/messages7/system/rcon_auth_on.py index 2abbf07..80b2dfc 100644 --- a/twnet_parser/messages7/system/rcon_auth_on.py +++ b/twnet_parser/messages7/system/rcon_auth_on.py @@ -4,10 +4,7 @@ from twnet_parser.pretty_print import PrettyPrint from twnet_parser.chunk_header import ChunkHeader class MsgRconAuthOn(PrettyPrint): - def __init__( - self, - - ) -> None: + def __init__(self) -> None: self.message_name = 'rcon_auth_on' self.system_message = True self.header: ChunkHeader diff --git a/twnet_parser/messages7/system/ready.py b/twnet_parser/messages7/system/ready.py index 58628a0..aea1c9c 100644 --- a/twnet_parser/messages7/system/ready.py +++ b/twnet_parser/messages7/system/ready.py @@ -4,10 +4,7 @@ from twnet_parser.pretty_print import PrettyPrint from twnet_parser.chunk_header import ChunkHeader class MsgReady(PrettyPrint): - def __init__( - self, - - ) -> None: + def __init__(self) -> None: self.message_name = 'ready' self.system_message = True self.header: ChunkHeader diff --git a/twnet_parser/messages7/system/request_map_data.py b/twnet_parser/messages7/system/request_map_data.py index 568770a..88c00c6 100644 --- a/twnet_parser/messages7/system/request_map_data.py +++ b/twnet_parser/messages7/system/request_map_data.py @@ -4,10 +4,7 @@ from twnet_parser.pretty_print import PrettyPrint from twnet_parser.chunk_header import ChunkHeader class MsgRequestMapData(PrettyPrint): - def __init__( - self, - - ) -> None: + def __init__(self) -> None: self.message_name = 'request_map_data' self.system_message = True self.header: ChunkHeader