Use named default for enums and move enum file
This commit is contained in:
parent
58051469f2
commit
90b43608b9
|
@ -46,6 +46,10 @@ class ArrayMemberTypeJson(TypedDict):
|
|||
class NetMessageMemberTypeJson(TypedDict):
|
||||
kind: KIND
|
||||
inner: InnerNetMessageMemberTypeJson
|
||||
|
||||
# enums
|
||||
enum: list[str]
|
||||
|
||||
# strings
|
||||
disallow_cc: bool
|
||||
|
||||
|
@ -164,7 +168,8 @@ def gen_unpack_members(msg: NetMessageJson) -> str:
|
|||
raise ValueError(f"Error: unknown data size {member['type']}")
|
||||
# {"name": ["mode"], "type": {"kind": "enum", "enum": ["chat"]}},
|
||||
elif member['type']['kind'] == 'enum':
|
||||
unpacker = 'int() # TODO: this is a enum'
|
||||
enum_name: str = name_to_camel(member['type']['enum']).upper()
|
||||
unpacker = f"int() # enum {enum_name}"
|
||||
elif member['type']['kind'] in ('int32', 'tick'):
|
||||
unpacker = 'int()'
|
||||
elif member['type']['kind'] == 'boolean':
|
||||
|
@ -187,6 +192,8 @@ def gen_unpack_members(msg: NetMessageJson) -> str:
|
|||
else:
|
||||
unpacker = 'str()'
|
||||
elif arr_member['kind'] == 'enum':
|
||||
# TODO: can we represent the enum as text
|
||||
# instead of as magic number?
|
||||
unpacker = 'int() # TODO: this is a enum'
|
||||
elif arr_member['kind'] == 'boolean':
|
||||
unpacker = 'int() == 1'
|
||||
|
@ -220,6 +227,7 @@ def gen_unpack_members(msg: NetMessageJson) -> str:
|
|||
def get_dependencies(msg: NetMessageJson) -> str:
|
||||
packer_deps: list[str] = []
|
||||
typing_deps: list[str] = []
|
||||
need_enums: bool = False
|
||||
for member in msg['members']:
|
||||
if member['type']['kind'] == 'string':
|
||||
packer_deps.append('pack_str')
|
||||
|
@ -236,6 +244,7 @@ def get_dependencies(msg: NetMessageJson) -> str:
|
|||
raise ValueError(f"Error: unknown data size {member['type']}")
|
||||
# {"name": ["mode"], "type": {"kind": "enum", "enum": ["chat"]}},
|
||||
elif member['type']['kind'] == 'enum':
|
||||
need_enums = True
|
||||
packer_deps.append('pack_int')
|
||||
elif member['type']['kind'] in ('int32', 'tick'):
|
||||
packer_deps.append('pack_int')
|
||||
|
@ -255,6 +264,7 @@ def get_dependencies(msg: NetMessageJson) -> str:
|
|||
if arr_member['disallow_cc']:
|
||||
packer_deps.append('SANITIZE_CC')
|
||||
elif arr_member['kind'] == 'enum':
|
||||
need_enums = True
|
||||
packer_deps.append('pack_int')
|
||||
elif arr_member['kind'] == 'boolean':
|
||||
packer_deps.append('pack_int')
|
||||
|
@ -280,6 +290,8 @@ def get_dependencies(msg: NetMessageJson) -> str:
|
|||
if len(typing_deps) > 0:
|
||||
res += 'from typing import ' + \
|
||||
', '.join(sorted(set(typing_deps))) + '\n'
|
||||
if need_enums:
|
||||
res += 'import twnet_parser.enum7 as enum7\n'
|
||||
return res
|
||||
|
||||
def pack_field(member: NetMessageMemberJson) -> str:
|
||||
|
@ -382,31 +394,10 @@ def get_default(field_path: str) -> Optional[str]:
|
|||
print(f" please check {def_file} for errors")
|
||||
exit(1)
|
||||
|
||||
def gen_enum_file7(enums: list[GameEnumJson]):
|
||||
enum_code: str = ''
|
||||
enum: GameEnumJson
|
||||
for enum in enums:
|
||||
base: str = name_to_snake(enum['name']).upper()
|
||||
val: GameEnumValueJson
|
||||
for val in enum['values']:
|
||||
sub: str = name_to_snake(val['name']).upper()
|
||||
enum_code += f"{base}_{sub}: int = {val['value']}\n"
|
||||
enum_code += "\n"
|
||||
# cut off last doubled newline
|
||||
# because we do not split a section anymore
|
||||
enum_code = enum_code[:-1]
|
||||
dirname = os.path.dirname(__file__)
|
||||
file_path= os.path.join(
|
||||
dirname,
|
||||
'../twnet_parser/msg_matcher/enum7.py')
|
||||
# if os.path.exists(file_path):
|
||||
# print(f"Warning: file already exists! {file_path}")
|
||||
# return
|
||||
with open(file_path, 'w') as out_file:
|
||||
print(f"Generating {file_path} ...")
|
||||
out_file.write(enum_code)
|
||||
|
||||
class CodeGenerator():
|
||||
def __init__(self) -> None:
|
||||
self.game_enums: list[GameEnumJson] = []
|
||||
|
||||
def generate_msg(
|
||||
self,
|
||||
msg: NetMessageJson,
|
||||
|
@ -465,8 +456,9 @@ class CodeGenerator():
|
|||
# {"name": ["mode"], "type": {"kind": "enum", "enum": ["chat"]}},
|
||||
elif member['type']['kind'] == 'enum':
|
||||
ftype = 'int'
|
||||
default = '0'
|
||||
# TODO: use ENUM_NAME_SOME_VALUE as default here
|
||||
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'
|
||||
|
@ -602,15 +594,59 @@ class CodeGenerator():
|
|||
out_file.write(' def pack(self) -> bytes:\n')
|
||||
out_file.write(gen_pack_return(msg))
|
||||
|
||||
def get_default_enum7(self, enum_name: str) -> str:
|
||||
"""
|
||||
enum_name has to be snake case
|
||||
can be lower or upper case does not matter
|
||||
|
||||
If for example enum_name 'chat' is given
|
||||
it returns 'CHAT_NONE'
|
||||
"""
|
||||
enum_name = enum_name.upper()
|
||||
enum: GameEnumJson
|
||||
for enum in self.game_enums:
|
||||
base: str = name_to_snake(enum['name']).upper()
|
||||
if base != enum_name:
|
||||
continue
|
||||
val: GameEnumValueJson
|
||||
for val in enum['values']:
|
||||
sub: str = name_to_snake(val['name']).upper()
|
||||
return f"{base}_{sub}"
|
||||
raise ValueError(f"Enum not found '{enum_name}'")
|
||||
|
||||
def gen_enum_file7(self) -> None:
|
||||
enum_code: str = ''
|
||||
enum: GameEnumJson
|
||||
for enum in self.game_enums:
|
||||
base: str = name_to_snake(enum['name']).upper()
|
||||
val: GameEnumValueJson
|
||||
for val in enum['values']:
|
||||
sub: str = name_to_snake(val['name']).upper()
|
||||
enum_code += f"{base}_{sub}: int = {val['value']}\n"
|
||||
enum_code += "\n"
|
||||
# cut off last doubled newline
|
||||
# because we do not split a section anymore
|
||||
enum_code = enum_code[:-1]
|
||||
dirname = os.path.dirname(__file__)
|
||||
file_path= os.path.join(
|
||||
dirname,
|
||||
'../twnet_parser/enum7.py')
|
||||
# if os.path.exists(file_path):
|
||||
# print(f"Warning: file already exists! {file_path}")
|
||||
# return
|
||||
with open(file_path, 'w') as out_file:
|
||||
print(f"Generating {file_path} ...")
|
||||
out_file.write(enum_code)
|
||||
|
||||
def generate(self, spec: str) -> None:
|
||||
print(f"generating classes from {spec} ...")
|
||||
with open(spec) as spec_io:
|
||||
spec_data: SpecJson = json.load(spec_io)
|
||||
# for msg in [spec_data['game_messages'][1]]:
|
||||
game_enums: list[GameEnumJson] = spec_data['game_enumerations']
|
||||
self.game_enums = spec_data['game_enumerations']
|
||||
game_messages: list[NetMessageJson] = spec_data['game_messages']
|
||||
system_messages: list[NetMessageJson] = spec_data['system_messages']
|
||||
gen_enum_file7(game_enums)
|
||||
self.gen_enum_file7()
|
||||
gen_match_file7('game', game_messages)
|
||||
gen_match_file7('system', system_messages)
|
||||
for msg in game_messages:
|
||||
|
|
|
@ -4,11 +4,12 @@ from twnet_parser.pretty_print import PrettyPrint
|
|||
from twnet_parser.packer import Unpacker
|
||||
from twnet_parser.chunk_header import ChunkHeader
|
||||
from twnet_parser.packer import pack_int
|
||||
import twnet_parser.enum7 as enum7
|
||||
|
||||
class MsgClEmoticon(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
emoticon: int = 0
|
||||
emoticon: int = enum7.EMOTICON_OOP
|
||||
) -> None:
|
||||
self.message_name = 'cl_emoticon'
|
||||
self.system_message = False
|
||||
|
@ -21,7 +22,7 @@ class MsgClEmoticon(PrettyPrint):
|
|||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.emoticon = unpacker.get_int() # TODO: this is a enum
|
||||
self.emoticon = unpacker.get_int() # enum EMOTICON
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
|
|
|
@ -4,11 +4,12 @@ from twnet_parser.pretty_print import PrettyPrint
|
|||
from twnet_parser.packer import Unpacker
|
||||
from twnet_parser.chunk_header import ChunkHeader
|
||||
from twnet_parser.packer import SANITIZE_CC, pack_int, pack_str
|
||||
import twnet_parser.enum7 as enum7
|
||||
|
||||
class MsgClSay(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
mode: int = 0,
|
||||
mode: int = enum7.CHAT_NONE,
|
||||
target: int = 0,
|
||||
message: str = 'default'
|
||||
) -> None:
|
||||
|
@ -25,7 +26,7 @@ class MsgClSay(PrettyPrint):
|
|||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.mode = unpacker.get_int() # TODO: this is a enum
|
||||
self.mode = unpacker.get_int() # enum CHAT
|
||||
self.target = unpacker.get_int()
|
||||
self.message = unpacker.get_str(SANITIZE_CC)
|
||||
return True
|
||||
|
|
|
@ -4,11 +4,12 @@ from twnet_parser.pretty_print import PrettyPrint
|
|||
from twnet_parser.packer import Unpacker
|
||||
from twnet_parser.chunk_header import ChunkHeader
|
||||
from twnet_parser.packer import pack_int
|
||||
import twnet_parser.enum7 as enum7
|
||||
|
||||
class MsgClSetSpectatorMode(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
spec_mode: int = 0,
|
||||
spec_mode: int = enum7.SPEC_FREEVIEW,
|
||||
spectator_id: int = 0
|
||||
) -> None:
|
||||
self.message_name = 'cl_set_spectator_mode'
|
||||
|
@ -23,7 +24,7 @@ class MsgClSetSpectatorMode(PrettyPrint):
|
|||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.spec_mode = unpacker.get_int() # TODO: this is a enum
|
||||
self.spec_mode = unpacker.get_int() # enum SPEC
|
||||
self.spectator_id = unpacker.get_int()
|
||||
return True
|
||||
|
||||
|
|
|
@ -4,11 +4,12 @@ from twnet_parser.pretty_print import PrettyPrint
|
|||
from twnet_parser.packer import Unpacker
|
||||
from twnet_parser.chunk_header import ChunkHeader
|
||||
from twnet_parser.packer import pack_int
|
||||
import twnet_parser.enum7 as enum7
|
||||
|
||||
class MsgClSetTeam(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
team: int = 0
|
||||
team: int = enum7.TEAM_SPECTATORS
|
||||
) -> None:
|
||||
self.message_name = 'cl_set_team'
|
||||
self.system_message = False
|
||||
|
@ -21,7 +22,7 @@ class MsgClSetTeam(PrettyPrint):
|
|||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.team = unpacker.get_int() # TODO: this is a enum
|
||||
self.team = unpacker.get_int() # enum TEAM
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
|
|
|
@ -4,13 +4,14 @@ from twnet_parser.pretty_print import PrettyPrint
|
|||
from twnet_parser.packer import Unpacker
|
||||
from twnet_parser.chunk_header import ChunkHeader
|
||||
from twnet_parser.packer import SANITIZE_CC, pack_int, pack_str
|
||||
import twnet_parser.enum7 as enum7
|
||||
|
||||
class MsgDeClientEnter(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
name: str = 'default',
|
||||
client_id: int = 0,
|
||||
team: int = 0
|
||||
team: int = enum7.TEAM_SPECTATORS
|
||||
) -> None:
|
||||
self.message_name = 'de_client_enter'
|
||||
self.system_message = False
|
||||
|
@ -27,7 +28,7 @@ class MsgDeClientEnter(PrettyPrint):
|
|||
unpacker = Unpacker(data)
|
||||
self.name = unpacker.get_str(SANITIZE_CC)
|
||||
self.client_id = unpacker.get_int()
|
||||
self.team = unpacker.get_int() # TODO: this is a enum
|
||||
self.team = unpacker.get_int() # enum TEAM
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
|
|
|
@ -4,11 +4,12 @@ from twnet_parser.pretty_print import PrettyPrint
|
|||
from twnet_parser.packer import Unpacker
|
||||
from twnet_parser.chunk_header import ChunkHeader
|
||||
from twnet_parser.packer import SANITIZE_CC, pack_int, pack_str
|
||||
import twnet_parser.enum7 as enum7
|
||||
|
||||
class MsgSvChat(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
mode: int = 0,
|
||||
mode: int = enum7.CHAT_NONE,
|
||||
client_id: int = 0,
|
||||
target_id: int = 0,
|
||||
message: str = 'default'
|
||||
|
@ -27,7 +28,7 @@ class MsgSvChat(PrettyPrint):
|
|||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.mode = unpacker.get_int() # TODO: this is a enum
|
||||
self.mode = unpacker.get_int() # enum CHAT
|
||||
self.client_id = unpacker.get_int()
|
||||
self.target_id = unpacker.get_int()
|
||||
self.message = unpacker.get_str(SANITIZE_CC)
|
||||
|
|
|
@ -5,13 +5,14 @@ from twnet_parser.packer import Unpacker
|
|||
from twnet_parser.chunk_header import ChunkHeader
|
||||
from twnet_parser.packer import SANITIZE_CC, pack_int, pack_str
|
||||
from typing import Annotated
|
||||
import twnet_parser.enum7 as enum7
|
||||
|
||||
class MsgSvClientInfo(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
client_id: int = 0,
|
||||
local: bool = False,
|
||||
team: int = 0,
|
||||
team: int = enum7.TEAM_SPECTATORS,
|
||||
name: str = 'default',
|
||||
clan: str = 'default',
|
||||
country: int = 0,
|
||||
|
@ -45,7 +46,7 @@ class MsgSvClientInfo(PrettyPrint):
|
|||
unpacker = Unpacker(data)
|
||||
self.client_id = unpacker.get_int()
|
||||
self.local = unpacker.get_int() == 1
|
||||
self.team = unpacker.get_int() # TODO: this is a enum
|
||||
self.team = unpacker.get_int() # enum TEAM
|
||||
self.name = unpacker.get_str(SANITIZE_CC)
|
||||
self.clan = unpacker.get_str(SANITIZE_CC)
|
||||
self.country = unpacker.get_int()
|
||||
|
|
|
@ -4,12 +4,13 @@ from twnet_parser.pretty_print import PrettyPrint
|
|||
from twnet_parser.packer import Unpacker
|
||||
from twnet_parser.chunk_header import ChunkHeader
|
||||
from twnet_parser.packer import pack_int
|
||||
import twnet_parser.enum7 as enum7
|
||||
|
||||
class MsgSvEmoticon(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
client_id: int = 0,
|
||||
emoticon: int = 0
|
||||
emoticon: int = enum7.EMOTICON_OOP
|
||||
) -> None:
|
||||
self.message_name = 'sv_emoticon'
|
||||
self.system_message = False
|
||||
|
@ -24,7 +25,7 @@ class MsgSvEmoticon(PrettyPrint):
|
|||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.client_id = unpacker.get_int()
|
||||
self.emoticon = unpacker.get_int() # TODO: this is a enum
|
||||
self.emoticon = unpacker.get_int() # enum EMOTICON
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
|
|
|
@ -4,12 +4,13 @@ from twnet_parser.pretty_print import PrettyPrint
|
|||
from twnet_parser.packer import Unpacker
|
||||
from twnet_parser.chunk_header import ChunkHeader
|
||||
from twnet_parser.packer import pack_int
|
||||
import twnet_parser.enum7 as enum7
|
||||
|
||||
class MsgSvTeam(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
client_id: int = 0,
|
||||
team: int = 0,
|
||||
team: int = enum7.TEAM_SPECTATORS,
|
||||
silent: bool = False,
|
||||
cooldown_tick: int = 0
|
||||
) -> None:
|
||||
|
@ -28,7 +29,7 @@ class MsgSvTeam(PrettyPrint):
|
|||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.client_id = unpacker.get_int()
|
||||
self.team = unpacker.get_int() # TODO: this is a enum
|
||||
self.team = unpacker.get_int() # enum TEAM
|
||||
self.silent = unpacker.get_int() == 1
|
||||
self.cooldown_tick = unpacker.get_int()
|
||||
return True
|
||||
|
|
|
@ -4,12 +4,13 @@ from twnet_parser.pretty_print import PrettyPrint
|
|||
from twnet_parser.packer import Unpacker
|
||||
from twnet_parser.chunk_header import ChunkHeader
|
||||
from twnet_parser.packer import SANITIZE_CC, pack_int, pack_str
|
||||
import twnet_parser.enum7 as enum7
|
||||
|
||||
class MsgSvVoteSet(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
client_id: int = 0,
|
||||
type: int = 0,
|
||||
type: int = enum7.VOTE_UNKNOWN,
|
||||
timeout: int = 0,
|
||||
description: str = 'default',
|
||||
reason: str = 'default'
|
||||
|
@ -30,7 +31,7 @@ class MsgSvVoteSet(PrettyPrint):
|
|||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.client_id = unpacker.get_int()
|
||||
self.type = unpacker.get_int() # TODO: this is a enum
|
||||
self.type = unpacker.get_int() # enum VOTE
|
||||
self.timeout = unpacker.get_int()
|
||||
self.description = unpacker.get_str(SANITIZE_CC)
|
||||
self.reason = unpacker.get_str(SANITIZE_CC)
|
||||
|
|
|
@ -4,11 +4,12 @@ from twnet_parser.pretty_print import PrettyPrint
|
|||
from twnet_parser.packer import Unpacker
|
||||
from twnet_parser.chunk_header import ChunkHeader
|
||||
from twnet_parser.packer import pack_int
|
||||
import twnet_parser.enum7 as enum7
|
||||
|
||||
class MsgSvWeaponPickup(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
weapon: int = 0
|
||||
weapon: int = enum7.WEAPON_HAMMER
|
||||
) -> None:
|
||||
self.message_name = 'sv_weapon_pickup'
|
||||
self.system_message = False
|
||||
|
@ -21,7 +22,7 @@ class MsgSvWeaponPickup(PrettyPrint):
|
|||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.weapon = unpacker.get_int() # TODO: this is a enum
|
||||
self.weapon = unpacker.get_int() # enum WEAPON
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
|
|
Loading…
Reference in a new issue