aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRitabrata Das <[email protected]>2025-03-02 11:14:16 +0530
committerRitabrata Das <[email protected]>2025-03-02 11:14:16 +0530
commit520853a8a659f0dc296f0d5fb301913cbee37688 (patch)
tree8a0200d1d22ca9d6828ceaec7129cb3efbf347c6
parent30c7e24aa8de762a1b8c21476e9e8436db1b9826 (diff)
handle client exits gracefully and improve plugin manager
-rw-r--r--lib/Player.py1
-rw-r--r--lib/discordSync.py2
-rw-r--r--lib/plugin_manager.py17
-rw-r--r--plugins/chat_weather_setter.py8
-rw-r--r--plugins/refuel.py5
-rw-r--r--proxy.py44
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)
diff --git a/proxy.py b/proxy.py
index d043b32..68bb6f7 100644
--- a/proxy.py
+++ b/proxy.py
@@ -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