First 0.6 draft
No 0.6 code is tested yet This commit is just about adding all 0.6 code without breaking existing 0.7 tests
This commit is contained in:
parent
d044e8dbad
commit
7c70e32725
|
@ -1033,7 +1033,8 @@ def match_connless{self.protocol_version}(msg_id: bytes, data: bytes) -> Connles
|
|||
raise ValueError(f"Enum not found '{enum_name}'")
|
||||
|
||||
def gen_enum_file(self) -> None:
|
||||
enum_code: str = 'from enum import Enum\n\n'
|
||||
enum_code = '# pylint: disable=duplicate-code\n' # TODO: remove
|
||||
enum_code += 'from enum import Enum\n\n'
|
||||
enum: GameEnumJson
|
||||
for enum in self.game_enums:
|
||||
base: str = name_to_camel(enum['name'])
|
||||
|
@ -1100,12 +1101,11 @@ def main() -> None:
|
|||
'../../libtw2/gamenet/generate/spec/teeworlds-0.7.5.json',
|
||||
'7'
|
||||
),
|
||||
SpecInfo(
|
||||
'../../libtw2/gamenet/generate/spec/teeworlds-0.6.json',
|
||||
'6'
|
||||
)
|
||||
]
|
||||
# SpecInfo(
|
||||
# '../../libtw2/gamenet/generate/spec/teeworlds-0.6.json',
|
||||
# '6'
|
||||
# )
|
||||
# ]
|
||||
for spec_info in spec_infos:
|
||||
spec_file = os.path.join(
|
||||
dirname,
|
||||
|
|
90
twnet_parser/enum6.py
Normal file
90
twnet_parser/enum6.py
Normal file
|
@ -0,0 +1,90 @@
|
|||
# pylint: skip-file
|
||||
from enum import Enum
|
||||
|
||||
class Emote(Enum):
|
||||
NORMAL: int = 0
|
||||
PAIN: int = 1
|
||||
HAPPY: int = 2
|
||||
SURPRISE: int = 3
|
||||
ANGRY: int = 4
|
||||
BLINK: int = 5
|
||||
|
||||
class Powerup(Enum):
|
||||
HEALTH: int = 0
|
||||
ARMOR: int = 1
|
||||
WEAPON: int = 2
|
||||
NINJA: int = 3
|
||||
|
||||
class Emoticon(Enum):
|
||||
OOP: int = 0
|
||||
EXCLAMATION: int = 1
|
||||
HEARTS: int = 2
|
||||
DROP: int = 3
|
||||
DOTDOT: int = 4
|
||||
MUSIC: int = 5
|
||||
SORRY: int = 6
|
||||
GHOST: int = 7
|
||||
SUSHI: int = 8
|
||||
SPLATTEE: int = 9
|
||||
DEVILTEE: int = 10
|
||||
ZOMG: int = 11
|
||||
ZZZ: int = 12
|
||||
WTF: int = 13
|
||||
EYES: int = 14
|
||||
QUESTION: int = 15
|
||||
|
||||
class Weapon(Enum):
|
||||
HAMMER: int = 0
|
||||
PISTOL: int = 1
|
||||
SHOTGUN: int = 2
|
||||
GRENADE: int = 3
|
||||
RIFLE: int = 4
|
||||
NINJA: int = 5
|
||||
|
||||
class Team(Enum):
|
||||
SPECTATORS: int = -1
|
||||
RED: int = 0
|
||||
BLUE: int = 1
|
||||
|
||||
class Sound(Enum):
|
||||
GUN_FIRE: int = 0
|
||||
SHOTGUN_FIRE: int = 1
|
||||
GRENADE_FIRE: int = 2
|
||||
HAMMER_FIRE: int = 3
|
||||
HAMMER_HIT: int = 4
|
||||
NINJA_FIRE: int = 5
|
||||
GRENADE_EXPLODE: int = 6
|
||||
NINJA_HIT: int = 7
|
||||
RIFLE_FIRE: int = 8
|
||||
RIFLE_BOUNCE: int = 9
|
||||
WEAPON_SWITCH: int = 10
|
||||
PLAYER_PAIN_SHORT: int = 11
|
||||
PLAYER_PAIN_LONG: int = 12
|
||||
BODY_LAND: int = 13
|
||||
PLAYER_AIRJUMP: int = 14
|
||||
PLAYER_JUMP: int = 15
|
||||
PLAYER_DIE: int = 16
|
||||
PLAYER_SPAWN: int = 17
|
||||
PLAYER_SKID: int = 18
|
||||
TEE_CRY: int = 19
|
||||
HOOK_LOOP: int = 20
|
||||
HOOK_ATTACH_GROUND: int = 21
|
||||
HOOK_ATTACH_PLAYER: int = 22
|
||||
HOOK_NOATTACH: int = 23
|
||||
PICKUP_HEALTH: int = 24
|
||||
PICKUP_ARMOR: int = 25
|
||||
PICKUP_GRENADE: int = 26
|
||||
PICKUP_SHOTGUN: int = 27
|
||||
PICKUP_NINJA: int = 28
|
||||
WEAPON_SPAWN: int = 29
|
||||
WEAPON_NOAMMO: int = 30
|
||||
HIT: int = 31
|
||||
CHAT_SERVER: int = 32
|
||||
CHAT_CLIENT: int = 33
|
||||
CHAT_HIGHLIGHT: int = 34
|
||||
CTF_DROP: int = 35
|
||||
CTF_RETURN: int = 36
|
||||
CTF_GRAB_PL: int = 37
|
||||
CTF_GRAB_EN: int = 38
|
||||
CTF_CAPTURE: int = 39
|
||||
MENU: int = 40
|
|
@ -1,3 +1,4 @@
|
|||
# pylint: skip-file
|
||||
from enum import Enum
|
||||
|
||||
class Pickup(Enum):
|
||||
|
|
28
twnet_parser/messages6/connless/count.py
Normal file
28
twnet_parser/messages6/connless/count.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
from twnet_parser.pretty_print import PrettyPrint
|
||||
from twnet_parser.packer import Unpacker
|
||||
from twnet_parser.packer import pack_be_uint16
|
||||
from typing import Literal
|
||||
|
||||
class MsgCount(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
count: int = 0
|
||||
) -> None:
|
||||
self.message_type: Literal['connless'] = 'connless'
|
||||
self.message_name: str = 'connless.count'
|
||||
self.message_id: list[int] = [255, 255, 255, 255, 115, 105, 122, 50]
|
||||
|
||||
self.count: int = count
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.count = unpacker.get_be_uint16()
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_be_uint16(self.count)
|
22
twnet_parser/messages6/connless/forward_check.py
Normal file
22
twnet_parser/messages6/connless/forward_check.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
from twnet_parser.pretty_print import PrettyPrint
|
||||
from typing import Literal
|
||||
|
||||
class MsgForwardCheck(PrettyPrint):
|
||||
def __init__(
|
||||
self
|
||||
) -> None:
|
||||
self.message_type: Literal['connless'] = 'connless'
|
||||
self.message_name: str = 'connless.forward_check'
|
||||
self.message_id: list[int] = [255, 255, 255, 255, 102, 119, 63, 63]
|
||||
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return b''
|
22
twnet_parser/messages6/connless/forward_error.py
Normal file
22
twnet_parser/messages6/connless/forward_error.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
from twnet_parser.pretty_print import PrettyPrint
|
||||
from typing import Literal
|
||||
|
||||
class MsgForwardError(PrettyPrint):
|
||||
def __init__(
|
||||
self
|
||||
) -> None:
|
||||
self.message_type: Literal['connless'] = 'connless'
|
||||
self.message_name: str = 'connless.forward_error'
|
||||
self.message_id: list[int] = [255, 255, 255, 255, 102, 119, 101, 114]
|
||||
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return b''
|
22
twnet_parser/messages6/connless/forward_ok.py
Normal file
22
twnet_parser/messages6/connless/forward_ok.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
from twnet_parser.pretty_print import PrettyPrint
|
||||
from typing import Literal
|
||||
|
||||
class MsgForwardOk(PrettyPrint):
|
||||
def __init__(
|
||||
self
|
||||
) -> None:
|
||||
self.message_type: Literal['connless'] = 'connless'
|
||||
self.message_name: str = 'connless.forward_ok'
|
||||
self.message_id: list[int] = [255, 255, 255, 255, 102, 119, 111, 107]
|
||||
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return b''
|
22
twnet_parser/messages6/connless/forward_response.py
Normal file
22
twnet_parser/messages6/connless/forward_response.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
from twnet_parser.pretty_print import PrettyPrint
|
||||
from typing import Literal
|
||||
|
||||
class MsgForwardResponse(PrettyPrint):
|
||||
def __init__(
|
||||
self
|
||||
) -> None:
|
||||
self.message_type: Literal['connless'] = 'connless'
|
||||
self.message_name: str = 'connless.forward_response'
|
||||
self.message_id: list[int] = [255, 255, 255, 255, 102, 119, 33, 33]
|
||||
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return b''
|
28
twnet_parser/messages6/connless/heartbeat.py
Normal file
28
twnet_parser/messages6/connless/heartbeat.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
from twnet_parser.pretty_print import PrettyPrint
|
||||
from twnet_parser.packer import Unpacker
|
||||
from twnet_parser.packer import pack_be_uint16
|
||||
from typing import Literal
|
||||
|
||||
class MsgHeartbeat(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
alt_port: int = 0
|
||||
) -> None:
|
||||
self.message_type: Literal['connless'] = 'connless'
|
||||
self.message_name: str = 'connless.heartbeat'
|
||||
self.message_id: list[int] = [255, 255, 255, 255, 98, 101, 97, 50]
|
||||
|
||||
self.alt_port: int = alt_port
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.alt_port = unpacker.get_be_uint16()
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_be_uint16(self.alt_port)
|
68
twnet_parser/messages6/connless/info.py
Normal file
68
twnet_parser/messages6/connless/info.py
Normal file
|
@ -0,0 +1,68 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
from twnet_parser.pretty_print import PrettyPrint
|
||||
from twnet_parser.packer import Unpacker
|
||||
from twnet_parser.packer import SANITIZE_CC, pack_str
|
||||
from typing import Literal
|
||||
|
||||
class MsgInfo(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
token: int = 0,
|
||||
version: str = 'default',
|
||||
name: str = 'default',
|
||||
map: str = 'default',
|
||||
game_type: str = 'default',
|
||||
flags: int = 0,
|
||||
num_players: int = 0,
|
||||
max_players: int = 0,
|
||||
num_clients: int = 0,
|
||||
max_clients: int = 0,
|
||||
clients: bytes = b''
|
||||
) -> None:
|
||||
self.message_type: Literal['connless'] = 'connless'
|
||||
self.message_name: str = 'connless.info'
|
||||
self.message_id: list[int] = [255, 255, 255, 255, 105, 110, 102, 51]
|
||||
|
||||
self.token: int = token
|
||||
self.version: str = version
|
||||
self.name: str = name
|
||||
self.map: str = map
|
||||
self.game_type: str = game_type
|
||||
self.flags: int = flags
|
||||
self.num_players: int = num_players
|
||||
self.max_players: int = max_players
|
||||
self.num_clients: int = num_clients
|
||||
self.max_clients: int = max_clients
|
||||
self.clients: bytes = clients
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.token = int(unpacker.get_str())
|
||||
self.version = unpacker.get_str(SANITIZE_CC)
|
||||
self.name = unpacker.get_str(SANITIZE_CC)
|
||||
self.map = unpacker.get_str(SANITIZE_CC)
|
||||
self.game_type = unpacker.get_str(SANITIZE_CC)
|
||||
self.flags = int(unpacker.get_str())
|
||||
self.num_players = int(unpacker.get_str())
|
||||
self.max_players = int(unpacker.get_str())
|
||||
self.num_clients = int(unpacker.get_str())
|
||||
self.max_clients = int(unpacker.get_str())
|
||||
self.clients = unpacker.get_raw()
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_str(str(self.token)) + \
|
||||
pack_str(self.version) + \
|
||||
pack_str(self.name) + \
|
||||
pack_str(self.map) + \
|
||||
pack_str(self.game_type) + \
|
||||
pack_str(str(self.flags)) + \
|
||||
pack_str(str(self.num_players)) + \
|
||||
pack_str(str(self.max_players)) + \
|
||||
pack_str(str(self.num_clients)) + \
|
||||
pack_str(str(self.max_clients)) + \
|
||||
self.clients
|
29
twnet_parser/messages6/connless/list.py
Normal file
29
twnet_parser/messages6/connless/list.py
Normal file
|
@ -0,0 +1,29 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
from twnet_parser.pretty_print import PrettyPrint
|
||||
from twnet_parser.packer import Unpacker
|
||||
from twnet_parser.master_server import MastersrvAddr
|
||||
from twnet_parser.packer import pack_packed_addresses
|
||||
from typing import Literal
|
||||
|
||||
class MsgList(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
servers: list[MastersrvAddr] = []
|
||||
) -> None:
|
||||
self.message_type: Literal['connless'] = 'connless'
|
||||
self.message_name: str = 'connless.list'
|
||||
self.message_id: list[int] = [255, 255, 255, 255, 108, 105, 115, 50]
|
||||
|
||||
self.servers: list[MastersrvAddr] = servers
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.servers = unpacker.get_packed_addresses()
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_packed_addresses(self.servers)
|
22
twnet_parser/messages6/connless/request_count.py
Normal file
22
twnet_parser/messages6/connless/request_count.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
from twnet_parser.pretty_print import PrettyPrint
|
||||
from typing import Literal
|
||||
|
||||
class MsgRequestCount(PrettyPrint):
|
||||
def __init__(
|
||||
self
|
||||
) -> None:
|
||||
self.message_type: Literal['connless'] = 'connless'
|
||||
self.message_name: str = 'connless.request_count'
|
||||
self.message_id: list[int] = [255, 255, 255, 255, 99, 111, 117, 50]
|
||||
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return b''
|
28
twnet_parser/messages6/connless/request_info.py
Normal file
28
twnet_parser/messages6/connless/request_info.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
from twnet_parser.pretty_print import PrettyPrint
|
||||
from twnet_parser.packer import Unpacker
|
||||
from twnet_parser.packer import pack_uint8
|
||||
from typing import Literal
|
||||
|
||||
class MsgRequestInfo(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
token: int = 0
|
||||
) -> None:
|
||||
self.message_type: Literal['connless'] = 'connless'
|
||||
self.message_name: str = 'connless.request_info'
|
||||
self.message_id: list[int] = [255, 255, 255, 255, 103, 105, 101, 51]
|
||||
|
||||
self.token: int = token
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.token = unpacker.get_uint8()
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_uint8(self.token)
|
22
twnet_parser/messages6/connless/request_list.py
Normal file
22
twnet_parser/messages6/connless/request_list.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
from twnet_parser.pretty_print import PrettyPrint
|
||||
from typing import Literal
|
||||
|
||||
class MsgRequestList(PrettyPrint):
|
||||
def __init__(
|
||||
self
|
||||
) -> None:
|
||||
self.message_type: Literal['connless'] = 'connless'
|
||||
self.message_name: str = 'connless.request_list'
|
||||
self.message_id: list[int] = [255, 255, 255, 255, 114, 101, 113, 50]
|
||||
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return b''
|
14
twnet_parser/messages6/control/accept.py
Normal file
14
twnet_parser/messages6/control/accept.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
from typing import Literal
|
||||
from twnet_parser.pretty_print import PrettyPrint
|
||||
|
||||
class CtrlAccept(PrettyPrint):
|
||||
def __init__(self) -> None:
|
||||
self.message_type: Literal['control'] = 'control'
|
||||
self.message_name: str = 'accept'
|
||||
self.message_id: int = 3
|
||||
|
||||
def unpack(self, data: bytes, we_are_a_client: bool = True) -> bool:
|
||||
return False
|
||||
|
||||
def pack(self, we_are_a_client: bool = True) -> bytes:
|
||||
return b''
|
29
twnet_parser/messages6/control/close.py
Normal file
29
twnet_parser/messages6/control/close.py
Normal file
|
@ -0,0 +1,29 @@
|
|||
from typing import Optional, Literal
|
||||
|
||||
from twnet_parser.pretty_print import PrettyPrint
|
||||
from twnet_parser.packer import Unpacker
|
||||
from twnet_parser.packer import pack_str
|
||||
|
||||
class CtrlClose(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
reason: Optional[str] = None
|
||||
) -> None:
|
||||
self.message_type: Literal['control'] = 'control'
|
||||
self.message_name: str = 'close'
|
||||
self.message_id: int = 4
|
||||
|
||||
self.reason: Optional[str] = reason
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes, we_are_a_client: bool = True) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.reason = unpacker.get_str() # TODO: this is an optional field
|
||||
return True
|
||||
|
||||
def pack(self, we_are_a_client: bool = True) -> bytes:
|
||||
if self.reason:
|
||||
return pack_str(self.reason)
|
||||
return b''
|
30
twnet_parser/messages6/control/connect.py
Normal file
30
twnet_parser/messages6/control/connect.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
from typing import Literal
|
||||
from twnet_parser.pretty_print import PrettyPrint
|
||||
|
||||
"""
|
||||
CtrlConnect
|
||||
|
||||
with security token from 0.6.5
|
||||
not compatible with 0.6.4 or earlier
|
||||
also not compatible with 0.7 or later
|
||||
"""
|
||||
class CtrlConnect(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
response_token: bytes = b'\xff\xff\xff\xff'
|
||||
) -> None:
|
||||
self.message_type: Literal['control'] = 'control'
|
||||
self.message_name: str = 'connect'
|
||||
self.message_id: int = 1
|
||||
|
||||
self.response_token: bytes = response_token
|
||||
|
||||
def unpack(self, data: bytes, we_are_a_client: bool = True) -> bool:
|
||||
# anti reflection attack
|
||||
if len(data) < 512:
|
||||
return False
|
||||
self.response_token = data[4:8]
|
||||
return True
|
||||
|
||||
def pack(self, we_are_a_client: bool = True) -> bytes:
|
||||
return bytes(4) + self.response_token + bytes(504)
|
26
twnet_parser/messages6/control/connect_accept.py
Normal file
26
twnet_parser/messages6/control/connect_accept.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
from typing import Literal
|
||||
from twnet_parser.pretty_print import PrettyPrint
|
||||
|
||||
"""
|
||||
CtrlConnectAccept
|
||||
|
||||
Only valid in 0.6.4 and earlier
|
||||
got removed in 0.6.5
|
||||
"""
|
||||
class CtrlConnectAccept(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
response_token: bytes = b'\xff\xff\xff\xff'
|
||||
) -> None:
|
||||
self.message_type: Literal['control'] = 'control'
|
||||
self.message_name: str = 'connect_accept'
|
||||
self.message_id: int = 2
|
||||
|
||||
self.response_token: bytes = response_token
|
||||
|
||||
def unpack(self, data: bytes, we_are_a_client: bool = True) -> bool:
|
||||
self.response_token = data[0:4]
|
||||
return True
|
||||
|
||||
def pack(self, we_are_a_client: bool = True) -> bytes:
|
||||
return self.response_token
|
14
twnet_parser/messages6/control/keep_alive.py
Normal file
14
twnet_parser/messages6/control/keep_alive.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
from typing import Literal
|
||||
from twnet_parser.pretty_print import PrettyPrint
|
||||
|
||||
class CtrlKeepAlive(PrettyPrint):
|
||||
def __init__(self) -> None:
|
||||
self.message_type: Literal['control'] = 'control'
|
||||
self.message_name: str = 'keep_alive'
|
||||
self.message_id: int = 0
|
||||
|
||||
def unpack(self, data: bytes, we_are_a_client: bool = True) -> bool:
|
||||
return False
|
||||
|
||||
def pack(self, we_are_a_client: bool = True) -> bytes:
|
||||
return b''
|
26
twnet_parser/messages6/control/token.py
Normal file
26
twnet_parser/messages6/control/token.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
from typing import Literal
|
||||
from twnet_parser.pretty_print import PrettyPrint
|
||||
|
||||
class CtrlToken(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
response_token: bytes = b'\xff\xff\xff\xff'
|
||||
) -> None:
|
||||
self.message_type: Literal['control'] = 'control'
|
||||
self.message_name: str = 'token'
|
||||
self.message_id: int = 5
|
||||
|
||||
self.response_token: bytes = response_token
|
||||
|
||||
def unpack(self, data: bytes, we_are_a_client: bool = True) -> bool:
|
||||
if not we_are_a_client:
|
||||
# anti reflection attack
|
||||
if len(data) < 512:
|
||||
return False
|
||||
self.response_token = data[0:4]
|
||||
return True
|
||||
|
||||
def pack(self, we_are_a_client: bool = True) -> bytes:
|
||||
if we_are_a_client:
|
||||
return self.response_token + bytes(508)
|
||||
return self.response_token
|
40
twnet_parser/messages6/game/cl_call_vote.py
Normal file
40
twnet_parser/messages6/game/cl_call_vote.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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_str
|
||||
from typing import Literal
|
||||
|
||||
class MsgClCallVote(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
type: str = 'default',
|
||||
value: str = 'default',
|
||||
reason: str = 'default'
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'game'
|
||||
self.message_name: str = 'cl_call_vote'
|
||||
self.system_message: bool = False
|
||||
self.message_id: int = 25
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.type: str = type
|
||||
self.value: str = value
|
||||
self.reason: str = reason
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.type = unpacker.get_str(SANITIZE_CC)
|
||||
self.value = unpacker.get_str(SANITIZE_CC)
|
||||
self.reason = unpacker.get_str(SANITIZE_CC)
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_str(self.type) + \
|
||||
pack_str(self.value) + \
|
||||
pack_str(self.reason)
|
56
twnet_parser/messages6/game/cl_change_info.py
Normal file
56
twnet_parser/messages6/game/cl_change_info.py
Normal file
|
@ -0,0 +1,56 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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
|
||||
from typing import Literal
|
||||
|
||||
class MsgClChangeInfo(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
name: str = 'default',
|
||||
clan: str = 'default',
|
||||
country: int = 0,
|
||||
skin: str = 'default',
|
||||
use_custom_color: bool = False,
|
||||
color_body: int = 0,
|
||||
color_feet: int = 0
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'game'
|
||||
self.message_name: str = 'cl_change_info'
|
||||
self.system_message: bool = False
|
||||
self.message_id: int = 21
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.name: str = name
|
||||
self.clan: str = clan
|
||||
self.country: int = country
|
||||
self.skin: str = skin
|
||||
self.use_custom_color: bool = use_custom_color
|
||||
self.color_body: int = color_body
|
||||
self.color_feet: int = color_feet
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.name = unpacker.get_str(SANITIZE_CC)
|
||||
self.clan = unpacker.get_str(SANITIZE_CC)
|
||||
self.country = unpacker.get_int()
|
||||
self.skin = unpacker.get_str(SANITIZE_CC)
|
||||
self.use_custom_color = unpacker.get_int() == 1
|
||||
self.color_body = unpacker.get_int()
|
||||
self.color_feet = unpacker.get_int()
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_str(self.name) + \
|
||||
pack_str(self.clan) + \
|
||||
pack_int(self.country) + \
|
||||
pack_str(self.skin) + \
|
||||
pack_int(self.use_custom_color) + \
|
||||
pack_int(self.color_body) + \
|
||||
pack_int(self.color_feet)
|
33
twnet_parser/messages6/game/cl_emoticon.py
Normal file
33
twnet_parser/messages6/game/cl_emoticon.py
Normal file
|
@ -0,0 +1,33 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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
|
||||
from typing import Literal
|
||||
import twnet_parser.enum6 as enum6
|
||||
|
||||
class MsgClEmoticon(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
emoticon: int = enum6.Emoticon.OOP.value
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'game'
|
||||
self.message_name: str = 'cl_emoticon'
|
||||
self.system_message: bool = False
|
||||
self.message_id: int = 23
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.emoticon: int = emoticon
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.emoticon = unpacker.get_int() # enum EMOTICON
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_int(self.emoticon)
|
26
twnet_parser/messages6/game/cl_kill.py
Normal file
26
twnet_parser/messages6/game/cl_kill.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
from twnet_parser.pretty_print import PrettyPrint
|
||||
from twnet_parser.chunk_header import ChunkHeader
|
||||
from typing import Literal
|
||||
|
||||
class MsgClKill(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader()
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'game'
|
||||
self.message_name: str = 'cl_kill'
|
||||
self.system_message: bool = False
|
||||
self.message_id: int = 22
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return b''
|
36
twnet_parser/messages6/game/cl_say.py
Normal file
36
twnet_parser/messages6/game/cl_say.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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
|
||||
from typing import Literal
|
||||
|
||||
class MsgClSay(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
team: bool = False,
|
||||
message: str = 'default'
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'game'
|
||||
self.message_name: str = 'cl_say'
|
||||
self.system_message: bool = False
|
||||
self.message_id: int = 17
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.team: bool = team
|
||||
self.message: str = message
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.team = unpacker.get_int() == 1
|
||||
self.message = unpacker.get_str(SANITIZE_CC)
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_int(self.team) + \
|
||||
pack_str(self.message)
|
32
twnet_parser/messages6/game/cl_set_spectator_mode.py
Normal file
32
twnet_parser/messages6/game/cl_set_spectator_mode.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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
|
||||
from typing import Literal
|
||||
|
||||
class MsgClSetSpectatorMode(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
spectator_id: int = 0
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'game'
|
||||
self.message_name: str = 'cl_set_spectator_mode'
|
||||
self.system_message: bool = False
|
||||
self.message_id: int = 19
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.spectator_id: int = spectator_id
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.spectator_id = unpacker.get_int()
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_int(self.spectator_id)
|
33
twnet_parser/messages6/game/cl_set_team.py
Normal file
33
twnet_parser/messages6/game/cl_set_team.py
Normal file
|
@ -0,0 +1,33 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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
|
||||
from typing import Literal
|
||||
import twnet_parser.enum6 as enum6
|
||||
|
||||
class MsgClSetTeam(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
team: int = enum6.Team.SPECTATORS.value
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'game'
|
||||
self.message_name: str = 'cl_set_team'
|
||||
self.system_message: bool = False
|
||||
self.message_id: int = 18
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.team: int = team
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.team = unpacker.get_int() # enum TEAM
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_int(self.team)
|
56
twnet_parser/messages6/game/cl_start_info.py
Normal file
56
twnet_parser/messages6/game/cl_start_info.py
Normal file
|
@ -0,0 +1,56 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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
|
||||
from typing import Literal
|
||||
|
||||
class MsgClStartInfo(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
name: str = 'default',
|
||||
clan: str = 'default',
|
||||
country: int = 0,
|
||||
skin: str = 'default',
|
||||
use_custom_color: bool = False,
|
||||
color_body: int = 0,
|
||||
color_feet: int = 0
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'game'
|
||||
self.message_name: str = 'cl_start_info'
|
||||
self.system_message: bool = False
|
||||
self.message_id: int = 20
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.name: str = name
|
||||
self.clan: str = clan
|
||||
self.country: int = country
|
||||
self.skin: str = skin
|
||||
self.use_custom_color: bool = use_custom_color
|
||||
self.color_body: int = color_body
|
||||
self.color_feet: int = color_feet
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.name = unpacker.get_str(SANITIZE_CC)
|
||||
self.clan = unpacker.get_str(SANITIZE_CC)
|
||||
self.country = unpacker.get_int()
|
||||
self.skin = unpacker.get_str(SANITIZE_CC)
|
||||
self.use_custom_color = unpacker.get_int() == 1
|
||||
self.color_body = unpacker.get_int()
|
||||
self.color_feet = unpacker.get_int()
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_str(self.name) + \
|
||||
pack_str(self.clan) + \
|
||||
pack_int(self.country) + \
|
||||
pack_str(self.skin) + \
|
||||
pack_int(self.use_custom_color) + \
|
||||
pack_int(self.color_body) + \
|
||||
pack_int(self.color_feet)
|
32
twnet_parser/messages6/game/cl_vote.py
Normal file
32
twnet_parser/messages6/game/cl_vote.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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
|
||||
from typing import Literal
|
||||
|
||||
class MsgClVote(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
vote: int = 0
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'game'
|
||||
self.message_name: str = 'cl_vote'
|
||||
self.system_message: bool = False
|
||||
self.message_id: int = 24
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.vote: int = vote
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.vote = unpacker.get_int()
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_int(self.vote)
|
32
twnet_parser/messages6/game/sv_broadcast.py
Normal file
32
twnet_parser/messages6/game/sv_broadcast.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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_str
|
||||
from typing import Literal
|
||||
|
||||
class MsgSvBroadcast(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
message: str = 'default'
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'game'
|
||||
self.message_name: str = 'sv_broadcast'
|
||||
self.system_message: bool = False
|
||||
self.message_id: int = 2
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.message: str = message
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.message = unpacker.get_str()
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_str(self.message)
|
40
twnet_parser/messages6/game/sv_chat.py
Normal file
40
twnet_parser/messages6/game/sv_chat.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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
|
||||
from typing import Literal
|
||||
|
||||
class MsgSvChat(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
team: bool = False,
|
||||
client_id: int = 0,
|
||||
message: str = 'default'
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'game'
|
||||
self.message_name: str = 'sv_chat'
|
||||
self.system_message: bool = False
|
||||
self.message_id: int = 3
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.team: bool = team
|
||||
self.client_id: int = client_id
|
||||
self.message: str = message
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.team = unpacker.get_int() == 1
|
||||
self.client_id = unpacker.get_int()
|
||||
self.message = unpacker.get_str(SANITIZE_CC)
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_int(self.team) + \
|
||||
pack_int(self.client_id) + \
|
||||
pack_str(self.message)
|
37
twnet_parser/messages6/game/sv_emoticon.py
Normal file
37
twnet_parser/messages6/game/sv_emoticon.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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
|
||||
from typing import Literal
|
||||
import twnet_parser.enum6 as enum6
|
||||
|
||||
class MsgSvEmoticon(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
client_id: int = 0,
|
||||
emoticon: int = enum6.Emoticon.OOP.value
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'game'
|
||||
self.message_name: str = 'sv_emoticon'
|
||||
self.system_message: bool = False
|
||||
self.message_id: int = 10
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.client_id: int = client_id
|
||||
self.emoticon: int = emoticon
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.client_id = unpacker.get_int()
|
||||
self.emoticon = unpacker.get_int() # enum EMOTICON
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_int(self.client_id) + \
|
||||
pack_int(self.emoticon)
|
32
twnet_parser/messages6/game/sv_extra_projectile.py
Normal file
32
twnet_parser/messages6/game/sv_extra_projectile.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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
|
||||
from typing import Literal
|
||||
|
||||
class MsgSvExtraProjectile(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
projectile: int = 0
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'game'
|
||||
self.message_name: str = 'sv_extra_projectile'
|
||||
self.system_message: bool = False
|
||||
self.message_id: int = 7
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.projectile: int = projectile
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.projectile = unpacker.get_int() # TODO: this is a snapshot object
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_int(self.projectile)
|
44
twnet_parser/messages6/game/sv_kill_msg.py
Normal file
44
twnet_parser/messages6/game/sv_kill_msg.py
Normal file
|
@ -0,0 +1,44 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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
|
||||
from typing import Literal
|
||||
|
||||
class MsgSvKillMsg(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
killer: int = 0,
|
||||
victim: int = 0,
|
||||
weapon: int = 0,
|
||||
mode_special: int = 0
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'game'
|
||||
self.message_name: str = 'sv_kill_msg'
|
||||
self.system_message: bool = False
|
||||
self.message_id: int = 4
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.killer: int = killer
|
||||
self.victim: int = victim
|
||||
self.weapon: int = weapon
|
||||
self.mode_special: int = mode_special
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.killer = unpacker.get_int()
|
||||
self.victim = unpacker.get_int()
|
||||
self.weapon = unpacker.get_int()
|
||||
self.mode_special = unpacker.get_int()
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_int(self.killer) + \
|
||||
pack_int(self.victim) + \
|
||||
pack_int(self.weapon) + \
|
||||
pack_int(self.mode_special)
|
32
twnet_parser/messages6/game/sv_motd.py
Normal file
32
twnet_parser/messages6/game/sv_motd.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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_str
|
||||
from typing import Literal
|
||||
|
||||
class MsgSvMotd(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
message: str = 'default'
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'game'
|
||||
self.message_name: str = 'sv_motd'
|
||||
self.system_message: bool = False
|
||||
self.message_id: int = 1
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.message: str = message
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.message = unpacker.get_str()
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_str(self.message)
|
26
twnet_parser/messages6/game/sv_ready_to_enter.py
Normal file
26
twnet_parser/messages6/game/sv_ready_to_enter.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
from twnet_parser.pretty_print import PrettyPrint
|
||||
from twnet_parser.chunk_header import ChunkHeader
|
||||
from typing import Literal
|
||||
|
||||
class MsgSvReadyToEnter(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader()
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'game'
|
||||
self.message_name: str = 'sv_ready_to_enter'
|
||||
self.system_message: bool = False
|
||||
self.message_id: int = 8
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return b''
|
33
twnet_parser/messages6/game/sv_sound_global.py
Normal file
33
twnet_parser/messages6/game/sv_sound_global.py
Normal file
|
@ -0,0 +1,33 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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
|
||||
from typing import Literal
|
||||
import twnet_parser.enum6 as enum6
|
||||
|
||||
class MsgSvSoundGlobal(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
sound_id: int = enum6.Sound.GUN_FIRE.value
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'game'
|
||||
self.message_name: str = 'sv_sound_global'
|
||||
self.system_message: bool = False
|
||||
self.message_id: int = 5
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.sound_id: int = sound_id
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.sound_id = unpacker.get_int() # enum SOUND
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_int(self.sound_id)
|
160
twnet_parser/messages6/game/sv_tune_params.py
Normal file
160
twnet_parser/messages6/game/sv_tune_params.py
Normal file
|
@ -0,0 +1,160 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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
|
||||
from typing import Literal
|
||||
|
||||
class MsgSvTuneParams(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
ground_control_speed: float = 10,
|
||||
ground_control_accel: float = 2,
|
||||
ground_friction: float = 0.5,
|
||||
ground_jump_impulse: float = 13.2,
|
||||
air_jump_impulse: float = 12,
|
||||
air_control_speed: float = 5,
|
||||
air_control_accel: float = 1.5,
|
||||
air_friction: float = 0.95,
|
||||
hook_length: float = 380,
|
||||
hook_fire_speed: float = 80,
|
||||
hook_drag_accel: float = 3,
|
||||
hook_drag_speed: float = 15,
|
||||
gravity: float = 0.5,
|
||||
velramp_start: float = 550,
|
||||
velramp_range: float = 2000,
|
||||
velramp_curvature: float = 1.4,
|
||||
gun_curvature: float = 1.25,
|
||||
gun_speed: float = 2200,
|
||||
gun_lifetime: float = 2,
|
||||
shotgun_curvature: float = 1.25,
|
||||
shotgun_speed: float = 2750,
|
||||
shotgun_speeddiff: float = 0.8,
|
||||
shotgun_lifetime: float = 0.2,
|
||||
grenade_curvature: float = 7,
|
||||
grenade_speed: float = 1000,
|
||||
grenade_lifetime: float = 2,
|
||||
laser_reach: float = 800,
|
||||
laser_bounce_delay: float = 150,
|
||||
laser_bounce_num: float = 1,
|
||||
laser_bounce_cost: float = 0,
|
||||
laser_damage: float = 0.0,
|
||||
player_collision: float = 1,
|
||||
player_hooking: float = 1
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'game'
|
||||
self.message_name: str = 'sv_tune_params'
|
||||
self.system_message: bool = False
|
||||
self.message_id: int = 6
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.ground_control_speed: float = ground_control_speed
|
||||
self.ground_control_accel: float = ground_control_accel
|
||||
self.ground_friction: float = ground_friction
|
||||
self.ground_jump_impulse: float = ground_jump_impulse
|
||||
self.air_jump_impulse: float = air_jump_impulse
|
||||
self.air_control_speed: float = air_control_speed
|
||||
self.air_control_accel: float = air_control_accel
|
||||
self.air_friction: float = air_friction
|
||||
self.hook_length: float = hook_length
|
||||
self.hook_fire_speed: float = hook_fire_speed
|
||||
self.hook_drag_accel: float = hook_drag_accel
|
||||
self.hook_drag_speed: float = hook_drag_speed
|
||||
self.gravity: float = gravity
|
||||
self.velramp_start: float = velramp_start
|
||||
self.velramp_range: float = velramp_range
|
||||
self.velramp_curvature: float = velramp_curvature
|
||||
self.gun_curvature: float = gun_curvature
|
||||
self.gun_speed: float = gun_speed
|
||||
self.gun_lifetime: float = gun_lifetime
|
||||
self.shotgun_curvature: float = shotgun_curvature
|
||||
self.shotgun_speed: float = shotgun_speed
|
||||
self.shotgun_speeddiff: float = shotgun_speeddiff
|
||||
self.shotgun_lifetime: float = shotgun_lifetime
|
||||
self.grenade_curvature: float = grenade_curvature
|
||||
self.grenade_speed: float = grenade_speed
|
||||
self.grenade_lifetime: float = grenade_lifetime
|
||||
self.laser_reach: float = laser_reach
|
||||
self.laser_bounce_delay: float = laser_bounce_delay
|
||||
self.laser_bounce_num: float = laser_bounce_num
|
||||
self.laser_bounce_cost: float = laser_bounce_cost
|
||||
self.laser_damage: float = laser_damage
|
||||
self.player_collision: float = player_collision
|
||||
self.player_hooking: float = player_hooking
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.ground_control_speed = unpacker.get_int() / 100.0
|
||||
self.ground_control_accel = unpacker.get_int() / 100.0
|
||||
self.ground_friction = unpacker.get_int() / 100.0
|
||||
self.ground_jump_impulse = unpacker.get_int() / 100.0
|
||||
self.air_jump_impulse = unpacker.get_int() / 100.0
|
||||
self.air_control_speed = unpacker.get_int() / 100.0
|
||||
self.air_control_accel = unpacker.get_int() / 100.0
|
||||
self.air_friction = unpacker.get_int() / 100.0
|
||||
self.hook_length = unpacker.get_int() / 100.0
|
||||
self.hook_fire_speed = unpacker.get_int() / 100.0
|
||||
self.hook_drag_accel = unpacker.get_int() / 100.0
|
||||
self.hook_drag_speed = unpacker.get_int() / 100.0
|
||||
self.gravity = unpacker.get_int() / 100.0
|
||||
self.velramp_start = unpacker.get_int() / 100.0
|
||||
self.velramp_range = unpacker.get_int() / 100.0
|
||||
self.velramp_curvature = unpacker.get_int() / 100.0
|
||||
self.gun_curvature = unpacker.get_int() / 100.0
|
||||
self.gun_speed = unpacker.get_int() / 100.0
|
||||
self.gun_lifetime = unpacker.get_int() / 100.0
|
||||
self.shotgun_curvature = unpacker.get_int() / 100.0
|
||||
self.shotgun_speed = unpacker.get_int() / 100.0
|
||||
self.shotgun_speeddiff = unpacker.get_int() / 100.0
|
||||
self.shotgun_lifetime = unpacker.get_int() / 100.0
|
||||
self.grenade_curvature = unpacker.get_int() / 100.0
|
||||
self.grenade_speed = unpacker.get_int() / 100.0
|
||||
self.grenade_lifetime = unpacker.get_int() / 100.0
|
||||
self.laser_reach = unpacker.get_int() / 100.0
|
||||
self.laser_bounce_delay = unpacker.get_int() / 100.0
|
||||
self.laser_bounce_num = unpacker.get_int() / 100.0
|
||||
self.laser_bounce_cost = unpacker.get_int() / 100.0
|
||||
self.laser_damage = unpacker.get_int() / 100.0
|
||||
self.player_collision = unpacker.get_int() / 100.0
|
||||
self.player_hooking = unpacker.get_int() / 100.0
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_int(int(self.ground_control_speed * 100.0)) + \
|
||||
pack_int(int(self.ground_control_accel * 100.0)) + \
|
||||
pack_int(int(self.ground_friction * 100.0)) + \
|
||||
pack_int(int(self.ground_jump_impulse * 100.0)) + \
|
||||
pack_int(int(self.air_jump_impulse * 100.0)) + \
|
||||
pack_int(int(self.air_control_speed * 100.0)) + \
|
||||
pack_int(int(self.air_control_accel * 100.0)) + \
|
||||
pack_int(int(self.air_friction * 100.0)) + \
|
||||
pack_int(int(self.hook_length * 100.0)) + \
|
||||
pack_int(int(self.hook_fire_speed * 100.0)) + \
|
||||
pack_int(int(self.hook_drag_accel * 100.0)) + \
|
||||
pack_int(int(self.hook_drag_speed * 100.0)) + \
|
||||
pack_int(int(self.gravity * 100.0)) + \
|
||||
pack_int(int(self.velramp_start * 100.0)) + \
|
||||
pack_int(int(self.velramp_range * 100.0)) + \
|
||||
pack_int(int(self.velramp_curvature * 100.0)) + \
|
||||
pack_int(int(self.gun_curvature * 100.0)) + \
|
||||
pack_int(int(self.gun_speed * 100.0)) + \
|
||||
pack_int(int(self.gun_lifetime * 100.0)) + \
|
||||
pack_int(int(self.shotgun_curvature * 100.0)) + \
|
||||
pack_int(int(self.shotgun_speed * 100.0)) + \
|
||||
pack_int(int(self.shotgun_speeddiff * 100.0)) + \
|
||||
pack_int(int(self.shotgun_lifetime * 100.0)) + \
|
||||
pack_int(int(self.grenade_curvature * 100.0)) + \
|
||||
pack_int(int(self.grenade_speed * 100.0)) + \
|
||||
pack_int(int(self.grenade_lifetime * 100.0)) + \
|
||||
pack_int(int(self.laser_reach * 100.0)) + \
|
||||
pack_int(int(self.laser_bounce_delay * 100.0)) + \
|
||||
pack_int(int(self.laser_bounce_num * 100.0)) + \
|
||||
pack_int(int(self.laser_bounce_cost * 100.0)) + \
|
||||
pack_int(int(self.laser_damage * 100.0)) + \
|
||||
pack_int(int(self.player_collision * 100.0)) + \
|
||||
pack_int(int(self.player_hooking * 100.0))
|
26
twnet_parser/messages6/game/sv_vote_clear_options.py
Normal file
26
twnet_parser/messages6/game/sv_vote_clear_options.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
from twnet_parser.pretty_print import PrettyPrint
|
||||
from twnet_parser.chunk_header import ChunkHeader
|
||||
from typing import Literal
|
||||
|
||||
class MsgSvVoteClearOptions(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader()
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'game'
|
||||
self.message_name: str = 'sv_vote_clear_options'
|
||||
self.system_message: bool = False
|
||||
self.message_id: int = 11
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return b''
|
32
twnet_parser/messages6/game/sv_vote_option_add.py
Normal file
32
twnet_parser/messages6/game/sv_vote_option_add.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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_str
|
||||
from typing import Literal
|
||||
|
||||
class MsgSvVoteOptionAdd(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
description: str = 'default'
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'game'
|
||||
self.message_name: str = 'sv_vote_option_add'
|
||||
self.system_message: bool = False
|
||||
self.message_id: int = 13
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.description: str = description
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.description = unpacker.get_str(SANITIZE_CC)
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_str(self.description)
|
38
twnet_parser/messages6/game/sv_vote_option_list_add.py
Normal file
38
twnet_parser/messages6/game/sv_vote_option_list_add.py
Normal file
|
@ -0,0 +1,38 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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
|
||||
from typing import Annotated, Literal
|
||||
|
||||
class MsgSvVoteOptionListAdd(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
num_options: int = 0,
|
||||
description: Annotated[list[str], 15] = \
|
||||
['', '', '', '', '', '', '', '', '', '', '', '', '', '', '']
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'game'
|
||||
self.message_name: str = 'sv_vote_option_list_add'
|
||||
self.system_message: bool = False
|
||||
self.message_id: int = 12
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.num_options: int = num_options
|
||||
self.description = description
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.num_options = unpacker.get_int()
|
||||
for i in range(0, 15):
|
||||
self.description[i] = unpacker.get_str(SANITIZE_CC)
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_int(self.num_options) + \
|
||||
b''.join([pack_str(x) for x in self.description])
|
32
twnet_parser/messages6/game/sv_vote_option_remove.py
Normal file
32
twnet_parser/messages6/game/sv_vote_option_remove.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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_str
|
||||
from typing import Literal
|
||||
|
||||
class MsgSvVoteOptionRemove(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
description: str = 'default'
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'game'
|
||||
self.message_name: str = 'sv_vote_option_remove'
|
||||
self.system_message: bool = False
|
||||
self.message_id: int = 14
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.description: str = description
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.description = unpacker.get_str(SANITIZE_CC)
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_str(self.description)
|
40
twnet_parser/messages6/game/sv_vote_set.py
Normal file
40
twnet_parser/messages6/game/sv_vote_set.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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
|
||||
from typing import Literal
|
||||
|
||||
class MsgSvVoteSet(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
timeout: int = 0,
|
||||
description: str = 'default',
|
||||
reason: str = 'default'
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'game'
|
||||
self.message_name: str = 'sv_vote_set'
|
||||
self.system_message: bool = False
|
||||
self.message_id: int = 15
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.timeout: int = timeout
|
||||
self.description: str = description
|
||||
self.reason: str = reason
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.timeout = unpacker.get_int()
|
||||
self.description = unpacker.get_str(SANITIZE_CC)
|
||||
self.reason = unpacker.get_str(SANITIZE_CC)
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_int(self.timeout) + \
|
||||
pack_str(self.description) + \
|
||||
pack_str(self.reason)
|
44
twnet_parser/messages6/game/sv_vote_status.py
Normal file
44
twnet_parser/messages6/game/sv_vote_status.py
Normal file
|
@ -0,0 +1,44 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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
|
||||
from typing import Literal
|
||||
|
||||
class MsgSvVoteStatus(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
yes: int = 0,
|
||||
no: int = 0,
|
||||
pass_: int = 0,
|
||||
total: int = 0
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'game'
|
||||
self.message_name: str = 'sv_vote_status'
|
||||
self.system_message: bool = False
|
||||
self.message_id: int = 16
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.yes: int = yes
|
||||
self.no: int = no
|
||||
self.pass_: int = pass_
|
||||
self.total: int = total
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.yes = unpacker.get_int()
|
||||
self.no = unpacker.get_int()
|
||||
self.pass_ = unpacker.get_int()
|
||||
self.total = unpacker.get_int()
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_int(self.yes) + \
|
||||
pack_int(self.no) + \
|
||||
pack_int(self.pass_) + \
|
||||
pack_int(self.total)
|
33
twnet_parser/messages6/game/sv_weapon_pickup.py
Normal file
33
twnet_parser/messages6/game/sv_weapon_pickup.py
Normal file
|
@ -0,0 +1,33 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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
|
||||
from typing import Literal
|
||||
import twnet_parser.enum6 as enum6
|
||||
|
||||
class MsgSvWeaponPickup(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
weapon: int = enum6.Weapon.HAMMER.value
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'game'
|
||||
self.message_name: str = 'sv_weapon_pickup'
|
||||
self.system_message: bool = False
|
||||
self.message_id: int = 9
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.weapon: int = weapon
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.weapon = unpacker.get_int() # enum WEAPON
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_int(self.weapon)
|
26
twnet_parser/messages6/system/con_ready.py
Normal file
26
twnet_parser/messages6/system/con_ready.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
from twnet_parser.pretty_print import PrettyPrint
|
||||
from twnet_parser.chunk_header import ChunkHeader
|
||||
from typing import Literal
|
||||
|
||||
class MsgConReady(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader()
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'system'
|
||||
self.message_name: str = 'con_ready'
|
||||
self.system_message: bool = True
|
||||
self.message_id: int = 4
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return b''
|
26
twnet_parser/messages6/system/enter_game.py
Normal file
26
twnet_parser/messages6/system/enter_game.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
from twnet_parser.pretty_print import PrettyPrint
|
||||
from twnet_parser.chunk_header import ChunkHeader
|
||||
from typing import Literal
|
||||
|
||||
class MsgEnterGame(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader()
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'system'
|
||||
self.message_name: str = 'enter_game'
|
||||
self.system_message: bool = True
|
||||
self.message_id: int = 15
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return b''
|
36
twnet_parser/messages6/system/info.py
Normal file
36
twnet_parser/messages6/system/info.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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_str
|
||||
from typing import Literal
|
||||
|
||||
class MsgInfo(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
version: str = '0.7 802f1be60a05665f',
|
||||
password: str = ''
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'system'
|
||||
self.message_name: str = 'info'
|
||||
self.system_message: bool = True
|
||||
self.message_id: int = 1
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.version: str = version
|
||||
self.password: str = password
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.version = unpacker.get_str()
|
||||
self.password = unpacker.get_str() # TODO: optionals
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_str(self.version) + \
|
||||
pack_str(self.password)
|
44
twnet_parser/messages6/system/input.py
Normal file
44
twnet_parser/messages6/system/input.py
Normal file
|
@ -0,0 +1,44 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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
|
||||
from typing import Literal
|
||||
|
||||
class MsgInput(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
ack_snapshot: int = 0,
|
||||
intended_tick: int = 0,
|
||||
input_size: int = 0,
|
||||
input: int = 0
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'system'
|
||||
self.message_name: str = 'input'
|
||||
self.system_message: bool = True
|
||||
self.message_id: int = 16
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.ack_snapshot: int = ack_snapshot
|
||||
self.intended_tick: int = intended_tick
|
||||
self.input_size: int = input_size
|
||||
self.input: int = input
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.ack_snapshot = unpacker.get_int()
|
||||
self.intended_tick = unpacker.get_int()
|
||||
self.input_size = unpacker.get_int()
|
||||
self.input = unpacker.get_int() # TODO: this is a snapshot object
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_int(self.ack_snapshot) + \
|
||||
pack_int(self.intended_tick) + \
|
||||
pack_int(self.input_size) + \
|
||||
pack_int(self.input)
|
36
twnet_parser/messages6/system/input_timing.py
Normal file
36
twnet_parser/messages6/system/input_timing.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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
|
||||
from typing import Literal
|
||||
|
||||
class MsgInputTiming(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
input_pred_tick: int = 0,
|
||||
time_left: int = 0
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'system'
|
||||
self.message_name: str = 'input_timing'
|
||||
self.system_message: bool = True
|
||||
self.message_id: int = 9
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.input_pred_tick: int = input_pred_tick
|
||||
self.time_left: int = time_left
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.input_pred_tick = unpacker.get_int()
|
||||
self.time_left = unpacker.get_int()
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_int(self.input_pred_tick) + \
|
||||
pack_int(self.time_left)
|
40
twnet_parser/messages6/system/map_change.py
Normal file
40
twnet_parser/messages6/system/map_change.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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, pack_str
|
||||
from typing import Literal
|
||||
|
||||
class MsgMapChange(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
name: str = 'default',
|
||||
crc: int = 0,
|
||||
size: int = 0
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'system'
|
||||
self.message_name: str = 'map_change'
|
||||
self.system_message: bool = True
|
||||
self.message_id: int = 2
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.name: str = name
|
||||
self.crc: int = crc
|
||||
self.size: int = size
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.name = unpacker.get_str()
|
||||
self.crc = unpacker.get_int()
|
||||
self.size = unpacker.get_int()
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_str(self.name) + \
|
||||
pack_int(self.crc) + \
|
||||
pack_int(self.size)
|
48
twnet_parser/messages6/system/map_data.py
Normal file
48
twnet_parser/messages6/system/map_data.py
Normal file
|
@ -0,0 +1,48 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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
|
||||
from typing import Literal, Optional
|
||||
|
||||
class MsgMapData(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
last: int = 0,
|
||||
crc: int = 0,
|
||||
chunk: int = 0,
|
||||
data_size: Optional[int] = None,
|
||||
data: bytes = b'\x00'
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'system'
|
||||
self.message_name: str = 'map_data'
|
||||
self.system_message: bool = True
|
||||
self.message_id: int = 3
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.last: int = last
|
||||
self.crc: int = crc
|
||||
self.chunk: int = chunk
|
||||
self.data_size: int = data_size if data_size else len(data)
|
||||
self.data: bytes = data
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.last = unpacker.get_int()
|
||||
self.crc = unpacker.get_int()
|
||||
self.chunk = unpacker.get_int()
|
||||
self.data_size = unpacker.get_int()
|
||||
self.data = unpacker.get_raw(self.data_size)
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_int(self.last) + \
|
||||
pack_int(self.crc) + \
|
||||
pack_int(self.chunk) + \
|
||||
pack_int(self.data_size) + \
|
||||
self.data
|
26
twnet_parser/messages6/system/ping.py
Normal file
26
twnet_parser/messages6/system/ping.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
from twnet_parser.pretty_print import PrettyPrint
|
||||
from twnet_parser.chunk_header import ChunkHeader
|
||||
from typing import Literal
|
||||
|
||||
class MsgPing(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader()
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'system'
|
||||
self.message_name: str = 'ping'
|
||||
self.system_message: bool = True
|
||||
self.message_id: int = 20
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return b''
|
26
twnet_parser/messages6/system/ping_reply.py
Normal file
26
twnet_parser/messages6/system/ping_reply.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
from twnet_parser.pretty_print import PrettyPrint
|
||||
from twnet_parser.chunk_header import ChunkHeader
|
||||
from typing import Literal
|
||||
|
||||
class MsgPingReply(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader()
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'system'
|
||||
self.message_name: str = 'ping_reply'
|
||||
self.system_message: bool = True
|
||||
self.message_id: int = 21
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return b''
|
40
twnet_parser/messages6/system/rcon_auth.py
Normal file
40
twnet_parser/messages6/system/rcon_auth.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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, pack_str
|
||||
from typing import Literal
|
||||
|
||||
class MsgRconAuth(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
_unused: str = 'default',
|
||||
password: str = 'default',
|
||||
request_commands: int = 0
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'system'
|
||||
self.message_name: str = 'rcon_auth'
|
||||
self.system_message: bool = True
|
||||
self.message_id: int = 18
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self._unused: str = _unused
|
||||
self.password: str = password
|
||||
self.request_commands: int = request_commands
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self._unused = unpacker.get_str()
|
||||
self.password = unpacker.get_str()
|
||||
self.request_commands = unpacker.get_int() # TODO: optionals
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_str(self._unused) + \
|
||||
pack_str(self.password) + \
|
||||
pack_int(self.request_commands)
|
36
twnet_parser/messages6/system/rcon_auth_status.py
Normal file
36
twnet_parser/messages6/system/rcon_auth_status.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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
|
||||
from typing import Literal
|
||||
|
||||
class MsgRconAuthStatus(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
auth_level: int = 0,
|
||||
receive_commands: int = 0
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'system'
|
||||
self.message_name: str = 'rcon_auth_status'
|
||||
self.system_message: bool = True
|
||||
self.message_id: int = 10
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.auth_level: int = auth_level
|
||||
self.receive_commands: int = receive_commands
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.auth_level = unpacker.get_int() # TODO: optionals
|
||||
self.receive_commands = unpacker.get_int() # TODO: optionals
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_int(self.auth_level) + \
|
||||
pack_int(self.receive_commands)
|
32
twnet_parser/messages6/system/rcon_cmd.py
Normal file
32
twnet_parser/messages6/system/rcon_cmd.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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_str
|
||||
from typing import Literal
|
||||
|
||||
class MsgRconCmd(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
cmd: str = 'default'
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'system'
|
||||
self.message_name: str = 'rcon_cmd'
|
||||
self.system_message: bool = True
|
||||
self.message_id: int = 17
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.cmd: str = cmd
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.cmd = unpacker.get_str()
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_str(self.cmd)
|
40
twnet_parser/messages6/system/rcon_cmd_add.py
Normal file
40
twnet_parser/messages6/system/rcon_cmd_add.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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_str
|
||||
from typing import Literal
|
||||
|
||||
class MsgRconCmdAdd(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
name: str = 'default',
|
||||
help: str = 'default',
|
||||
params: str = 'default'
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'system'
|
||||
self.message_name: str = 'rcon_cmd_add'
|
||||
self.system_message: bool = True
|
||||
self.message_id: int = 25
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.name: str = name
|
||||
self.help: str = help
|
||||
self.params: str = params
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.name = unpacker.get_str()
|
||||
self.help = unpacker.get_str()
|
||||
self.params = unpacker.get_str()
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_str(self.name) + \
|
||||
pack_str(self.help) + \
|
||||
pack_str(self.params)
|
32
twnet_parser/messages6/system/rcon_cmd_remove.py
Normal file
32
twnet_parser/messages6/system/rcon_cmd_remove.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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_str
|
||||
from typing import Literal
|
||||
|
||||
class MsgRconCmdRemove(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
name: str = 'default'
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'system'
|
||||
self.message_name: str = 'rcon_cmd_remove'
|
||||
self.system_message: bool = True
|
||||
self.message_id: int = 26
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.name: str = name
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.name = unpacker.get_str()
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_str(self.name)
|
32
twnet_parser/messages6/system/rcon_line.py
Normal file
32
twnet_parser/messages6/system/rcon_line.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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_str
|
||||
from typing import Literal
|
||||
|
||||
class MsgRconLine(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
line: str = 'default'
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'system'
|
||||
self.message_name: str = 'rcon_line'
|
||||
self.system_message: bool = True
|
||||
self.message_id: int = 11
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.line: str = line
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.line = unpacker.get_str()
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_str(self.line)
|
26
twnet_parser/messages6/system/ready.py
Normal file
26
twnet_parser/messages6/system/ready.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
from twnet_parser.pretty_print import PrettyPrint
|
||||
from twnet_parser.chunk_header import ChunkHeader
|
||||
from typing import Literal
|
||||
|
||||
class MsgReady(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader()
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'system'
|
||||
self.message_name: str = 'ready'
|
||||
self.system_message: bool = True
|
||||
self.message_id: int = 14
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return b''
|
32
twnet_parser/messages6/system/request_map_data.py
Normal file
32
twnet_parser/messages6/system/request_map_data.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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
|
||||
from typing import Literal
|
||||
|
||||
class MsgRequestMapData(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
chunk: int = 0
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'system'
|
||||
self.message_name: str = 'request_map_data'
|
||||
self.system_message: bool = True
|
||||
self.message_id: int = 19
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.chunk: int = chunk
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.chunk = unpacker.get_int()
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_int(self.chunk)
|
58
twnet_parser/messages6/system/snap.py
Normal file
58
twnet_parser/messages6/system/snap.py
Normal file
|
@ -0,0 +1,58 @@
|
|||
from typing import Literal, Optional
|
||||
|
||||
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
|
||||
from twnet_parser.snapshot7 import Snapshot
|
||||
|
||||
class MsgSnap(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
tick: int = 0,
|
||||
delta_tick: int = 0,
|
||||
num_parts: int = 0,
|
||||
part: int = 0,
|
||||
crc: int = 0,
|
||||
data_size: Optional[int] = None,
|
||||
data: bytes = b'\x00'
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'system'
|
||||
self.message_name: str = 'snap'
|
||||
self.system_message: bool = True
|
||||
self.message_id: int = 5
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.tick: int = tick
|
||||
self.delta_tick: int = delta_tick
|
||||
self.num_parts: int = num_parts
|
||||
self.part: int = part
|
||||
self.crc: int = crc
|
||||
self.data_size: int = data_size if data_size else len(data)
|
||||
self.data: bytes = data
|
||||
self.snapshot = Snapshot()
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.tick = unpacker.get_int()
|
||||
self.delta_tick = unpacker.get_int()
|
||||
self.num_parts = unpacker.get_int()
|
||||
self.part = unpacker.get_int()
|
||||
self.crc = unpacker.get_int()
|
||||
self.data_size = unpacker.get_int()
|
||||
self.data = unpacker.get_raw(self.data_size)
|
||||
self.snapshot.unpack(self.data)
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_int(self.tick) + \
|
||||
pack_int(self.delta_tick) + \
|
||||
pack_int(self.num_parts) + \
|
||||
pack_int(self.part) + \
|
||||
pack_int(self.crc) + \
|
||||
pack_int(self.data_size) + \
|
||||
self.snapshot.pack()
|
36
twnet_parser/messages6/system/snap_empty.py
Normal file
36
twnet_parser/messages6/system/snap_empty.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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
|
||||
from typing import Literal
|
||||
|
||||
class MsgSnapEmpty(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
tick: int = 0,
|
||||
delta_tick: int = 0
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'system'
|
||||
self.message_name: str = 'snap_empty'
|
||||
self.system_message: bool = True
|
||||
self.message_id: int = 6
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.tick: int = tick
|
||||
self.delta_tick: int = delta_tick
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.tick = unpacker.get_int()
|
||||
self.delta_tick = unpacker.get_int()
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_int(self.tick) + \
|
||||
pack_int(self.delta_tick)
|
48
twnet_parser/messages6/system/snap_single.py
Normal file
48
twnet_parser/messages6/system/snap_single.py
Normal file
|
@ -0,0 +1,48 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
|
||||
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
|
||||
from typing import Literal, Optional
|
||||
|
||||
class MsgSnapSingle(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
chunk_header: ChunkHeader = ChunkHeader(),
|
||||
tick: int = 0,
|
||||
delta_tick: int = 0,
|
||||
crc: int = 0,
|
||||
data_size: Optional[int] = None,
|
||||
data: bytes = b'\x00'
|
||||
) -> None:
|
||||
self.message_type: Literal['system', 'game'] = 'system'
|
||||
self.message_name: str = 'snap_single'
|
||||
self.system_message: bool = True
|
||||
self.message_id: int = 7
|
||||
self.header: ChunkHeader = chunk_header
|
||||
|
||||
self.tick: int = tick
|
||||
self.delta_tick: int = delta_tick
|
||||
self.crc: int = crc
|
||||
self.data_size: int = data_size if data_size else len(data)
|
||||
self.data: bytes = data
|
||||
|
||||
# first byte of data
|
||||
# has to be the first byte of the message payload
|
||||
# NOT the chunk header and NOT the message id
|
||||
def unpack(self, data: bytes) -> bool:
|
||||
unpacker = Unpacker(data)
|
||||
self.tick = unpacker.get_int()
|
||||
self.delta_tick = unpacker.get_int()
|
||||
self.crc = unpacker.get_int()
|
||||
self.data_size = unpacker.get_int()
|
||||
self.data = unpacker.get_raw(self.data_size)
|
||||
return True
|
||||
|
||||
def pack(self) -> bytes:
|
||||
return pack_int(self.tick) + \
|
||||
pack_int(self.delta_tick) + \
|
||||
pack_int(self.crc) + \
|
||||
pack_int(self.data_size) + \
|
||||
self.data
|
80
twnet_parser/msg6.py
Normal file
80
twnet_parser/msg6.py
Normal file
|
@ -0,0 +1,80 @@
|
|||
# connless
|
||||
# pylint: disable=duplicate-code
|
||||
|
||||
CONNLESS_HEARTBEAT = b'\xff\xff\xff\xffbea2'
|
||||
CONNLESS_REQUEST_LIST = b'\xff\xff\xff\xffreq2'
|
||||
CONNLESS_LIST = b'\xff\xff\xff\xfflis2'
|
||||
CONNLESS_REQUEST_COUNT = b'\xff\xff\xff\xffcou2'
|
||||
CONNLESS_COUNT = b'\xff\xff\xff\xffsiz2'
|
||||
CONNLESS_REQUEST_INFO = b'\xff\xff\xff\xffgie3'
|
||||
CONNLESS_INFO = b'\xff\xff\xff\xffinf3'
|
||||
CONNLESS_FORWARD_CHECK = b'\xff\xff\xff\xfffw??'
|
||||
CONNLESS_FORWARD_RESPONSE = b'\xff\xff\xff\xfffw!!'
|
||||
CONNLESS_FORWARD_OK = b'\xff\xff\xff\xfffwok'
|
||||
CONNLESS_FORWARD_ERROR = b'\xff\xff\xff\xfffwer'
|
||||
|
||||
# control
|
||||
|
||||
CTRL_KEEPALIVE = 0
|
||||
CTRL_CONNECT = 1
|
||||
CTRL_CONNECT_ACCEPT = 2
|
||||
CTRL_ACCEPT = 2 # got remove in 0.6.5
|
||||
CTRL_CLOSE = 4
|
||||
|
||||
# system
|
||||
INFO = 1
|
||||
MAP_CHANGE = 2 # sent when client should switch map
|
||||
MAP_DATA = 3 # map transfer, contains a chunk of the map file
|
||||
CON_READY = 4 # connection is ready, client should send start info
|
||||
SNAP = 5 # normal snapshot, multiple parts
|
||||
SNAP_EMPTY = 6 # empty snapshot
|
||||
SNAP_SINGLE = 7
|
||||
SNAP_SMALL = 8
|
||||
INPUT_TIMING = 9 # reports how off the input was
|
||||
RCON_AUTH_STATUS = 10# result of the authentication
|
||||
RCON_LINE = 11 # line that should be printed to the remote console
|
||||
AUTH_CHALLANGE = 12
|
||||
AUTH_RESULT = 13
|
||||
READY = 14
|
||||
ENTER_GAME = 15
|
||||
INPUT = 16 # contains the inputdata from the client
|
||||
RCON_CMD = 17
|
||||
RCON_AUTH = 18
|
||||
REQUEST_MAP_DATA = 19
|
||||
AUTH_START = 20
|
||||
AUTH_RESPONSE = 21
|
||||
PING = 22
|
||||
PING_REPLY = 23
|
||||
ERROR = 24
|
||||
RCON_CMD_ADD = 25
|
||||
RCON_CMD_REMOVE = 26
|
||||
|
||||
# game
|
||||
INVALID = 0
|
||||
SV_MOTD = 1
|
||||
SV_BROADCAST = 2
|
||||
SV_CHAT = 3
|
||||
SV_KILL_MSG = 4
|
||||
SV_SOUND_GLOBAL = 5
|
||||
SV_TUNE_PARAMS = 6
|
||||
SV_EXTRA_PROJECTILE = 7
|
||||
SV_READY_TO_ENTER = 8
|
||||
SV_WEAPON_PICKUP = 9
|
||||
SV_EMOTICON = 10
|
||||
SV_VOTE_CLEAR_OPTIONS = 11
|
||||
SV_VOTE_OPTION_LIST_ADD = 12
|
||||
SV_VOTE_OPTION_ADD = 13
|
||||
SV_VOTE_OPTION_REMOVE = 14
|
||||
SV_VOTE_SET = 15
|
||||
SV_VOTE_STATUS = 16
|
||||
CL_SAY = 17
|
||||
CL_SET_TEAM = 18
|
||||
CL_SET_SPECTATOR_MODE = 19
|
||||
CL_START_INFO = 20
|
||||
CL_CHANGE_INFO = 21
|
||||
CL_KILL = 22
|
||||
CL_EMOTICON = 23
|
||||
CL_VOTE = 24
|
||||
CL_CALL_VOTE = 25
|
||||
NUM_GAME_MESSAGES = 26
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
# connless
|
||||
# pylint: disable=duplicate-code
|
||||
|
||||
CONNLESS_HEARTBEAT = b'\xff\xff\xff\xffbea2'
|
||||
CONNLESS_REQUEST_LIST = b'\xff\xff\xff\xffreq2'
|
||||
|
|
62
twnet_parser/msg_matcher/connless6.py
Normal file
62
twnet_parser/msg_matcher/connless6.py
Normal file
|
@ -0,0 +1,62 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
from typing import Optional
|
||||
|
||||
import twnet_parser.msg6
|
||||
from twnet_parser.connless_message import ConnlessMessage
|
||||
|
||||
import twnet_parser.messages6.connless.request_list as \
|
||||
connless_request_list
|
||||
import twnet_parser.messages6.connless.list as \
|
||||
connless_list
|
||||
import twnet_parser.messages6.connless.request_count as \
|
||||
connless_request_count
|
||||
import twnet_parser.messages6.connless.count as \
|
||||
connless_count
|
||||
import twnet_parser.messages6.connless.request_info as \
|
||||
connless_request_info
|
||||
import twnet_parser.messages6.connless.info as \
|
||||
connless_info
|
||||
import twnet_parser.messages6.connless.heartbeat as \
|
||||
connless_heartbeat
|
||||
import twnet_parser.messages6.connless.forward_check as \
|
||||
connless_forward_check
|
||||
import twnet_parser.messages6.connless.forward_response as \
|
||||
connless_forward_response
|
||||
import twnet_parser.messages6.connless.forward_ok as \
|
||||
connless_forward_ok
|
||||
import twnet_parser.messages6.connless.forward_error as \
|
||||
connless_forward_error
|
||||
|
||||
def match_connless6(msg_id: bytes, data: bytes) -> ConnlessMessage:
|
||||
msg: Optional[ConnlessMessage] = None
|
||||
|
||||
if msg_id == twnet_parser.msg6.CONNLESS_REQUEST_LIST:
|
||||
msg = connless_request_list.MsgRequestList()
|
||||
elif msg_id == twnet_parser.msg6.CONNLESS_LIST:
|
||||
msg = connless_list.MsgList()
|
||||
elif msg_id == twnet_parser.msg6.CONNLESS_REQUEST_COUNT:
|
||||
msg = connless_request_count.MsgRequestCount()
|
||||
elif msg_id == twnet_parser.msg6.CONNLESS_COUNT:
|
||||
msg = connless_count.MsgCount()
|
||||
elif msg_id == twnet_parser.msg6.CONNLESS_REQUEST_INFO:
|
||||
msg = connless_request_info.MsgRequestInfo()
|
||||
elif msg_id == twnet_parser.msg6.CONNLESS_INFO:
|
||||
msg = connless_info.MsgInfo()
|
||||
elif msg_id == twnet_parser.msg6.CONNLESS_HEARTBEAT:
|
||||
msg = connless_heartbeat.MsgHeartbeat()
|
||||
elif msg_id == twnet_parser.msg6.CONNLESS_FORWARD_CHECK:
|
||||
msg = connless_forward_check.MsgForwardCheck()
|
||||
elif msg_id == twnet_parser.msg6.CONNLESS_FORWARD_RESPONSE:
|
||||
msg = connless_forward_response.MsgForwardResponse()
|
||||
elif msg_id == twnet_parser.msg6.CONNLESS_FORWARD_OK:
|
||||
msg = connless_forward_ok.MsgForwardOk()
|
||||
elif msg_id == twnet_parser.msg6.CONNLESS_FORWARD_ERROR:
|
||||
msg = connless_forward_error.MsgForwardError()
|
||||
|
||||
if msg is None:
|
||||
raise ValueError(
|
||||
f"Error: unknown conless message id={msg_id!r} data={data[0]}"
|
||||
)
|
||||
|
||||
msg.unpack(data)
|
||||
return msg
|
30
twnet_parser/msg_matcher/control6.py
Normal file
30
twnet_parser/msg_matcher/control6.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
from typing import Optional
|
||||
|
||||
import twnet_parser.msg6
|
||||
from twnet_parser.ctrl_message import CtrlMessage
|
||||
|
||||
import twnet_parser.messages6.control.keep_alive as keep_alive6
|
||||
import twnet_parser.messages6.control.connect as connect6
|
||||
import twnet_parser.messages6.control.connect_accept as connect_accept6
|
||||
import twnet_parser.messages6.control.accept as accept6
|
||||
import twnet_parser.messages6.control.close as close6
|
||||
|
||||
def match_control6(msg_id: int, data: bytes, client: bool) -> CtrlMessage:
|
||||
msg: Optional[CtrlMessage] = None
|
||||
|
||||
if msg_id == twnet_parser.msg6.CTRL_KEEPALIVE:
|
||||
msg = keep_alive6.CtrlKeepAlive()
|
||||
elif msg_id == twnet_parser.msg6.CTRL_CONNECT:
|
||||
msg = connect6.CtrlConnect()
|
||||
elif msg_id == twnet_parser.msg6.CTRL_CONNECT_ACCEPT:
|
||||
msg = connect_accept6.CtrlConnectAccept()
|
||||
elif msg_id == twnet_parser.msg6.CTRL_ACCEPT:
|
||||
msg = accept6.CtrlAccept()
|
||||
elif msg_id == twnet_parser.msg6.CTRL_CLOSE:
|
||||
msg = close6.CtrlClose()
|
||||
|
||||
if msg is None:
|
||||
raise ValueError(f"Error: unknown control message id={msg_id} data={data[0]}")
|
||||
|
||||
msg.unpack(data, client)
|
||||
return msg
|
116
twnet_parser/msg_matcher/game6.py
Normal file
116
twnet_parser/msg_matcher/game6.py
Normal file
|
@ -0,0 +1,116 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
from typing import Optional
|
||||
|
||||
import twnet_parser.msg6
|
||||
from twnet_parser.net_message import NetMessage
|
||||
|
||||
import twnet_parser.messages6.game.sv_motd as \
|
||||
game6_sv_motd
|
||||
import twnet_parser.messages6.game.sv_broadcast as \
|
||||
game6_sv_broadcast
|
||||
import twnet_parser.messages6.game.sv_chat as \
|
||||
game6_sv_chat
|
||||
import twnet_parser.messages6.game.sv_kill_msg as \
|
||||
game6_sv_kill_msg
|
||||
import twnet_parser.messages6.game.sv_sound_global as \
|
||||
game6_sv_sound_global
|
||||
import twnet_parser.messages6.game.sv_tune_params as \
|
||||
game6_sv_tune_params
|
||||
import twnet_parser.messages6.game.sv_extra_projectile as \
|
||||
game6_sv_extra_projectile
|
||||
import twnet_parser.messages6.game.sv_ready_to_enter as \
|
||||
game6_sv_ready_to_enter
|
||||
import twnet_parser.messages6.game.sv_weapon_pickup as \
|
||||
game6_sv_weapon_pickup
|
||||
import twnet_parser.messages6.game.sv_emoticon as \
|
||||
game6_sv_emoticon
|
||||
import twnet_parser.messages6.game.sv_vote_clear_options as \
|
||||
game6_sv_vote_clear_options
|
||||
import twnet_parser.messages6.game.sv_vote_option_list_add as \
|
||||
game6_sv_vote_option_list_add
|
||||
import twnet_parser.messages6.game.sv_vote_option_add as \
|
||||
game6_sv_vote_option_add
|
||||
import twnet_parser.messages6.game.sv_vote_option_remove as \
|
||||
game6_sv_vote_option_remove
|
||||
import twnet_parser.messages6.game.sv_vote_set as \
|
||||
game6_sv_vote_set
|
||||
import twnet_parser.messages6.game.sv_vote_status as \
|
||||
game6_sv_vote_status
|
||||
import twnet_parser.messages6.game.cl_say as \
|
||||
game6_cl_say
|
||||
import twnet_parser.messages6.game.cl_set_team as \
|
||||
game6_cl_set_team
|
||||
import twnet_parser.messages6.game.cl_set_spectator_mode as \
|
||||
game6_cl_set_spectator_mode
|
||||
import twnet_parser.messages6.game.cl_start_info as \
|
||||
game6_cl_start_info
|
||||
import twnet_parser.messages6.game.cl_change_info as \
|
||||
game6_cl_change_info
|
||||
import twnet_parser.messages6.game.cl_kill as \
|
||||
game6_cl_kill
|
||||
import twnet_parser.messages6.game.cl_emoticon as \
|
||||
game6_cl_emoticon
|
||||
import twnet_parser.messages6.game.cl_vote as \
|
||||
game6_cl_vote
|
||||
import twnet_parser.messages6.game.cl_call_vote as \
|
||||
game6_cl_call_vote
|
||||
|
||||
def match_game6(msg_id: int, data: bytes) -> NetMessage:
|
||||
msg: Optional[NetMessage] = None
|
||||
|
||||
if msg_id == twnet_parser.msg6.SV_MOTD:
|
||||
msg = game6_sv_motd.MsgSvMotd()
|
||||
elif msg_id == twnet_parser.msg6.SV_BROADCAST:
|
||||
msg = game6_sv_broadcast.MsgSvBroadcast()
|
||||
elif msg_id == twnet_parser.msg6.SV_CHAT:
|
||||
msg = game6_sv_chat.MsgSvChat()
|
||||
elif msg_id == twnet_parser.msg6.SV_KILL_MSG:
|
||||
msg = game6_sv_kill_msg.MsgSvKillMsg()
|
||||
elif msg_id == twnet_parser.msg6.SV_SOUND_GLOBAL:
|
||||
msg = game6_sv_sound_global.MsgSvSoundGlobal()
|
||||
elif msg_id == twnet_parser.msg6.SV_TUNE_PARAMS:
|
||||
msg = game6_sv_tune_params.MsgSvTuneParams()
|
||||
elif msg_id == twnet_parser.msg6.SV_EXTRA_PROJECTILE:
|
||||
msg = game6_sv_extra_projectile.MsgSvExtraProjectile()
|
||||
elif msg_id == twnet_parser.msg6.SV_READY_TO_ENTER:
|
||||
msg = game6_sv_ready_to_enter.MsgSvReadyToEnter()
|
||||
elif msg_id == twnet_parser.msg6.SV_WEAPON_PICKUP:
|
||||
msg = game6_sv_weapon_pickup.MsgSvWeaponPickup()
|
||||
elif msg_id == twnet_parser.msg6.SV_EMOTICON:
|
||||
msg = game6_sv_emoticon.MsgSvEmoticon()
|
||||
elif msg_id == twnet_parser.msg6.SV_VOTE_CLEAR_OPTIONS:
|
||||
msg = game6_sv_vote_clear_options.MsgSvVoteClearOptions()
|
||||
elif msg_id == twnet_parser.msg6.SV_VOTE_OPTION_LIST_ADD:
|
||||
msg = game6_sv_vote_option_list_add.MsgSvVoteOptionListAdd()
|
||||
elif msg_id == twnet_parser.msg6.SV_VOTE_OPTION_ADD:
|
||||
msg = game6_sv_vote_option_add.MsgSvVoteOptionAdd()
|
||||
elif msg_id == twnet_parser.msg6.SV_VOTE_OPTION_REMOVE:
|
||||
msg = game6_sv_vote_option_remove.MsgSvVoteOptionRemove()
|
||||
elif msg_id == twnet_parser.msg6.SV_VOTE_SET:
|
||||
msg = game6_sv_vote_set.MsgSvVoteSet()
|
||||
elif msg_id == twnet_parser.msg6.SV_VOTE_STATUS:
|
||||
msg = game6_sv_vote_status.MsgSvVoteStatus()
|
||||
elif msg_id == twnet_parser.msg6.CL_SAY:
|
||||
msg = game6_cl_say.MsgClSay()
|
||||
elif msg_id == twnet_parser.msg6.CL_SET_TEAM:
|
||||
msg = game6_cl_set_team.MsgClSetTeam()
|
||||
elif msg_id == twnet_parser.msg6.CL_SET_SPECTATOR_MODE:
|
||||
msg = game6_cl_set_spectator_mode.MsgClSetSpectatorMode()
|
||||
elif msg_id == twnet_parser.msg6.CL_START_INFO:
|
||||
msg = game6_cl_start_info.MsgClStartInfo()
|
||||
elif msg_id == twnet_parser.msg6.CL_CHANGE_INFO:
|
||||
msg = game6_cl_change_info.MsgClChangeInfo()
|
||||
elif msg_id == twnet_parser.msg6.CL_KILL:
|
||||
msg = game6_cl_kill.MsgClKill()
|
||||
elif msg_id == twnet_parser.msg6.CL_EMOTICON:
|
||||
msg = game6_cl_emoticon.MsgClEmoticon()
|
||||
elif msg_id == twnet_parser.msg6.CL_VOTE:
|
||||
msg = game6_cl_vote.MsgClVote()
|
||||
elif msg_id == twnet_parser.msg6.CL_CALL_VOTE:
|
||||
msg = game6_cl_call_vote.MsgClCallVote()
|
||||
|
||||
if msg is None:
|
||||
raise ValueError(f"Error: unknown game message id={msg_id} data={data[0]}")
|
||||
|
||||
msg.unpack(data)
|
||||
return msg
|
96
twnet_parser/msg_matcher/system6.py
Normal file
96
twnet_parser/msg_matcher/system6.py
Normal file
|
@ -0,0 +1,96 @@
|
|||
# generated by scripts/generate_messages.py
|
||||
from typing import Optional
|
||||
|
||||
import twnet_parser.msg6
|
||||
from twnet_parser.net_message import NetMessage
|
||||
|
||||
import twnet_parser.messages6.system.info as \
|
||||
system6_info
|
||||
import twnet_parser.messages6.system.map_change as \
|
||||
system6_map_change
|
||||
import twnet_parser.messages6.system.map_data as \
|
||||
system6_map_data
|
||||
import twnet_parser.messages6.system.con_ready as \
|
||||
system6_con_ready
|
||||
import twnet_parser.messages6.system.snap as \
|
||||
system6_snap
|
||||
import twnet_parser.messages6.system.snap_empty as \
|
||||
system6_snap_empty
|
||||
import twnet_parser.messages6.system.snap_single as \
|
||||
system6_snap_single
|
||||
import twnet_parser.messages6.system.input_timing as \
|
||||
system6_input_timing
|
||||
import twnet_parser.messages6.system.rcon_auth_status as \
|
||||
system6_rcon_auth_status
|
||||
import twnet_parser.messages6.system.rcon_line as \
|
||||
system6_rcon_line
|
||||
import twnet_parser.messages6.system.ready as \
|
||||
system6_ready
|
||||
import twnet_parser.messages6.system.enter_game as \
|
||||
system6_enter_game
|
||||
import twnet_parser.messages6.system.input as \
|
||||
system6_input
|
||||
import twnet_parser.messages6.system.rcon_cmd as \
|
||||
system6_rcon_cmd
|
||||
import twnet_parser.messages6.system.rcon_auth as \
|
||||
system6_rcon_auth
|
||||
import twnet_parser.messages6.system.request_map_data as \
|
||||
system6_request_map_data
|
||||
import twnet_parser.messages6.system.ping as \
|
||||
system6_ping
|
||||
import twnet_parser.messages6.system.ping_reply as \
|
||||
system6_ping_reply
|
||||
import twnet_parser.messages6.system.rcon_cmd_add as \
|
||||
system6_rcon_cmd_add
|
||||
import twnet_parser.messages6.system.rcon_cmd_remove as \
|
||||
system6_rcon_cmd_remove
|
||||
|
||||
def match_system6(msg_id: int, data: bytes) -> NetMessage:
|
||||
msg: Optional[NetMessage] = None
|
||||
|
||||
if msg_id == twnet_parser.msg6.INFO:
|
||||
msg = system6_info.MsgInfo()
|
||||
elif msg_id == twnet_parser.msg6.MAP_CHANGE:
|
||||
msg = system6_map_change.MsgMapChange()
|
||||
elif msg_id == twnet_parser.msg6.MAP_DATA:
|
||||
msg = system6_map_data.MsgMapData()
|
||||
elif msg_id == twnet_parser.msg6.CON_READY:
|
||||
msg = system6_con_ready.MsgConReady()
|
||||
elif msg_id == twnet_parser.msg6.SNAP:
|
||||
msg = system6_snap.MsgSnap()
|
||||
elif msg_id == twnet_parser.msg6.SNAP_EMPTY:
|
||||
msg = system6_snap_empty.MsgSnapEmpty()
|
||||
elif msg_id == twnet_parser.msg6.SNAP_SINGLE:
|
||||
msg = system6_snap_single.MsgSnapSingle()
|
||||
elif msg_id == twnet_parser.msg6.INPUT_TIMING:
|
||||
msg = system6_input_timing.MsgInputTiming()
|
||||
elif msg_id == twnet_parser.msg6.RCON_AUTH_STATUS:
|
||||
msg = system6_rcon_auth_status.MsgRconAuthStatus()
|
||||
elif msg_id == twnet_parser.msg6.RCON_LINE:
|
||||
msg = system6_rcon_line.MsgRconLine()
|
||||
elif msg_id == twnet_parser.msg6.READY:
|
||||
msg = system6_ready.MsgReady()
|
||||
elif msg_id == twnet_parser.msg6.ENTER_GAME:
|
||||
msg = system6_enter_game.MsgEnterGame()
|
||||
elif msg_id == twnet_parser.msg6.INPUT:
|
||||
msg = system6_input.MsgInput()
|
||||
elif msg_id == twnet_parser.msg6.RCON_CMD:
|
||||
msg = system6_rcon_cmd.MsgRconCmd()
|
||||
elif msg_id == twnet_parser.msg6.RCON_AUTH:
|
||||
msg = system6_rcon_auth.MsgRconAuth()
|
||||
elif msg_id == twnet_parser.msg6.REQUEST_MAP_DATA:
|
||||
msg = system6_request_map_data.MsgRequestMapData()
|
||||
elif msg_id == twnet_parser.msg6.PING:
|
||||
msg = system6_ping.MsgPing()
|
||||
elif msg_id == twnet_parser.msg6.PING_REPLY:
|
||||
msg = system6_ping_reply.MsgPingReply()
|
||||
elif msg_id == twnet_parser.msg6.RCON_CMD_ADD:
|
||||
msg = system6_rcon_cmd_add.MsgRconCmdAdd()
|
||||
elif msg_id == twnet_parser.msg6.RCON_CMD_REMOVE:
|
||||
msg = system6_rcon_cmd_remove.MsgRconCmdRemove()
|
||||
|
||||
if msg is None:
|
||||
raise ValueError(f"Error: unknown system message id={msg_id} data={data[0]}")
|
||||
|
||||
msg.unpack(data)
|
||||
return msg
|
|
@ -11,6 +11,8 @@ from twnet_parser.connless_message import ConnlessMessage
|
|||
from twnet_parser.chunk_header import ChunkHeader, ChunkFlags
|
||||
from twnet_parser.msg_matcher.control7 import match_control7
|
||||
from twnet_parser.msg_matcher.connless7 import match_connless7
|
||||
from twnet_parser.msg_matcher.control6 import match_control6
|
||||
from twnet_parser.msg_matcher.connless6 import match_connless6
|
||||
from twnet_parser.constants import NET_MAX_SEQUENCE, NET_PACKETVERSION
|
||||
|
||||
from twnet_parser.external.huffman import huffman
|
||||
|
@ -22,6 +24,12 @@ PACKETFLAG7_RESEND = 2
|
|||
PACKETFLAG7_COMPRESSION = 4
|
||||
PACKETFLAG7_CONNLESS = 8
|
||||
|
||||
PACKETFLAG6_TOKEN = 1
|
||||
PACKETFLAG6_CONTROL = 2
|
||||
PACKETFLAG6_CONNLESS = 4
|
||||
PACKETFLAG6_RESEND = 8
|
||||
PACKETFLAG6_COMPRESSION = 16
|
||||
|
||||
CHUNKFLAG7_VITAL = 1
|
||||
CHUNKFLAG7_RESEND = 2
|
||||
|
||||
|
@ -43,6 +51,73 @@ class PacketFlags6(PrettyPrint):
|
|||
self.compression: Optional[bool] = None
|
||||
self.connless: Optional[bool] = None
|
||||
|
||||
class PacketHeader6(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
flags: Optional[PacketFlags6] = None,
|
||||
ack: int = 0,
|
||||
token: bytes = b'\xff\xff\xff\xff',
|
||||
num_chunks: Optional[int] = None
|
||||
) -> None:
|
||||
"""
|
||||
If num_chunks is not set it will count
|
||||
the messages it was given when
|
||||
the pack() method is called
|
||||
"""
|
||||
if not flags:
|
||||
flags = PacketFlags6()
|
||||
self.flags: PacketFlags6 = flags
|
||||
self.ack: int = ack % NET_MAX_SEQUENCE
|
||||
self.token: bytes = token
|
||||
self.num_chunks: Optional[int] = num_chunks
|
||||
|
||||
# connless only
|
||||
self.connless_version: int = NET_PACKETVERSION
|
||||
self.response_token: bytes = b'\xff\xff\xff\xff'
|
||||
|
||||
def pack(self) -> bytes:
|
||||
"""
|
||||
Generate 7 byte teeworlds 0.6.5 packet header
|
||||
based on the current instance variable
|
||||
values.
|
||||
|
||||
The layout is as follows
|
||||
6bit flags, 2bit ack
|
||||
8bit ack
|
||||
8bit chunks
|
||||
32bit token
|
||||
|
||||
ffffffaa
|
||||
aaaaaaaa
|
||||
NNNNNNNN
|
||||
TTTTTTTT
|
||||
TTTTTTTT
|
||||
TTTTTTTT
|
||||
TTTTTTTT
|
||||
"""
|
||||
flags = 0
|
||||
if self.flags.token:
|
||||
flags |= PACKETFLAG6_TOKEN
|
||||
if self.flags.control:
|
||||
flags |= PACKETFLAG6_CONTROL
|
||||
if self.flags.connless:
|
||||
flags |= PACKETFLAG6_CONNLESS
|
||||
if self.flags.resend:
|
||||
flags |= PACKETFLAG6_RESEND
|
||||
if self.flags.compression:
|
||||
flags |= PACKETFLAG6_COMPRESSION
|
||||
if self.num_chunks is None:
|
||||
self.num_chunks = 0
|
||||
if self.flags.connless:
|
||||
return bytes([ \
|
||||
((PACKETFLAG6_CONNLESS<<2)&0xfc) | (self.connless_version&0x03)
|
||||
]) + self.token + self.response_token
|
||||
return bytes([ \
|
||||
((flags << 2)&0xfc) | ((self.ack>>8)&0x03), \
|
||||
self.ack&0xff, \
|
||||
self.num_chunks \
|
||||
]) + self.token
|
||||
|
||||
class PacketHeader(PrettyPrint):
|
||||
def __init__(
|
||||
self,
|
||||
|
@ -113,7 +188,7 @@ class TwPacket(PrettyPrint):
|
|||
self.version: str = 'unknown'
|
||||
self.payload_raw: bytes = b''
|
||||
self.payload_decompressed: bytes = b''
|
||||
self.header: PacketHeader = PacketHeader()
|
||||
self.header: Union[PacketHeader, PacketHeader6] = PacketHeader()
|
||||
self.messages: list[Union[CtrlMessage, NetMessage, ConnlessMessage]] = []
|
||||
|
||||
def pack(self, we_are_a_client = True) -> bytes:
|
||||
|
@ -156,6 +231,48 @@ class TwPacket(PrettyPrint):
|
|||
self.header.flags.connless = True
|
||||
return self.header.pack() + payload
|
||||
|
||||
class PacketHeaderParser6():
|
||||
def parse_flags6(self, data: bytes) -> PacketFlags6:
|
||||
# FFFF FFaa
|
||||
flag_bits = data[0] >> 2
|
||||
flags = PacketFlags6()
|
||||
flags.token = (flag_bits & PACKETFLAG6_TOKEN) != 0
|
||||
flags.control = (flag_bits & PACKETFLAG6_CONTROL) != 0
|
||||
flags.connless = (flag_bits & PACKETFLAG6_CONNLESS) != 0
|
||||
flags.resend = (flag_bits & PACKETFLAG6_RESEND) != 0
|
||||
flags.compression = (flag_bits & PACKETFLAG6_COMPRESSION) != 0
|
||||
return flags
|
||||
|
||||
def parse_ack(self, header_bytes: bytes) -> int:
|
||||
# ffAA AAAA AAAA
|
||||
return ((header_bytes[0] & 0x3) << 8) | header_bytes[1]
|
||||
|
||||
def parse_num_chunks(self, header_bytes: bytes) -> int:
|
||||
# TODO: not sure if this is correct
|
||||
return header_bytes[2]
|
||||
|
||||
def parse_token(self, header_bytes: bytes) -> bytes:
|
||||
return header_bytes[3:7]
|
||||
|
||||
def parse_header(self, data: bytes) -> PacketHeader6:
|
||||
header = PacketHeader6()
|
||||
# bits 1..5
|
||||
header.flags = self.parse_flags6(data)
|
||||
if header.flags.connless:
|
||||
# TODO: do not hardcode version field
|
||||
# but actually read the bits
|
||||
header.connless_version = NET_PACKETVERSION
|
||||
header.token = data[1:5]
|
||||
header.response_token = data[5:9]
|
||||
else:
|
||||
# bits 6..16
|
||||
header.ack = self.parse_ack(data)
|
||||
# bits 17..25
|
||||
header.num_chunks = self.parse_num_chunks(data)
|
||||
# bits 16..57
|
||||
header.token = self.parse_token(data)
|
||||
return header
|
||||
|
||||
class PacketHeaderParser7():
|
||||
def parse_flags7(self, data: bytes) -> PacketFlags7:
|
||||
# FFFF FFaa
|
||||
|
@ -256,6 +373,35 @@ class PacketParser():
|
|||
msg.header = chunk_header
|
||||
return msg
|
||||
|
||||
def parse6(self, data: bytes, client: bool) -> TwPacket:
|
||||
pck = TwPacket()
|
||||
pck.version = '0.6'
|
||||
# TODO: what is the most performant way in python to do this?
|
||||
# heap allocating a PacketHeaderParser7 just to bundle a bunch of
|
||||
# methods that do not share state seems like a waste of performance
|
||||
# would this be nicer with class methods?
|
||||
pck.header = PacketHeaderParser6().parse_header(data)
|
||||
header_size = PACKET_HEADER7_SIZE
|
||||
if pck.header.flags.connless:
|
||||
header_size = CONNLESS_PACKET_HEADER7_SIZE
|
||||
pck.payload_raw = data[header_size:]
|
||||
pck.payload_decompressed = pck.payload_raw
|
||||
if pck.header.flags.control:
|
||||
ctrl_msg: CtrlMessage = match_control6(data[7], data[8:], client)
|
||||
pck.messages.append(ctrl_msg)
|
||||
return pck
|
||||
if pck.header.flags.connless:
|
||||
connless_msg: ConnlessMessage = match_connless6(data[9:17], data[17:])
|
||||
pck.messages.append(connless_msg)
|
||||
return pck
|
||||
if pck.header.flags.compression:
|
||||
payload = bytearray(pck.payload_raw)
|
||||
pck.payload_decompressed = huffman.decompress(payload)
|
||||
pck.messages = cast(
|
||||
list[Union[CtrlMessage, NetMessage, ConnlessMessage]],
|
||||
self.get_messages(pck.payload_decompressed))
|
||||
return pck
|
||||
|
||||
def parse7(self, data: bytes, client: bool) -> TwPacket:
|
||||
pck = TwPacket()
|
||||
pck.version = '0.7'
|
||||
|
@ -285,8 +431,8 @@ class PacketParser():
|
|||
self.get_messages(pck.payload_decompressed))
|
||||
return pck
|
||||
|
||||
def parse6(data: bytes) -> TwPacket:
|
||||
raise NotImplementedError()
|
||||
def parse6(data: bytes, we_are_a_client: bool = True) -> TwPacket:
|
||||
return PacketParser().parse6(data, we_are_a_client)
|
||||
|
||||
def parse7(data: bytes, we_are_a_client: bool = True) -> TwPacket:
|
||||
return PacketParser().parse7(data, we_are_a_client)
|
||||
|
|
Loading…
Reference in a new issue