From 079a638c619e516908ec8d86fc311d9af499a4ae Mon Sep 17 00:00:00 2001 From: Skipper Date: Mon, 10 Feb 2025 12:47:24 +0000 Subject: Some updates to packets Various updates, added smoke function to airplanestate, which modifies the incoming packet to make the client smoke, needs to be taken with WEAPONCONFIG.addSmoke Added in placeholder classes for Player and Aircraft --- lib/Aircraft.py | 83 ++++++++++++++++++++++ lib/PacketManager/PacketManager.py | 4 +- .../packets/FSNETCMD_AIRPLANESTATE.py | 55 +++++++++++--- .../packets/FSNETCMD_MISSILELAUNCH.py | 57 +++++++++++---- lib/PacketManager/packets/FSNETCMD_TEXTMESSAGE.py | 2 +- lib/PacketManager/packets/FSNETCMD_WEAPONCONFIG.py | 2 +- lib/Player.py | 35 +++++++++ 7 files changed, 213 insertions(+), 25 deletions(-) create mode 100644 lib/Aircraft.py create mode 100644 lib/Player.py (limited to 'lib') diff --git a/lib/Aircraft.py b/lib/Aircraft.py new file mode 100644 index 0000000..3b79947 --- /dev/null +++ b/lib/Aircraft.py @@ -0,0 +1,83 @@ +from lib.PacketManager.packets import FSNETCMD_AIRPLANESTATE, FSNETCMD_AIRCMD +class Aircraft: + """ + An aircraft class - this will hold the info from the Airplane state, weapons etc packets.""" + def __init__(self, parent=None): + self.parent = parent + self.name = "" + self.position = [0,0,0] + self.attitude = [0,0,0] + self.initial_config = {} + self.custom_config = {} + self.life = -1 + self.prev_life = -1 + self.id = -1 + self.last_packet = None + + def reset(self): + """Resets the aircraft""" + self.name = "" + self.position = [0,0,0] + self.attitude = [0,0,0] + self.initial_config = {} + self.custom_config = {} + self.life = -1 + self.prev_life = -1 + self.id = -1 + self.last_packet = None + + def set_position(self, position:list): + """Sets the position of the aircraft from the Airplane state packet""" + self.position = position + + def set_attitude(self, attitude:list): + """Sets the attitude of the aircraft from the Airplane state packet""" + self.attitude = attitude + + def get_position(self): + """Returns the position of the aircraft""" + return self.position + + def get_altitude(self): + """Returns the altitude in m""" + return self.position[2] + + def get_attitude(self): + """Returns the attitude of the aircraft""" + return self.attitude + + def set_initial_config(self, config:dict): + """Sets the initial config of the aircraft""" + for key in config: + self.initial_config[key] = config[key] + + def get_initial_config_value(self, key:str): + """Returns the value of the initial config""" + if key in self.initial_config: + return self.initial_config[key] + + return None + + def set_custom_config_value(self, key:str, value): + """Sets a custom config value""" + self.custom_config[key] = value + #Send this to the client. + + def add_state(self, packet:FSNETCMD_AIRPLANESTATE): + """Adds the state of the aircraft""" + if packet.player_id != self.id: + return None + self.prev_life = self.life + self.life = packet.life + self.set_position(packet.position) + self.set_attitude(packet.atti) + self.last_packet = packet + return packet + + def check_command(self,command:FSNETCMD_AIRCMD): + """Checks the command""" + if command.aircraft_id != self.id: + return + if command.command: + self.initial_config[command.command[0]] = command.command[1] + print(f"Command: {command.command}") diff --git a/lib/PacketManager/PacketManager.py b/lib/PacketManager/PacketManager.py index f019369..489b46a 100644 --- a/lib/PacketManager/PacketManager.py +++ b/lib/PacketManager/PacketManager.py @@ -1,5 +1,5 @@ from struct import unpack, pack -from PacketManager.packets import MESSAGE_TYPES, FSWEAPON_DICT, GUIDEDWEAPONS +from lib.PacketManager.packets.constants import MESSAGE_TYPES, FSWEAPON_DICT, GUIDEDWEAPONS class PacketManager: @@ -9,4 +9,6 @@ class PacketManager: def get_packet_type(self, data: bytes): #Returns the message type of that packet. + if len(data) < 4: + return None return MESSAGE_TYPES[unpack("> 8) & 255 # bitshift 8 to the right, #then mask with 255 if self.flags["smoke"] == 0: self.flags["smoke"] = 255 # Need to review what this actuall does! + if flags & 16: self.flags["beacon"] = True if flags & 32: @@ -133,14 +137,15 @@ class FSNETCMD_AIRPLANESTATE: #11 else: self.position = list(unpack("fff", self.buffer[16:28])) - self.atti = list(map(lambda x: x / (pi / 32768.0), - unpack("hhh", self.buffer[28:34]))) + self.atti = list(map(lambda x: x * (pi / 32768.0), + unpack("HHH", self.buffer[28:34]))) + self.velocity = list(map(lambda x: x/10, - unpack("hhh", self.buffer[34:40]))) + unpack("HHH", self.buffer[34:40]))) self.atti_velocity = list(map(lambda x: x / (pi / 32768.0), - unpack("hhh", self.buffer[40:46]))) + unpack("HHH", self.buffer[40:46]))) self.g_value = unpack("h", self.buffer[46:48])[0]/100.0 self.gun_ammo, self.aam, self.agm, self.bomb, self.smoke_oil = unpack("hhhhh", self.buffer[48:58]) @@ -183,6 +188,36 @@ class FSNETCMD_AIRPLANESTATE: #11 self.thrust_vector["reverser"] = unpack("B", self.buffer[96:97])[0]/255.0 self.bomb_bay_info = unpack("B", self.buffer[97:98])[0]/255.0 + def smoke(self): + if self.packet_version == 4 or self.packet_version == 5: + flag = unpack('h',self.buffer[56:58])[0] + flag &= ~((1<<8)|2) + flag |= (1<<8) |2 + flag |= (1<<9) + flag |= (1<<10) + packet = self.buffer[:56] + pack('h',flag) + self.buffer[58:] + return pack('I',len(packet)) + packet + else: + flag = unpack('h',self.buffer[74:75])[0] + + flag &= ~((255<<8)|2) + flag |= (255<<8) | 2 + print(flag) + packet = self.buffer[:74] + pack('h',flag) + self.buffer[76:] + return pack('I',len(packet)) + packet + + def stop_firing(self): + if self.packet_version == 4 or self.packet_version == 5: + flag = unpack('h',self.buffer[56:58])[0] + flag &= ~(8) + packet = self.buffer[:56] + pack('h',flag) + self.buffer[58:] + return pack('I',len(packet)) + packet + else: + flag = unpack('h',self.buffer[74:75])[0] + flag &= ~(8) + packet = self.buffer[:74] + pack('h',flag) + self.buffer[76:] + return pack('I',len(packet)) + packet + @staticmethod def get_life(buffer:bytes): version = unpack("h", buffer[12:14])[0] diff --git a/lib/PacketManager/packets/FSNETCMD_MISSILELAUNCH.py b/lib/PacketManager/packets/FSNETCMD_MISSILELAUNCH.py index 4059773..ad03128 100644 --- a/lib/PacketManager/packets/FSNETCMD_MISSILELAUNCH.py +++ b/lib/PacketManager/packets/FSNETCMD_MISSILELAUNCH.py @@ -1,5 +1,8 @@ from struct import pack, unpack from .constants import FSWEAPON_DICT, GUIDEDWEAPONS +from lib.Aircraft import Aircraft +from math import pi +import random class FSNETCMD_MISSILELAUNCH: #20 """ @@ -24,33 +27,52 @@ class FSNETCMD_MISSILELAUNCH: #20 self.decode() def decode(self): + print(self.buffer) + # _ = unpack("I", self.buffer[:4])[0] #Packet type + # IH # 6 + # fff # 12 + # fff # 12 + # ffH #10 + # II # 8 self.weapon_type = unpack("H", self.buffer[4:6])[0] self.position = list(unpack("fff", self.buffer[6:18])) self.atti = list(unpack("fff", self.buffer[18:30])) - self.velocity, self.life_remaining, self.power = unpack("ffH", self.buffer[30:38]) - self.fired_by_aircraft = bool(unpack("I", self.buffer[38:42])[0]) - self.fired_by = unpack("I", self.buffer[42:46])[0] + self.velocity, self.life_remaining, self.power = unpack("ffH", self.buffer[30:40]) + self.fired_by_aircraft = unpack("I", self.buffer[40:44])[0] + self.fired_by = unpack("I", self.buffer[44:48])[0] if self.weapon_type in FSWEAPON_DICT: self.weapon_type = FSWEAPON_DICT[self.weapon_type] if self.weapon_type in GUIDEDWEAPONS: - self.v_max, self.mobility, self.radar = unpack("fff", self.buffer[46:58]) - self.fired_at_aircraft = bool(unpack("I", self.buffer[58:62])[0]) - self.fired_at = unpack("I", self.buffer[62:66])[0] + self.v_max, self.mobility, self.radar = unpack("fff", self.buffer[48:60]) + self.fired_at_aircraft = bool(unpack("I", self.buffer[60:64])[0]) + self.fired_at = unpack("I", self.buffer[64:68])[0] elif self.weapon_type == "FSWEAPON_FLARE": - self.v_max = unpack("f", self.buffer[46:50])[0] + self.v_max = unpack("f", self.buffer[48:52])[0] + + @staticmethod def encode(weapon_type, position, atti, velocity, life_remaining, power, - fired_by_aircraft, fired_by, v_max=None, mobility=None, - radar=None, fired_at_aircraft=None, fired_at=None, with_size:bool=False): + fired_by_aircraft, fired_by, v_max=1000, mobility=0, + radar=0, fired_at_aircraft=False, fired_at=0, with_size:bool=False): if weapon_type in FSWEAPON_DICT and isinstance(weapon_type,int): weapon_type_name = FSWEAPON_DICT[weapon_type] else: weapon_type_name = weapon_type weapon_type = list(FSWEAPON_DICT.keys())[list(FSWEAPON_DICT.values()).index(weapon_type)] - buffer = pack("I",20)+pack("Hfff", weapon_type, *position)+pack("fff", *atti)+pack("ffH", velocity, life_remaining, power) - buffer += pack("I",fired_by_aircraft)+pack("I",fired_by) + buffer = pack("I",20) #Packet type 0:4 + + buffer += pack("H", weapon_type) #Weapon type 4:6 + buffer += pack("f", position[0]) #6:10 + buffer += pack("f", position[1]) #10:14 + buffer += pack("f", position[2]) #Position #14:18 + buffer += pack("f", atti[0]) #18:22 + buffer += pack("f", atti[1]) #22:26 + buffer += pack("f", atti[2]) #Attitude #26:30 + buffer += pack("ffH", velocity, life_remaining, power) #Velocity, life remaining, power #30:40 + buffer += pack("II",fired_by_aircraft,fired_by) #Fired by aircraft, fired by #40:48 + print(buffer) if weapon_type_name in GUIDEDWEAPONS: buffer += pack("fff", v_max, mobility, radar) if isinstance(fired_at_aircraft, bool): @@ -61,4 +83,15 @@ class FSNETCMD_MISSILELAUNCH: #20 if with_size: return pack("I",len(buffer))+buffer - return buffer \ No newline at end of file + return buffer + + @staticmethod + def drop_bombs(aircraft:Aircraft): + position = aircraft.position + atti = aircraft.attitude + # atti = [(value*(32768/ pi)) for value in atti] + atti[2] =0 + weapon_type = random.randint(0,13) + packet = FSNETCMD_MISSILELAUNCH.encode(weapon_type, position=position, atti=atti, velocity=20, life_remaining=30000, power=999, fired_by_aircraft=0, fired_by=aircraft.id, v_max=1000, with_size=True) + print(packet) + return packet \ No newline at end of file diff --git a/lib/PacketManager/packets/FSNETCMD_TEXTMESSAGE.py b/lib/PacketManager/packets/FSNETCMD_TEXTMESSAGE.py index 4ff987d..f524b9f 100644 --- a/lib/PacketManager/packets/FSNETCMD_TEXTMESSAGE.py +++ b/lib/PacketManager/packets/FSNETCMD_TEXTMESSAGE.py @@ -18,7 +18,7 @@ class FSNETCMD_TEXTMESSAGE: #32 @staticmethod def encode(message:str, with_size:bool=False): - buffer = pack("I",32)+message.encode("utf-8")+b"\x00" + buffer = pack("III",32,0,0)+message.encode("utf-8")+b"\x00" if with_size: return pack("I",len(buffer))+buffer return buffer diff --git a/lib/PacketManager/packets/FSNETCMD_WEAPONCONFIG.py b/lib/PacketManager/packets/FSNETCMD_WEAPONCONFIG.py index b6acf82..aa4876b 100644 --- a/lib/PacketManager/packets/FSNETCMD_WEAPONCONFIG.py +++ b/lib/PacketManager/packets/FSNETCMD_WEAPONCONFIG.py @@ -52,4 +52,4 @@ class FSNETCMD_WEAPONCONFIG: @staticmethod def addSmoke(aircraft_id:int): - return FSNETCMD_WEAPONCONFIG.encode(aircraft_id, {32:[66,66,66]}, True) + return FSNETCMD_WEAPONCONFIG.encode(aircraft_id, {32:[66,66,66],33:[66,66,66],34:[66,66,66]}, True) diff --git a/lib/Player.py b/lib/Player.py new file mode 100644 index 0000000..be49746 --- /dev/null +++ b/lib/Player.py @@ -0,0 +1,35 @@ +from lib.Aircraft import Aircraft +from lib.PacketManager.packets import FSNETCMD_LOGON, FSNETCMD_ADDOBJECT +class Player: + """ + A player class, this will hold info about the client, including which aircraft they're flying""" + def __init__(self, server_messages, client_messages): + + self.username = "" + self.alias = "" + self.aircraft = Aircraft() + self.version = 0 + self.ip = "" + + def set_aircraft(self, aircraft:Aircraft): + self.aircraft = aircraft + + def login(self, packet:FSNETCMD_LOGON): + self.username = packet.username + self.alias = packet.alias + self.version = packet.version + + def set_ip(self, ip): + self.ip = ip + + def check_add_object(self, packet:FSNETCMD_ADDOBJECT): + if packet.pilot == self.username: + self.aircraft = Aircraft() + self.aircraft.name = packet.identifier + self.aircraft.id = packet.object_id + self.aircraft.set_position(packet.pos) + self.aircraft.set_initial_config({ + "IFF": packet.iff + }) + return True + return False \ No newline at end of file -- cgit v1.2.3