diff options
| author | Skipper <[email protected]> | 2025-02-14 21:47:55 +0000 |
|---|---|---|
| committer | Skipper <[email protected]> | 2025-02-14 21:47:55 +0000 |
| commit | 17ad19c30478bb9361cb872d4e9bd4cd424edf49 (patch) | |
| tree | 2825197d40c3f1788322661887425b501a2898e7 | |
| parent | f664470829ea834de36194a311f08f691005ee01 (diff) | |
Added custom aircraft list plugin
| -rw-r--r-- | lib/PacketManager/packets/FSNETCMD_LIST.py | 70 | ||||
| -rw-r--r-- | lib/PacketManager/packets/__init__.py | 4 | ||||
| -rw-r--r-- | plugins/custom_aircraft_list/Plugin.py | 44 | ||||
| -rw-r--r-- | plugins/custom_aircraft_list/__init__.py | 2 | ||||
| -rw-r--r-- | plugins/custom_aircraft_list/custom_list.json | 14 | ||||
| -rw-r--r-- | proxy.py | 10 |
6 files changed, 142 insertions, 2 deletions
diff --git a/lib/PacketManager/packets/FSNETCMD_LIST.py b/lib/PacketManager/packets/FSNETCMD_LIST.py new file mode 100644 index 0000000..d6cb83c --- /dev/null +++ b/lib/PacketManager/packets/FSNETCMD_LIST.py @@ -0,0 +1,70 @@ +from struct import unpack, pack +class FSNETCMD_LIST: #44 + def __init__(self, buffer:bytes, should_decode:bool=True): + self.buffer = buffer + self.list_type = None + self.num_of_items = 0 + self.list = [] + if should_decode: + self.decode() + + def decode(self): + packet_type = unpack('I', self.buffer[:4])[0] + self.list_type = unpack('B', self.buffer[4:5])[0] + self.num_of_items = unpack('B', self.buffer[5:6])[0] + #Then there is a spacer. + _ = unpack('BB', self.buffer[6:8]) + self.list = self.buffer[8:].split(b'\x00')[:-1] + + @staticmethod + def encode(list_type:int=1, list_buffer:bytes=b'', num_of_items:int=0, with_size:bool=False): + #Max length of the packet is 1024 bytes. + # 8+1 bytes for the header, leaving 1015 bytes for the list. + buffer = pack('IBBBB', 44, list_type, num_of_items, 0, 0) + buffer += list_buffer + if with_size: + return pack("I", len(buffer)) + buffer + return buffer + + +class List_Constructor: + """Takes a list of aircraft, and constructes a list of FSNETCMD_LIST packets for sending. + If sending custom lists to clients, the client FSNETCMD_LIST reply must be blocked from the server + and the server FSNETCMD_LIST command must also be blocked. + """ + def __init__(self, aircraftList:list, with_size:bool=True): + self.aircraftList = aircraftList + self.packet_list = [] + self.num_of_packets = 0 + self.with_size = with_size + self.construct_packets() + + def construct_packets(self): + packet = b'' + packet_length = 0 + for aircraft in self.aircraftList: + aircraft = aircraft.replace(' ', '_') + aircraft = aircraft.encode() + b'\x00' + if self.check_fit(packet, aircraft) and packet_length<32: + packet += aircraft + packet_length += 1 + else: + packet = FSNETCMD_LIST.encode(1,packet, packet_length,self.with_size) + self.packet_list.append(packet) + packet = b'' + packet += aircraft + self.num_of_packets += 1 + packet_length = 1 + #Append whatever is left over. + if len(packet) > 0: + packet = FSNETCMD_LIST.encode(1,packet, packet_length,self.with_size) + self.packet_list.append(packet) + self.num_of_packets += 1 + + def check_fit(self, packet, aircraft): + if len(packet) + len(aircraft) + 1 > 1015: + return False + return True + + def get_packets(self): + return self.packet_list diff --git a/lib/PacketManager/packets/__init__.py b/lib/PacketManager/packets/__init__.py index 250be0d..1139ab5 100644 --- a/lib/PacketManager/packets/__init__.py +++ b/lib/PacketManager/packets/__init__.py @@ -41,7 +41,7 @@ from .FSNETCMD_WEAPONCONFIG import FSNETCMD_WEAPONCONFIG #from .FSNETCMD_CTRLSHOWUSERNAME import FSNETCMD_CTRLSHOWUSERNAME #from .FSNETCMD_CONFIRMEXISTENCE import FSNETCMD_CONFIRMEXISTENCE #from .FSNETCMD_CONFIGSTRING import FSNETCMD_CONFIGSTRING -#from .FSNETCMD_LIST import FSNETCMD_LIST +from .FSNETCMD_LIST import FSNETCMD_LIST, List_Constructor #from .FSNETCMD_GNDCMD import FSNETCMD_GNDCMD #from .FSNETCMD_REPORTSCORE import FSNETCMD_REPORTSCORE #from .FSNETCMD_SERVER_FORCE_JOIN import FSNETCMD_SERVER_FORCE_JOIN @@ -64,4 +64,4 @@ __all__ = ["FSNETCMD_LOGON", "FSNETCMD_LOGOFF", "FSNETCMD_ERROR", "FSNETCMD_MISSILELAUNCH", "FSNETCMD_GETDAMAGE", "FSNETCMD_WEAPONCONFIG", "FSNETCMD_AIRCMD", "FSNETCMD_TEXTMESSAGE", "FSNETCMD_ENVIRONMENT", - "FSNETCMD_SKYCOLOR", "FSNETCMD_FOGCOLOR"] + "FSNETCMD_SKYCOLOR", "FSNETCMD_FOGCOLOR", "FSNETCMD_LIST", "List_Constructor"] diff --git a/plugins/custom_aircraft_list/Plugin.py b/plugins/custom_aircraft_list/Plugin.py new file mode 100644 index 0000000..b96920f --- /dev/null +++ b/plugins/custom_aircraft_list/Plugin.py @@ -0,0 +1,44 @@ +"""TThis plugin will cause the aircraft to emit smoke if it's health is below a certain threshold. +It is also an example of a plugin as a folder/module. +This can be used as a basis for more complex plugins that may need multiple files.""" +from lib.PacketManager.packets import List_Constructor +from json import load +from struct import pack +from logging import error +ENABLED = True +custom_list_file = "plugins\\custom_aircraft_list\\custom_list.json" + +class Plugin: + def __init__(self): + self.plugin_manager = None + self.aircraft_list = [] + + def register(self, plugin_manager): + self.plugin_manager = plugin_manager + with open(custom_list_file, 'r', encoding='utf-8') as f: + json_file = load(f) + if isinstance(json_file,list): + self.aircraft_list = json_file + else: + error(f"Invalid JSON file {custom_list_file}. Must be a list of aircraft.") + self.plugin_manager.register_hook('on_list', self.on_list) + self.plugin_manager.register_hook('on_list_server', self.on_list_server) + + def on_list(self, packet, player, message_to_client, message_to_server): + if ENABLED: + return False + return True + + def on_list_server(self, packet, player, message_to_client, message_to_server): + if ENABLED: + #Send the packet straight back to the server, and prevent it being passed to the client. + packet = pack("I",len(packet)) + packet + message_to_server.append(packet) + if not hasattr(player, 'custom_packet_sent'): + player.custom_packet_sent=True + #Send the custom list packets. + lc = List_Constructor(self.aircraft_list).get_packets() + for packet in lc: + message_to_client.append(packet) + return False + return True diff --git a/plugins/custom_aircraft_list/__init__.py b/plugins/custom_aircraft_list/__init__.py new file mode 100644 index 0000000..425d2ad --- /dev/null +++ b/plugins/custom_aircraft_list/__init__.py @@ -0,0 +1,2 @@ +from .Plugin import Plugin +from .Plugin import ENABLED
\ No newline at end of file diff --git a/plugins/custom_aircraft_list/custom_list.json b/plugins/custom_aircraft_list/custom_list.json new file mode 100644 index 0000000..987350d --- /dev/null +++ b/plugins/custom_aircraft_list/custom_list.json @@ -0,0 +1,14 @@ +[ + "AIRBUS300", + "AIRBUS320", + "B737", + "B747", + "B767", + "B777", + "CONCORDE", + "DIAMOND_ECLIPSE", + "PIPER_ARCHER(WASHIN-AIR_MARKING)", + "T-400", + "U-125", + "U-125A" +] @@ -82,6 +82,7 @@ async def handle_client(client_reader, client_writer): try: #Test if there are any unsent messages to the client or # server from other processes. + keep_message = True # Reset this before each loop. if len(message_to_client) > 0: client_writer.write(message_to_client.pop(0)) await client_writer.drain() @@ -162,6 +163,10 @@ async def handle_client(client_reader, client_writer): if DISCORD_ENABLED: # Make it non blocking! asyncio.create_task(discord_send_message(CHANNEL_ID, finalMsg)) + elif packet_type == "FSNETCMD_LIST": + keep_message = plugin_manager.triggar_hook('on_list', packet, player, message_to_client, message_to_server) + if not keep_message: + data = None except Exception as e: warning(f"Error parsing flight data: {e}", exc_info=True) @@ -196,6 +201,11 @@ async def handle_client(client_reader, client_writer): if not keep_message: data = None + elif packet_type == "FSNETCMD_LIST": + keep_message = plugin_manager.triggar_hook('on_list_server', packet, player, message_to_client, message_to_server) + if not keep_message: + data = None + # Forward the packet to the other endpoint if the data packet still exists. if data: writer.write(data) |
