diff options
| author | Ritabrata Das <[email protected]> | 2025-03-02 11:14:16 +0530 |
|---|---|---|
| committer | Ritabrata Das <[email protected]> | 2025-03-02 11:14:16 +0530 |
| commit | 520853a8a659f0dc296f0d5fb301913cbee37688 (patch) | |
| tree | 8a0200d1d22ca9d6828ceaec7129cb3efbf347c6 | |
| parent | 30c7e24aa8de762a1b8c21476e9e8436db1b9826 (diff) | |
handle client exits gracefully and improve plugin manager
| -rw-r--r-- | lib/Player.py | 1 | ||||
| -rw-r--r-- | lib/discordSync.py | 2 | ||||
| -rw-r--r-- | lib/plugin_manager.py | 17 | ||||
| -rw-r--r-- | plugins/chat_weather_setter.py | 8 | ||||
| -rw-r--r-- | plugins/refuel.py | 5 | ||||
| -rw-r--r-- | proxy.py | 44 |
6 files changed, 55 insertions, 22 deletions
diff --git a/lib/Player.py b/lib/Player.py index 8e2250a..cfd50a8 100644 --- a/lib/Player.py +++ b/lib/Player.py @@ -13,6 +13,7 @@ class Player: self.streamWriterObject = streamWriterObject self.is_a_bot = True # We check if they are still present after LOGIN packet, then they're not a bot self.iff = 1 + self.connection_closed = False def set_aircraft(self, aircraft:Aircraft): self.aircraft = aircraft diff --git a/lib/discordSync.py b/lib/discordSync.py index 0a8e8be..770543e 100644 --- a/lib/discordSync.py +++ b/lib/discordSync.py @@ -84,8 +84,6 @@ async def monitor_channel(channel_id, playerList:list): encoded_msg = txtMsgr.encode(f"[Discord] {message['author']['username']}: {message['content']}", True) for player in playerList: if player.streamWriterObject.is_closing(): - if not player.is_a_bot: - asyncio.create_task(discord_send_message(channel_id, f"{player.username} has left the server!")) playerList.remove(player) # Remove disconnected players continue player.streamWriterObject.write(encoded_msg) diff --git a/lib/plugin_manager.py b/lib/plugin_manager.py index 52fb1f7..5cc93d2 100644 --- a/lib/plugin_manager.py +++ b/lib/plugin_manager.py @@ -45,13 +45,24 @@ class PluginManager: self.hooks[hook_name] = [] self.hooks[hook_name].append(callback) - def register_command(self, command_name, callback): - """Registers the command with the plugin manager""" + def register_command(self, command_name, callback, help_text="No Description", alias:str=None): + """Registers the command with the plugin manager + Set help text to help users understand what your command does. + """ if command_name in self.commands: warning(f"Command {command_name} already registered, Ignoring this registration") else: self.commands[command_name] = callback - self.help_message = self.help_message + f"/{command_name}\n" + if alias == None: + self.help_message = self.help_message + f"/{command_name} : {help_text}\n" + if alias != None: + if alias in self.commands: + warning(f"Command {alias} already registered, Ignoring this registration") + else: + self.commands[alias] = callback + self.help_message = self.help_message + f"/{command_name} [{alias}] : {help_text}\n" + + def triggar_hook(self, hook_name, data, *args, **kwargs): """Triggars the callbacks for the hook. diff --git a/plugins/chat_weather_setter.py b/plugins/chat_weather_setter.py index 5b31a38..675bac5 100644 --- a/plugins/chat_weather_setter.py +++ b/plugins/chat_weather_setter.py @@ -13,10 +13,10 @@ class Plugin: self.plugin_manager = plugin_manager #self.plugin_manager.register_hook('on_chat', self.on_chat) self.plugin_manager.register_hook('on_environment_server', self.on_environment) - self.plugin_manager.register_command('fog', self.fog) - self.plugin_manager.register_command('sky', self.sky) - self.plugin_manager.register_command('time', self.time) - self.plugin_manager.register_command('vis', self.visibility) + self.plugin_manager.register_command('fog', self.fog, "Sets fog color. Usage : /fog r,g,b") + self.plugin_manager.register_command('sky', self.sky, "Sets sky color. Usage : /sky r,g,b") + self.plugin_manager.register_command('time', self.time, "Sets time. Usage : /time <day|night>") + self.plugin_manager.register_command('visibility', self.visibility, "Sets Visibilty : /vis <visibilty in meters>", "vis") def fog(self, full_message, player, message_to_client, message_to_server): try: diff --git a/plugins/refuel.py b/plugins/refuel.py index ff96699..cde2e03 100644 --- a/plugins/refuel.py +++ b/plugins/refuel.py @@ -1,6 +1,7 @@ """ This plugin enables you to perform air to air refueling. """ +from ast import alias import math from lib.PacketManager.packets import FSNETCMD_AIRCMD, FSNETCMD_AIRPLANESTATE from lib import YSchat @@ -21,8 +22,8 @@ class Plugin: def register(self, plugin_manager): self.plugin_manager = plugin_manager - self.plugin_manager.register_command('refuel', self.refuel) - self.plugin_manager.register_command('refueler', self.refueler) + self.plugin_manager.register_command('refuel', self.refuel, "Allows you to get refuled", alias = "r") + self.plugin_manager.register_command('refueler', self.refueler, "Allows other players to refuel from you", alias = "rf") self.plugin_manager.register_hook('on_flight_data', self.on_flight_data) self.plugin_manager.register_hook('on_unjoin', self.on_unjoin) @@ -57,6 +57,14 @@ info("Press CTRL+C to stop the proxy") #Load the plugins plugin_manager = PluginManager() +# Close Connection +async def close_connection(client_writer, server_writer): + # if DISCORD_ENABLED: await discord_send_message(CHANNEL_ID, "has left the server!") + client_writer.close() + server_writer.close() + await client_writer.wait_closed() + await server_writer.wait_closed() + # Handle client connections async def handle_client(client_reader, client_writer): message_to_client = [] @@ -92,10 +100,13 @@ async def handle_client(client_reader, client_writer): try: header = await reader.readexactly(4) # Ensures we always get 4 bytes except asyncio.IncompleteReadError: + await close_connection(client_writer, server_writer) break except ConnectionResetError: + await close_connection(client_writer, server_writer) break except Exception as e: + await close_connection(client_writer, server_writer) critical(f"Error reading header: {e}") break @@ -107,6 +118,7 @@ async def handle_client(client_reader, client_writer): packet = await reader.read(length) if not packet: + await close_connection(client_writer, server_writer) break data = header + packet @@ -170,10 +182,10 @@ async def handle_client(client_reader, client_writer): data = None command = msg.message.split(" ")[0][1:] asyncio.create_task(triggerCommand.triggerCommand(command, msg.message, player, message_to_client, message_to_server, plugin_manager)) - - if DISCORD_ENABLED: - # Make it non blocking! - asyncio.create_task(discord_send_message(CHANNEL_ID, finalMsg)) + else: + 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) @@ -223,11 +235,13 @@ async def handle_client(client_reader, client_writer): writer.write(data) await writer.drain() except (asyncio.CancelledError, ConnectionResetError, BrokenPipeError) as e: - if e == BrokenPipeError or ConnectionResetError or asyncio.CancelledError: - info(f"Connection closed by {player.username} : {player.ip}") - else: - warning(f"Connection error during packet forwarding: {e}") - break + if not player.connection_closed: + await close_connection(client_writer, server_writer) + if e == BrokenPipeError or ConnectionResetError or asyncio.CancelledError: + info(f"Connection closed by {player.username} : {player.ip}") + else: + warning(f"Connection error during packet forwarding: {e}") + break # Start forwarding data between client and server await asyncio.gather( @@ -238,12 +252,20 @@ async def handle_client(client_reader, client_writer): if not isinstance(e, BrokenPipeError): critical(f"Connection error: {e}") finally: + """ try: - client_writer.close() - await client_writer.wait_closed() + #client_writer.close() + #await client_writer.wait_closed() + pass except Exception as e: if not isinstance(e, BrokenPipeError): critical(f"Error closing client connection: {e}") + """ + if not player.connection_closed: + player.connection_closed = True + if DISCORD_ENABLED : + await discord_send_message(CHANNEL_ID, f"{player.username} has left the server!") + await close_connection(client_writer, server_writer) # Start the proxy server |
