feat!: snap items in sys/game messages

This commit is not about snapshots!

Generated the snap item classes for 0.6 and 0.7
And changed the type used for snap items from int to the snap class

This now allows to properly serialize and deserialize
messages such as sys.input
This commit is contained in:
ChillerDragon 2023-06-09 12:25:43 +02:00
parent cfc9c47d0d
commit e06ce8366f
51 changed files with 1825 additions and 38 deletions

View file

@ -33,12 +33,12 @@ for msg in packet.messages:
| ---------------------------- | ------------------ | ------------------ |
| Deserialize packet headers | :heavy_check_mark: | :heavy_check_mark: |
| Deserialize chunk headers | :heavy_check_mark: | :heavy_check_mark: |
| Deserialize messages | 85% | 85% |
| Deserialize messages | 90% | 90% |
| Deserialize snapshots | | |
| Deserialize connless packets | :heavy_check_mark: | :heavy_check_mark: |
| Serialize packet headers | :heavy_check_mark: | :heavy_check_mark: |
| Serialize chunk headers | :heavy_check_mark: | :heavy_check_mark: |
| Serialize messages | 85% | 85% |
| Serialize messages | 90% | 90% |
| Serialize snapshots | | |
| Serialize connless packets | :heavy_check_mark: | :heavy_check_mark: |

View file

@ -62,6 +62,9 @@ class NetMessageMemberTypeJson(TypedDict):
kind: KIND
inner: InnerNetMessageMemberTypeJson
# snapshot items
name: list[str]
# enums
enum: list[str]
@ -171,8 +174,9 @@ def gen_unpack_members(msg: NetMessageJson) -> str:
elif member['type']['kind'] == 'tune_param':
unpacker = 'int() / 100.0'
elif member['type']['kind'] == 'snapshot_object':
# TODO: think about snapshot_object
unpacker = 'int() # TODO: this is a snapshot object'
name = name_to_snake(member["name"])
res += f' self.{name}.unpack(unpacker.get_raw())\n'
continue
elif member['type']['kind'] == 'array':
size: int = member['type']['count']
if size is None:
@ -258,8 +262,8 @@ def pack_field(member: NetMessageMemberJson) -> str:
packer = 'int'
field = f'int({field} * 100.0)'
elif member['type']['kind'] == 'snapshot_object':
# TODO: think about snapshot_object
packer = 'int'
name = name_to_snake(member['name'])
return f'self.{name}.pack()'
elif member['type']['kind'] == 'array':
arr_member: ArrayMemberTypeJson = member['type']['member_type']
if arr_member['kind'] == 'string':
@ -415,6 +419,7 @@ class CodeGenerator():
) -> str:
packer_deps: list[str] = []
typing_deps: list[str] = []
custom_deps: list[str] = []
if typing_dep:
typing_deps.append(typing_dep)
need_enums: bool = False
@ -443,8 +448,12 @@ class CodeGenerator():
elif member['type']['kind'] == 'tune_param':
packer_deps.append('pack_int')
elif member['type']['kind'] == 'snapshot_object':
# TODO: think about snapshot_object
packer_deps.append('pack_int')
obj_name: str = 'Obj' + name_to_camel(member['type']['name'])
file_name: str = name_to_snake(member['type']['name'])
typing_deps.append('Optional')
custom_deps.append(
f'from twnet_parser.snap{self.protocol_version}.{file_name} import {obj_name}'
)
elif member['type']['kind'] == 'array':
packer_deps.append('pack_int')
typing_deps.append('Annotated')
@ -488,6 +497,8 @@ class CodeGenerator():
if len(typing_deps) > 0:
res += 'from typing import ' + \
', '.join(sorted(set(typing_deps))) + '\n'
if len(custom_deps) > 0:
res += '\n'.join(sorted(set(custom_deps))) + '\n'
if need_enums:
res += f'import twnet_parser.enum{self.protocol_version} as enum{self.protocol_version}\n'
return res
@ -676,9 +687,9 @@ def match_connless{self.protocol_version}(msg_id: bytes, data: bytes) -> Connles
ftype = 'float'
default = '0.0'
elif member['type']['kind'] == 'snapshot_object':
# TODO: think about snapshot_object
ftype = 'int'
default = '0'
obj_name: str = 'Obj' + name_to_camel(member['type']['name'])
ftype = f'Optional[{obj_name}]'
default = 'None'
elif member['type']['kind'] == 'array':
size: int = member['type']['count']
if size is None:
@ -791,7 +802,7 @@ def match_connless{self.protocol_version}(msg_id: bytes, data: bytes) -> Connles
dirname = os.path.dirname(__file__)
file_path= os.path.join(
dirname,
f'../twnet_parser/snap/0{self.protocol_version}/',
f'../twnet_parser/snap{self.protocol_version}/',
f'{name_snake}.py')
with open(file_path, 'w') as out_file:
print(f"Generating {file_path} ...")
@ -934,8 +945,13 @@ def match_connless{self.protocol_version}(msg_id: bytes, data: bytes) -> Connles
elif member['type']['kind'] == 'tune_param':
ftype = 'float'
elif member['type']['kind'] == 'snapshot_object':
# TODO: think about snapshot_object
ftype = 'int'
obj_name: str = 'Obj' + name_to_camel(member['type']['name'])
ftype = obj_name
name = name_to_snake(member["name"])
out_file.write(f" if not {name}:\n")
out_file.write(f" {name} = {obj_name}()\n")
out_file.write(f" self.{name}: {ftype} = {name}\n")
continue
elif member['type']['kind'] == 'array':
# Array type annotations are so annoyingly long
# also there is a planned refactor
@ -958,6 +974,7 @@ def match_connless{self.protocol_version}(msg_id: bytes, data: bytes) -> Connles
name = name_to_snake(member["name"])
if ftype != '':
ftype = f': {ftype}'
# TODO: what is this if statement doing?
if member['type']['kind'] == 'enum':
out_file.write(f" self.{name}{ftype} = {name}\n")
else:
@ -1079,8 +1096,8 @@ def match_connless{self.protocol_version}(msg_id: bytes, data: bytes) -> Connles
self.generate_msg(msg, 'system')
for connless_msg in connless_messages:
self.generate_msg_connless(connless_msg)
# for obj in snapshot_objects:
# self.generate_snap_obj7(obj)
for obj in snapshot_objects:
self.generate_snap_obj7(obj)
class SpecInfo:
def __init__(

View file

@ -45,3 +45,23 @@ def test_unpack_real_sys_info() -> None:
assert msg.intended_tick == 1654
assert msg.input_size == 40
# these tested values are not really validated
# against another implementation
# but they seem about right
# i was walking left so dir -1 is OK
# i did not touch the mouse so aim 1/0
# seems okay since the server disallows 0/0
# and sets it to 1/0
# i was not hooking/firing/jumping and so on
# since i just joined and held the a key
assert msg.input.direction == -1
assert msg.input.target_x == 1
assert msg.input.target_y == 0
assert msg.input.jump == 0
assert msg.input.fire == 0
assert msg.input.hook == 0
assert msg.input.player_flags == 0
assert msg.input.wanted_weapon == 0
assert msg.input.next_weapon == 0
assert msg.input.prev_weapon == 0

View file

@ -3,14 +3,14 @@
from twnet_parser.pretty_print import PrettyPrint
from twnet_parser.packer import Unpacker
from twnet_parser.chunk_header import ChunkHeader
from twnet_parser.packer import pack_int
from typing import Literal
from typing import Literal, Optional
from twnet_parser.snap6.projectile import ObjProjectile
class MsgSvExtraProjectile(PrettyPrint):
def __init__(
self,
chunk_header: ChunkHeader = ChunkHeader(),
projectile: int = 0
projectile: Optional[ObjProjectile] = None
) -> None:
self.message_type: Literal['system', 'game'] = 'game'
self.message_name: str = 'sv_extra_projectile'
@ -18,15 +18,17 @@ class MsgSvExtraProjectile(PrettyPrint):
self.message_id: int = 7
self.header: ChunkHeader = chunk_header
self.projectile: int = projectile
if not projectile:
projectile = ObjProjectile()
self.projectile: ObjProjectile = 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
self.projectile.unpack(unpacker.get_raw())
return True
def pack(self) -> bytes:
return pack_int(self.projectile)
return self.projectile.pack()

View file

@ -4,7 +4,8 @@ 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
from typing import Literal, Optional
from twnet_parser.snap6.player_input import ObjPlayerInput
class MsgInput(PrettyPrint):
def __init__(
@ -13,7 +14,7 @@ class MsgInput(PrettyPrint):
ack_snapshot: int = 0,
intended_tick: int = 0,
input_size: int = 0,
input: int = 0
input: Optional[ObjPlayerInput] = None
) -> None:
self.message_type: Literal['system', 'game'] = 'system'
self.message_name: str = 'input'
@ -24,7 +25,9 @@ class MsgInput(PrettyPrint):
self.ack_snapshot: int = ack_snapshot
self.intended_tick: int = intended_tick
self.input_size: int = input_size
self.input: int = input
if not input:
input = ObjPlayerInput()
self.input: ObjPlayerInput = input
# first byte of data
# has to be the first byte of the message payload
@ -34,11 +37,11 @@ class MsgInput(PrettyPrint):
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
self.input.unpack(unpacker.get_raw())
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)
self.input.pack()

View file

@ -3,14 +3,14 @@
from twnet_parser.pretty_print import PrettyPrint
from twnet_parser.packer import Unpacker
from twnet_parser.chunk_header import ChunkHeader
from twnet_parser.packer import pack_int
from typing import Literal
from typing import Literal, Optional
from twnet_parser.snap7.projectile import ObjProjectile
class MsgSvExtraProjectile(PrettyPrint):
def __init__(
self,
chunk_header: ChunkHeader = ChunkHeader(),
projectile: int = 0
projectile: Optional[ObjProjectile] = None
) -> None:
self.message_type: Literal['system', 'game'] = 'game'
self.message_name: str = 'sv_extra_projectile'
@ -18,15 +18,17 @@ class MsgSvExtraProjectile(PrettyPrint):
self.message_id: int = 7
self.header: ChunkHeader = chunk_header
self.projectile: int = projectile
if not projectile:
projectile = ObjProjectile()
self.projectile: ObjProjectile = 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
self.projectile.unpack(unpacker.get_raw())
return True
def pack(self) -> bytes:
return pack_int(self.projectile)
return self.projectile.pack()

View file

@ -4,7 +4,8 @@ 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
from typing import Literal, Optional
from twnet_parser.snap7.player_input import ObjPlayerInput
class MsgInput(PrettyPrint):
def __init__(
@ -13,7 +14,7 @@ class MsgInput(PrettyPrint):
ack_snapshot: int = 0,
intended_tick: int = 0,
input_size: int = 0,
input: int = 0
input: Optional[ObjPlayerInput] = None
) -> None:
self.message_type: Literal['system', 'game'] = 'system'
self.message_name: str = 'input'
@ -24,7 +25,9 @@ class MsgInput(PrettyPrint):
self.ack_snapshot: int = ack_snapshot
self.intended_tick: int = intended_tick
self.input_size: int = input_size
self.input: int = input
if not input:
input = ObjPlayerInput()
self.input: ObjPlayerInput = input
# first byte of data
# has to be the first byte of the message payload
@ -34,11 +37,11 @@ class MsgInput(PrettyPrint):
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
self.input.unpack(unpacker.get_raw())
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)
self.input.pack()

View file

@ -0,0 +1,52 @@
# 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_int
import twnet_parser.enum6 as enum6
class ObjCharacter(PrettyPrint):
def __init__(
self,
player_flags: int = 0,
health: int = 0,
armor: int = 0,
ammo_count: int = 0,
weapon: int = enum6.Weapon.HAMMER.value,
emote: int = enum6.Emote.NORMAL.value,
attack_tick: int = 0
) -> None:
self.item_name: str = 'connless.character'
self.type_id: int = 9
self.id: int = 0
self.player_flags: int = player_flags
self.health: int = health
self.armor: int = armor
self.ammo_count: int = ammo_count
self.weapon: int = weapon
self.emote: int = emote
self.attack_tick: int = attack_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.player_flags = unpacker.get_int()
self.health = unpacker.get_int()
self.armor = unpacker.get_int()
self.ammo_count = unpacker.get_int()
self.weapon = unpacker.get_int() # enum WEAPON
self.emote = unpacker.get_int() # enum EMOTE
self.attack_tick = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.player_flags) + \
pack_int(self.health) + \
pack_int(self.armor) + \
pack_int(self.ammo_count) + \
pack_int(self.weapon) + \
pack_int(self.emote) + \
pack_int(self.attack_tick)

View file

@ -0,0 +1,83 @@
# 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_int
class ObjCharacterCore(PrettyPrint):
def __init__(
self,
tick: int = 0,
x: int = 0,
y: int = 0,
vel_x: int = 0,
vel_y: int = 0,
angle: int = 0,
direction: int = 0,
jumped: int = 0,
hooked_player: int = 0,
hook_state: int = 0,
hook_tick: int = 0,
hook_x: int = 0,
hook_y: int = 0,
hook_dx: int = 0,
hook_dy: int = 0
) -> None:
self.item_name: str = 'connless.character_core'
self.type_id: int = 8
self.id: int = 0
self.tick: int = tick
self.x: int = x
self.y: int = y
self.vel_x: int = vel_x
self.vel_y: int = vel_y
self.angle: int = angle
self.direction: int = direction
self.jumped: int = jumped
self.hooked_player: int = hooked_player
self.hook_state: int = hook_state
self.hook_tick: int = hook_tick
self.hook_x: int = hook_x
self.hook_y: int = hook_y
self.hook_dx: int = hook_dx
self.hook_dy: int = hook_dy
# 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.x = unpacker.get_int()
self.y = unpacker.get_int()
self.vel_x = unpacker.get_int()
self.vel_y = unpacker.get_int()
self.angle = unpacker.get_int()
self.direction = unpacker.get_int()
self.jumped = unpacker.get_int()
self.hooked_player = unpacker.get_int()
self.hook_state = unpacker.get_int()
self.hook_tick = unpacker.get_int()
self.hook_x = unpacker.get_int()
self.hook_y = unpacker.get_int()
self.hook_dx = unpacker.get_int()
self.hook_dy = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.tick) + \
pack_int(self.x) + \
pack_int(self.y) + \
pack_int(self.vel_x) + \
pack_int(self.vel_y) + \
pack_int(self.angle) + \
pack_int(self.direction) + \
pack_int(self.jumped) + \
pack_int(self.hooked_player) + \
pack_int(self.hook_state) + \
pack_int(self.hook_tick) + \
pack_int(self.hook_x) + \
pack_int(self.hook_y) + \
pack_int(self.hook_dx) + \
pack_int(self.hook_dy)

View file

@ -0,0 +1,58 @@
# 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_int
from typing import Annotated
class ObjClientInfo(PrettyPrint):
def __init__(
self,
name: Annotated[list[int], 4] = \
[0, 0, 0, 0],
clan: Annotated[list[int], 3] = \
[0, 0, 0],
country: int = 0,
skin: Annotated[list[int], 6] = \
[0, 0, 0, 0, 0, 0],
use_custom_color: int = 0,
color_body: int = 0,
color_feet: int = 0
) -> None:
self.item_name: str = 'connless.client_info'
self.type_id: int = 11
self.id: int = 0
self.name = name
self.clan = clan
self.country: int = country
self.skin = skin
self.use_custom_color: int = 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)
for i in range(0, 4):
self.name[i] = unpacker.get_int()
for i in range(0, 3):
self.clan[i] = unpacker.get_int()
self.country = unpacker.get_int()
for i in range(0, 6):
self.skin[i] = unpacker.get_int()
self.use_custom_color = unpacker.get_int()
self.color_body = unpacker.get_int()
self.color_feet = unpacker.get_int()
return True
def pack(self) -> bytes:
return b''.join([pack_int(x) for x in self.name]) + \
b''.join([pack_int(x) for x in self.clan]) + \
pack_int(self.country) + \
b''.join([pack_int(x) for x in self.skin]) + \
pack_int(self.use_custom_color) + \
pack_int(self.color_body) + \
pack_int(self.color_feet)

View file

@ -0,0 +1,31 @@
# 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_int
class ObjCommon(PrettyPrint):
def __init__(
self,
x: int = 0,
y: int = 0
) -> None:
self.item_name: str = 'connless.common'
self.type_id: int = 13
self.id: int = 0
self.x: int = x
self.y: int = y
# 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.x = unpacker.get_int()
self.y = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.x) + \
pack_int(self.y)

View file

@ -0,0 +1,27 @@
# 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_int
class ObjDamageInd(PrettyPrint):
def __init__(
self,
angle: int = 0
) -> None:
self.item_name: str = 'connless.damage_ind'
self.type_id: int = 20
self.id: int = 0
self.angle: int = angle
# 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.angle = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.angle)

View file

@ -0,0 +1,27 @@
# 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_int
class ObjDeath(PrettyPrint):
def __init__(
self,
client_id: int = 0
) -> None:
self.item_name: str = 'connless.death'
self.type_id: int = 17
self.id: int = 0
self.client_id: int = client_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.client_id = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.client_id)

View file

@ -0,0 +1,21 @@
# generated by scripts/generate_messages.py
from twnet_parser.pretty_print import PrettyPrint
class ObjExplosion(PrettyPrint):
def __init__(
self
) -> None:
self.item_name: str = 'connless.explosion'
self.type_id: int = 14
self.id: int = 0
# 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''

View file

@ -0,0 +1,35 @@
# 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_int
class ObjFlag(PrettyPrint):
def __init__(
self,
x: int = 0,
y: int = 0,
team: int = 0
) -> None:
self.item_name: str = 'connless.flag'
self.type_id: int = 5
self.id: int = 0
self.x: int = x
self.y: int = y
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.x = unpacker.get_int()
self.y = unpacker.get_int()
self.team = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.x) + \
pack_int(self.y) + \
pack_int(self.team)

View file

@ -0,0 +1,39 @@
# 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_int
class ObjGameData(PrettyPrint):
def __init__(
self,
teamscore_red: int = 0,
teamscore_blue: int = 0,
flag_carrier_red: int = 0,
flag_carrier_blue: int = 0
) -> None:
self.item_name: str = 'connless.game_data'
self.type_id: int = 7
self.id: int = 0
self.teamscore_red: int = teamscore_red
self.teamscore_blue: int = teamscore_blue
self.flag_carrier_red: int = flag_carrier_red
self.flag_carrier_blue: int = flag_carrier_blue
# 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.teamscore_red = unpacker.get_int()
self.teamscore_blue = unpacker.get_int()
self.flag_carrier_red = unpacker.get_int()
self.flag_carrier_blue = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.teamscore_red) + \
pack_int(self.teamscore_blue) + \
pack_int(self.flag_carrier_red) + \
pack_int(self.flag_carrier_blue)

View file

@ -0,0 +1,55 @@
# 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_int
class ObjGameInfo(PrettyPrint):
def __init__(
self,
game_flags: int = 0,
game_state_flags: int = 0,
round_start_tick: int = 0,
warmup_timer: int = 0,
score_limit: int = 0,
time_limit: int = 0,
round_num: int = 0,
round_current: int = 0
) -> None:
self.item_name: str = 'connless.game_info'
self.type_id: int = 6
self.id: int = 0
self.game_flags: int = game_flags
self.game_state_flags: int = game_state_flags
self.round_start_tick: int = round_start_tick
self.warmup_timer: int = warmup_timer
self.score_limit: int = score_limit
self.time_limit: int = time_limit
self.round_num: int = round_num
self.round_current: int = round_current
# 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.game_flags = unpacker.get_int()
self.game_state_flags = unpacker.get_int()
self.round_start_tick = unpacker.get_int()
self.warmup_timer = unpacker.get_int()
self.score_limit = unpacker.get_int()
self.time_limit = unpacker.get_int()
self.round_num = unpacker.get_int()
self.round_current = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.game_flags) + \
pack_int(self.game_state_flags) + \
pack_int(self.round_start_tick) + \
pack_int(self.warmup_timer) + \
pack_int(self.score_limit) + \
pack_int(self.time_limit) + \
pack_int(self.round_num) + \
pack_int(self.round_current)

View file

@ -0,0 +1,21 @@
# generated by scripts/generate_messages.py
from twnet_parser.pretty_print import PrettyPrint
class ObjHammerHit(PrettyPrint):
def __init__(
self
) -> None:
self.item_name: str = 'connless.hammer_hit'
self.type_id: int = 16
self.id: int = 0
# 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''

View file

@ -0,0 +1,43 @@
# 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_int
class ObjLaser(PrettyPrint):
def __init__(
self,
x: int = 0,
y: int = 0,
from_x: int = 0,
from_y: int = 0,
start_tick: int = 0
) -> None:
self.item_name: str = 'connless.laser'
self.type_id: int = 3
self.id: int = 0
self.x: int = x
self.y: int = y
self.from_x: int = from_x
self.from_y: int = from_y
self.start_tick: int = start_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.x = unpacker.get_int()
self.y = unpacker.get_int()
self.from_x = unpacker.get_int()
self.from_y = unpacker.get_int()
self.start_tick = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.x) + \
pack_int(self.y) + \
pack_int(self.from_x) + \
pack_int(self.from_y) + \
pack_int(self.start_tick)

View file

@ -0,0 +1,39 @@
# 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_int
class ObjPickup(PrettyPrint):
def __init__(
self,
x: int = 0,
y: int = 0,
type: int = 0,
subtype: int = 0
) -> None:
self.item_name: str = 'connless.pickup'
self.type_id: int = 4
self.id: int = 0
self.x: int = x
self.y: int = y
self.type: int = type
self.subtype: int = subtype
# 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.x = unpacker.get_int()
self.y = unpacker.get_int()
self.type = unpacker.get_int()
self.subtype = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.x) + \
pack_int(self.y) + \
pack_int(self.type) + \
pack_int(self.subtype)

View 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.packer import pack_int
import twnet_parser.enum6 as enum6
class ObjPlayerInfo(PrettyPrint):
def __init__(
self,
local: int = 0,
client_id: int = 0,
team: int = enum6.Team.SPECTATORS.value,
score: int = 0,
latency: int = 0
) -> None:
self.item_name: str = 'connless.player_info'
self.type_id: int = 10
self.id: int = 0
self.local: int = local
self.client_id: int = client_id
self.team: int = team
self.score: int = score
self.latency: int = latency
# 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.local = unpacker.get_int()
self.client_id = unpacker.get_int()
self.team = unpacker.get_int() # enum TEAM
self.score = unpacker.get_int()
self.latency = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.local) + \
pack_int(self.client_id) + \
pack_int(self.team) + \
pack_int(self.score) + \
pack_int(self.latency)

View file

@ -0,0 +1,63 @@
# 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_int
class ObjPlayerInput(PrettyPrint):
def __init__(
self,
direction: int = 0,
target_x: int = 0,
target_y: int = 0,
jump: int = 0,
fire: int = 0,
hook: int = 0,
player_flags: int = 0,
wanted_weapon: int = 0,
next_weapon: int = 0,
prev_weapon: int = 0
) -> None:
self.item_name: str = 'connless.player_input'
self.type_id: int = 1
self.id: int = 0
self.direction: int = direction
self.target_x: int = target_x
self.target_y: int = target_y
self.jump: int = jump
self.fire: int = fire
self.hook: int = hook
self.player_flags: int = player_flags
self.wanted_weapon: int = wanted_weapon
self.next_weapon: int = next_weapon
self.prev_weapon: int = prev_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.direction = unpacker.get_int()
self.target_x = unpacker.get_int()
self.target_y = unpacker.get_int()
self.jump = unpacker.get_int()
self.fire = unpacker.get_int()
self.hook = unpacker.get_int()
self.player_flags = unpacker.get_int()
self.wanted_weapon = unpacker.get_int()
self.next_weapon = unpacker.get_int()
self.prev_weapon = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.direction) + \
pack_int(self.target_x) + \
pack_int(self.target_y) + \
pack_int(self.jump) + \
pack_int(self.fire) + \
pack_int(self.hook) + \
pack_int(self.player_flags) + \
pack_int(self.wanted_weapon) + \
pack_int(self.next_weapon) + \
pack_int(self.prev_weapon)

View 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.packer import pack_int
import twnet_parser.enum6 as enum6
class ObjProjectile(PrettyPrint):
def __init__(
self,
x: int = 0,
y: int = 0,
vel_x: int = 0,
vel_y: int = 0,
type: int = enum6.Weapon.HAMMER.value,
start_tick: int = 0
) -> None:
self.item_name: str = 'connless.projectile'
self.type_id: int = 2
self.id: int = 0
self.x: int = x
self.y: int = y
self.vel_x: int = vel_x
self.vel_y: int = vel_y
self.type: int = type
self.start_tick: int = start_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.x = unpacker.get_int()
self.y = unpacker.get_int()
self.vel_x = unpacker.get_int()
self.vel_y = unpacker.get_int()
self.type = unpacker.get_int() # enum WEAPON
self.start_tick = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.x) + \
pack_int(self.y) + \
pack_int(self.vel_x) + \
pack_int(self.vel_y) + \
pack_int(self.type) + \
pack_int(self.start_tick)

View 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_int
import twnet_parser.enum6 as enum6
class ObjSoundGlobal(PrettyPrint):
def __init__(
self,
sound_id: int = enum6.Sound.GUN_FIRE.value
) -> None:
self.item_name: str = 'connless.sound_global'
self.type_id: int = 18
self.id: int = 0
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)

View 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_int
import twnet_parser.enum6 as enum6
class ObjSoundWorld(PrettyPrint):
def __init__(
self,
sound_id: int = enum6.Sound.GUN_FIRE.value
) -> None:
self.item_name: str = 'connless.sound_world'
self.type_id: int = 19
self.id: int = 0
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)

View file

@ -0,0 +1,21 @@
# generated by scripts/generate_messages.py
from twnet_parser.pretty_print import PrettyPrint
class ObjSpawn(PrettyPrint):
def __init__(
self
) -> None:
self.item_name: str = 'connless.spawn'
self.type_id: int = 15
self.id: int = 0
# 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''

View file

@ -0,0 +1,35 @@
# 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_int
class ObjSpectatorInfo(PrettyPrint):
def __init__(
self,
spectator_id: int = 0,
x: int = 0,
y: int = 0
) -> None:
self.item_name: str = 'connless.spectator_info'
self.type_id: int = 12
self.id: int = 0
self.spectator_id: int = spectator_id
self.x: int = x
self.y: int = y
# 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()
self.x = unpacker.get_int()
self.y = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.spectator_id) + \
pack_int(self.x) + \
pack_int(self.y)

View file

@ -0,0 +1,52 @@
# 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_int
import twnet_parser.enum7 as enum7
class ObjCharacter(PrettyPrint):
def __init__(
self,
health: int = 0,
armor: int = 0,
ammo_count: int = 0,
weapon: int = enum7.Weapon.HAMMER.value,
emote: int = enum7.Emote.NORMAL.value,
attack_tick: int = 0,
triggered_events: int = 0
) -> None:
self.item_name: str = 'connless.character'
self.type_id: int = 10
self.id: int = 0
self.health: int = health
self.armor: int = armor
self.ammo_count: int = ammo_count
self.weapon: int = weapon
self.emote: int = emote
self.attack_tick: int = attack_tick
self.triggered_events: int = triggered_events
# 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.health = unpacker.get_int()
self.armor = unpacker.get_int()
self.ammo_count = unpacker.get_int()
self.weapon = unpacker.get_int() # enum WEAPON
self.emote = unpacker.get_int() # enum EMOTE
self.attack_tick = unpacker.get_int()
self.triggered_events = unpacker.get_int() # TODO: this is a flag
return True
def pack(self) -> bytes:
return pack_int(self.health) + \
pack_int(self.armor) + \
pack_int(self.ammo_count) + \
pack_int(self.weapon) + \
pack_int(self.emote) + \
pack_int(self.attack_tick) + \
pack_int(self.triggered_events)

View file

@ -0,0 +1,83 @@
# 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_int
class ObjCharacterCore(PrettyPrint):
def __init__(
self,
tick: int = 0,
x: int = 0,
y: int = 0,
vel_x: int = 0,
vel_y: int = 0,
angle: int = 0,
direction: int = 0,
jumped: int = 0,
hooked_player: int = 0,
hook_state: int = 0,
hook_tick: int = 0,
hook_x: int = 0,
hook_y: int = 0,
hook_dx: int = 0,
hook_dy: int = 0
) -> None:
self.item_name: str = 'connless.character_core'
self.type_id: int = 9
self.id: int = 0
self.tick: int = tick
self.x: int = x
self.y: int = y
self.vel_x: int = vel_x
self.vel_y: int = vel_y
self.angle: int = angle
self.direction: int = direction
self.jumped: int = jumped
self.hooked_player: int = hooked_player
self.hook_state: int = hook_state
self.hook_tick: int = hook_tick
self.hook_x: int = hook_x
self.hook_y: int = hook_y
self.hook_dx: int = hook_dx
self.hook_dy: int = hook_dy
# 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.x = unpacker.get_int()
self.y = unpacker.get_int()
self.vel_x = unpacker.get_int()
self.vel_y = unpacker.get_int()
self.angle = unpacker.get_int()
self.direction = unpacker.get_int()
self.jumped = unpacker.get_int()
self.hooked_player = unpacker.get_int()
self.hook_state = unpacker.get_int()
self.hook_tick = unpacker.get_int()
self.hook_x = unpacker.get_int()
self.hook_y = unpacker.get_int()
self.hook_dx = unpacker.get_int()
self.hook_dy = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.tick) + \
pack_int(self.x) + \
pack_int(self.y) + \
pack_int(self.vel_x) + \
pack_int(self.vel_y) + \
pack_int(self.angle) + \
pack_int(self.direction) + \
pack_int(self.jumped) + \
pack_int(self.hooked_player) + \
pack_int(self.hook_state) + \
pack_int(self.hook_tick) + \
pack_int(self.hook_x) + \
pack_int(self.hook_y) + \
pack_int(self.hook_dx) + \
pack_int(self.hook_dy)

View file

@ -0,0 +1,31 @@
# 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_int
class ObjCommon(PrettyPrint):
def __init__(
self,
x: int = 0,
y: int = 0
) -> None:
self.item_name: str = 'connless.common'
self.type_id: int = 16
self.id: int = 0
self.x: int = x
self.y: int = y
# 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.x = unpacker.get_int()
self.y = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.x) + \
pack_int(self.y)

View file

@ -0,0 +1,43 @@
# 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_int
class ObjDamage(PrettyPrint):
def __init__(
self,
client_id: int = 0,
angle: int = 0,
health_amount: int = 0,
armor_amount: int = 0,
self_: bool = False
) -> None:
self.item_name: str = 'connless.damage'
self.type_id: int = 22
self.id: int = 0
self.client_id: int = client_id
self.angle: int = angle
self.health_amount: int = health_amount
self.armor_amount: int = armor_amount
self.self_: bool = self_
# 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.angle = unpacker.get_int()
self.health_amount = unpacker.get_int()
self.armor_amount = unpacker.get_int()
self.self_ = unpacker.get_int() == 1
return True
def pack(self) -> bytes:
return pack_int(self.client_id) + \
pack_int(self.angle) + \
pack_int(self.health_amount) + \
pack_int(self.armor_amount) + \
pack_int(self.self_)

View file

@ -0,0 +1,75 @@
# 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_int
from typing import Annotated
import twnet_parser.enum7 as enum7
class ObjDeClientInfo(PrettyPrint):
def __init__(
self,
local: bool = False,
team: int = enum7.Team.SPECTATORS.value,
name: Annotated[list[int], 4] = \
[0, 0, 0, 0],
clan: Annotated[list[int], 3] = \
[0, 0, 0],
country: int = 0,
skin_part_names: Annotated[list[list[int]], (6,6)] = \
[[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0]],
use_custom_colors: Annotated[list[bool], 6] = \
[False, False, False, False, False, False],
skin_part_colors: Annotated[list[int], 6] = \
[0, 0, 0, 0, 0, 0]
) -> None:
self.item_name: str = 'connless.de_client_info'
self.type_id: int = 13
self.id: int = 0
self.local: bool = local
self.team: int = team
self.name = name
self.clan = clan
self.country: int = country
self.skin_part_names = skin_part_names
self.use_custom_colors = use_custom_colors
self.skin_part_colors = skin_part_colors
# 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.local = unpacker.get_int() == 1
self.team = unpacker.get_int() # enum TEAM
for i in range(0, 4):
self.name[i] = unpacker.get_int()
for i in range(0, 3):
self.clan[i] = unpacker.get_int()
self.country = unpacker.get_int()
for i in range(0, 6):
sub: list[int] = []
for k in range(0, 6):
sub[k] = unpacker.get_int()
self.skin_part_names[i] = sub
for i in range(0, 6):
self.use_custom_colors[i] = unpacker.get_int() == 1
for i in range(0, 6):
self.skin_part_colors[i] = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.local) + \
pack_int(self.team) + \
b''.join([pack_int(x) for x in self.name]) + \
b''.join([pack_int(x) for x in self.clan]) + \
pack_int(self.country) + \
b''.join([b''.join([pack_int(x) for x in sub]) for sub in self.skin_part_names]) + \
b''.join([pack_int(x) for x in self.use_custom_colors]) + \
b''.join([pack_int(x) for x in self.skin_part_colors])

View file

@ -0,0 +1,43 @@
# 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_int
class ObjDeGameInfo(PrettyPrint):
def __init__(
self,
game_flags: int = 0,
score_limit: int = 0,
time_limit: int = 0,
match_num: int = 0,
match_current: int = 0
) -> None:
self.item_name: str = 'connless.de_game_info'
self.type_id: int = 14
self.id: int = 0
self.game_flags: int = game_flags
self.score_limit: int = score_limit
self.time_limit: int = time_limit
self.match_num: int = match_num
self.match_current: int = match_current
# 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.game_flags = unpacker.get_int() # TODO: this is a flag
self.score_limit = unpacker.get_int()
self.time_limit = unpacker.get_int()
self.match_num = unpacker.get_int()
self.match_current = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.game_flags) + \
pack_int(self.score_limit) + \
pack_int(self.time_limit) + \
pack_int(self.match_num) + \
pack_int(self.match_current)

View file

@ -0,0 +1,30 @@
# 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_int
from typing import Annotated
class ObjDeTuneParams(PrettyPrint):
def __init__(
self,
tune_params: Annotated[list[int], 32] = \
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
) -> None:
self.item_name: str = 'connless.de_tune_params'
self.type_id: int = 15
self.id: int = 0
self.tune_params = tune_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)
for i in range(0, 32):
self.tune_params[i] = unpacker.get_int()
return True
def pack(self) -> bytes:
return b''.join([pack_int(x) for x in self.tune_params])

View file

@ -0,0 +1,27 @@
# 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_int
class ObjDeath(PrettyPrint):
def __init__(
self,
client_id: int = 0
) -> None:
self.item_name: str = 'connless.death'
self.type_id: int = 20
self.id: int = 0
self.client_id: int = client_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.client_id = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.client_id)

View file

@ -0,0 +1,21 @@
# generated by scripts/generate_messages.py
from twnet_parser.pretty_print import PrettyPrint
class ObjExplosion(PrettyPrint):
def __init__(
self
) -> None:
self.item_name: str = 'connless.explosion'
self.type_id: int = 17
self.id: int = 0
# 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''

View file

@ -0,0 +1,35 @@
# 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_int
class ObjFlag(PrettyPrint):
def __init__(
self,
x: int = 0,
y: int = 0,
team: int = 0
) -> None:
self.item_name: str = 'connless.flag'
self.type_id: int = 5
self.id: int = 0
self.x: int = x
self.y: int = y
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.x = unpacker.get_int()
self.y = unpacker.get_int()
self.team = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.x) + \
pack_int(self.y) + \
pack_int(self.team)

View file

@ -0,0 +1,35 @@
# 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_int
class ObjGameData(PrettyPrint):
def __init__(
self,
game_start_tick: int = 0,
game_state_flags: int = 0,
game_state_end_tick: int = 0
) -> None:
self.item_name: str = 'connless.game_data'
self.type_id: int = 6
self.id: int = 0
self.game_start_tick: int = game_start_tick
self.game_state_flags: int = game_state_flags
self.game_state_end_tick: int = game_state_end_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.game_start_tick = unpacker.get_int()
self.game_state_flags = unpacker.get_int() # TODO: this is a flag
self.game_state_end_tick = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.game_start_tick) + \
pack_int(self.game_state_flags) + \
pack_int(self.game_state_end_tick)

View file

@ -0,0 +1,39 @@
# 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_int
class ObjGameDataFlag(PrettyPrint):
def __init__(
self,
flag_carrier_red: int = 0,
flag_carrier_blue: int = 0,
flag_drop_tick_red: int = 0,
flag_drop_tick_blue: int = 0
) -> None:
self.item_name: str = 'connless.game_data_flag'
self.type_id: int = 8
self.id: int = 0
self.flag_carrier_red: int = flag_carrier_red
self.flag_carrier_blue: int = flag_carrier_blue
self.flag_drop_tick_red: int = flag_drop_tick_red
self.flag_drop_tick_blue: int = flag_drop_tick_blue
# 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.flag_carrier_red = unpacker.get_int()
self.flag_carrier_blue = unpacker.get_int()
self.flag_drop_tick_red = unpacker.get_int()
self.flag_drop_tick_blue = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.flag_carrier_red) + \
pack_int(self.flag_carrier_blue) + \
pack_int(self.flag_drop_tick_red) + \
pack_int(self.flag_drop_tick_blue)

View file

@ -0,0 +1,35 @@
# 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_int
class ObjGameDataRace(PrettyPrint):
def __init__(
self,
best_time: int = 0,
precision: int = 0,
race_flags: int = 0
) -> None:
self.item_name: str = 'connless.game_data_race'
self.type_id: int = 24
self.id: int = 0
self.best_time: int = best_time
self.precision: int = precision
self.race_flags: int = race_flags
# 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.best_time = unpacker.get_int()
self.precision = unpacker.get_int()
self.race_flags = unpacker.get_int() # TODO: this is a flag
return True
def pack(self) -> bytes:
return pack_int(self.best_time) + \
pack_int(self.precision) + \
pack_int(self.race_flags)

View file

@ -0,0 +1,31 @@
# 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_int
class ObjGameDataTeam(PrettyPrint):
def __init__(
self,
teamscore_red: int = 0,
teamscore_blue: int = 0
) -> None:
self.item_name: str = 'connless.game_data_team'
self.type_id: int = 7
self.id: int = 0
self.teamscore_red: int = teamscore_red
self.teamscore_blue: int = teamscore_blue
# 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.teamscore_red = unpacker.get_int()
self.teamscore_blue = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.teamscore_red) + \
pack_int(self.teamscore_blue)

View file

@ -0,0 +1,21 @@
# generated by scripts/generate_messages.py
from twnet_parser.pretty_print import PrettyPrint
class ObjHammerHit(PrettyPrint):
def __init__(
self
) -> None:
self.item_name: str = 'connless.hammer_hit'
self.type_id: int = 19
self.id: int = 0
# 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''

View file

@ -0,0 +1,43 @@
# 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_int
class ObjLaser(PrettyPrint):
def __init__(
self,
x: int = 0,
y: int = 0,
from_x: int = 0,
from_y: int = 0,
start_tick: int = 0
) -> None:
self.item_name: str = 'connless.laser'
self.type_id: int = 3
self.id: int = 0
self.x: int = x
self.y: int = y
self.from_x: int = from_x
self.from_y: int = from_y
self.start_tick: int = start_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.x = unpacker.get_int()
self.y = unpacker.get_int()
self.from_x = unpacker.get_int()
self.from_y = unpacker.get_int()
self.start_tick = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.x) + \
pack_int(self.y) + \
pack_int(self.from_x) + \
pack_int(self.from_y) + \
pack_int(self.start_tick)

View 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.packer import pack_int
import twnet_parser.enum7 as enum7
class ObjPickup(PrettyPrint):
def __init__(
self,
x: int = 0,
y: int = 0,
type: int = enum7.Pickup.HEALTH.value
) -> None:
self.item_name: str = 'connless.pickup'
self.type_id: int = 4
self.id: int = 0
self.x: int = x
self.y: int = y
self.type: int = type
# 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.x = unpacker.get_int()
self.y = unpacker.get_int()
self.type = unpacker.get_int() # enum PICKUP
return True
def pack(self) -> bytes:
return pack_int(self.x) + \
pack_int(self.y) + \
pack_int(self.type)

View file

@ -0,0 +1,35 @@
# 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_int
class ObjPlayerInfo(PrettyPrint):
def __init__(
self,
player_flags: int = 0,
score: int = 0,
latency: int = 0
) -> None:
self.item_name: str = 'connless.player_info'
self.type_id: int = 11
self.id: int = 0
self.player_flags: int = player_flags
self.score: int = score
self.latency: int = latency
# 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.player_flags = unpacker.get_int() # TODO: this is a flag
self.score = unpacker.get_int()
self.latency = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.player_flags) + \
pack_int(self.score) + \
pack_int(self.latency)

View file

@ -0,0 +1,27 @@
# 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_int
class ObjPlayerInfoRace(PrettyPrint):
def __init__(
self,
race_start_tick: int = 0
) -> None:
self.item_name: str = 'connless.player_info_race'
self.type_id: int = 23
self.id: int = 0
self.race_start_tick: int = race_start_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.race_start_tick = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.race_start_tick)

View file

@ -0,0 +1,63 @@
# 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_int
class ObjPlayerInput(PrettyPrint):
def __init__(
self,
direction: int = 0,
target_x: int = 0,
target_y: int = 0,
jump: bool = False,
fire: int = 0,
hook: bool = False,
player_flags: int = 0,
wanted_weapon: int = 0,
next_weapon: int = 0,
prev_weapon: int = 0
) -> None:
self.item_name: str = 'connless.player_input'
self.type_id: int = 1
self.id: int = 0
self.direction: int = direction
self.target_x: int = target_x
self.target_y: int = target_y
self.jump: bool = jump
self.fire: int = fire
self.hook: bool = hook
self.player_flags: int = player_flags
self.wanted_weapon: int = wanted_weapon
self.next_weapon: int = next_weapon
self.prev_weapon: int = prev_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.direction = unpacker.get_int()
self.target_x = unpacker.get_int()
self.target_y = unpacker.get_int()
self.jump = unpacker.get_int() == 1
self.fire = unpacker.get_int()
self.hook = unpacker.get_int() == 1
self.player_flags = unpacker.get_int() # TODO: this is a flag
self.wanted_weapon = unpacker.get_int()
self.next_weapon = unpacker.get_int()
self.prev_weapon = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.direction) + \
pack_int(self.target_x) + \
pack_int(self.target_y) + \
pack_int(self.jump) + \
pack_int(self.fire) + \
pack_int(self.hook) + \
pack_int(self.player_flags) + \
pack_int(self.wanted_weapon) + \
pack_int(self.next_weapon) + \
pack_int(self.prev_weapon)

View 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.packer import pack_int
import twnet_parser.enum7 as enum7
class ObjProjectile(PrettyPrint):
def __init__(
self,
x: int = 0,
y: int = 0,
vel_x: int = 0,
vel_y: int = 0,
type: int = enum7.Weapon.HAMMER.value,
start_tick: int = 0
) -> None:
self.item_name: str = 'connless.projectile'
self.type_id: int = 2
self.id: int = 0
self.x: int = x
self.y: int = y
self.vel_x: int = vel_x
self.vel_y: int = vel_y
self.type: int = type
self.start_tick: int = start_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.x = unpacker.get_int()
self.y = unpacker.get_int()
self.vel_x = unpacker.get_int()
self.vel_y = unpacker.get_int()
self.type = unpacker.get_int() # enum WEAPON
self.start_tick = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.x) + \
pack_int(self.y) + \
pack_int(self.vel_x) + \
pack_int(self.vel_y) + \
pack_int(self.type) + \
pack_int(self.start_tick)

View 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_int
import twnet_parser.enum7 as enum7
class ObjSoundWorld(PrettyPrint):
def __init__(
self,
sound_id: int = enum7.Sound.GUN_FIRE.value
) -> None:
self.item_name: str = 'connless.sound_world'
self.type_id: int = 21
self.id: int = 0
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)

View file

@ -0,0 +1,21 @@
# generated by scripts/generate_messages.py
from twnet_parser.pretty_print import PrettyPrint
class ObjSpawn(PrettyPrint):
def __init__(
self
) -> None:
self.item_name: str = 'connless.spawn'
self.type_id: int = 18
self.id: int = 0
# 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''

View 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.packer import pack_int
import twnet_parser.enum7 as enum7
class ObjSpectatorInfo(PrettyPrint):
def __init__(
self,
spec_mode: int = enum7.Spec.FREEVIEW.value,
spectator_id: int = 0,
x: int = 0,
y: int = 0
) -> None:
self.item_name: str = 'connless.spectator_info'
self.type_id: int = 12
self.id: int = 0
self.spec_mode: int = spec_mode
self.spectator_id: int = spectator_id
self.x: int = x
self.y: int = y
# 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.spec_mode = unpacker.get_int() # enum SPEC
self.spectator_id = unpacker.get_int()
self.x = unpacker.get_int()
self.y = unpacker.get_int()
return True
def pack(self) -> bytes:
return pack_int(self.spec_mode) + \
pack_int(self.spectator_id) + \
pack_int(self.x) + \
pack_int(self.y)