aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRitabrata Das <[email protected]>2025-02-11 11:17:07 +0530
committerRitabrata Das <[email protected]>2025-02-11 11:17:07 +0530
commit0a2325598f27d559b583ae37a8586d2d7552d6f9 (patch)
tree36b751c60ea58577bcf6a0caac9d7457b49712d1
parentde594e15c4a2abbdbd76a27d735dc71611d71666 (diff)
Add Smoke, Engine Breakdown, Made sure non-ab planes do not get ab after repairs
-rw-r--r--.gitignore1
-rw-r--r--config.py4
-rw-r--r--lib/Aircraft.py5
-rw-r--r--lib/PacketManager/packets/FSNETCMD_AIRCMD.py2
-rw-r--r--lib/PacketManager/packets/FSNETCMD_AIRPLANESTATE.py12
-rw-r--r--proxy.py85
6 files changed, 84 insertions, 25 deletions
diff --git a/.gitignore b/.gitignore
index 35e3958..509d35b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@ __pycache__/
lib/__pycache__/
venv/
flightPacketParser.ipynb
+config.py
diff --git a/config.py b/config.py
index 37c8edc..321b133 100644
--- a/config.py
+++ b/config.py
@@ -8,9 +8,9 @@ LOGGING_LEVEL = INFO
# Server Configuration
# Replace with the YSFlight server address
SERVER_HOST = "127.0.0.1"
-SERVER_PORT = 7914 # Please put where the normal YSFlight server is running
+SERVER_PORT = 7915 # Please put where the normal YSFlight server is running
# Port for the proxy server
-PROXY_PORT = 7915
+PROXY_PORT = 9000
# Welcome Message to the playe
# For formatting use {username}
diff --git a/lib/Aircraft.py b/lib/Aircraft.py
index 2672621..ecbecff 100644
--- a/lib/Aircraft.py
+++ b/lib/Aircraft.py
@@ -1,4 +1,5 @@
-from lib.PacketManager.packets import FSNETCMD_AIRPLANESTATE, FSNETCMD_AIRCMD
+from lib.PacketManager.packets import FSNETCMD_AIRPLANESTATE
+from lib.PacketManager.packets.FSNETCMD_AIRCMD import FSNETCMD_AIRCMD
from logging import debug
class Aircraft:
@@ -16,6 +17,7 @@ class Aircraft:
self.id = -1
self.last_packet = None
self.damage_engine_warn_sent = False
+ self.just_repaired = False
def reset(self):
"""Resets the aircraft"""
@@ -29,6 +31,7 @@ class Aircraft:
self.id = -1
self.last_packet = None
self.damage_engine_warn_sent = False
+ self.just_repaired = False
def set_position(self, position:list):
"""Sets the position of the aircraft from the Airplane state packet"""
diff --git a/lib/PacketManager/packets/FSNETCMD_AIRCMD.py b/lib/PacketManager/packets/FSNETCMD_AIRCMD.py
index 50a9228..6770079 100644
--- a/lib/PacketManager/packets/FSNETCMD_AIRCMD.py
+++ b/lib/PacketManager/packets/FSNETCMD_AIRCMD.py
@@ -53,7 +53,7 @@ class FSNETCMD_AIRCMD: #30
return FSNETCMD_AIRCMD.encode(aircraft_id, message, with_size)
@staticmethod
- def set_command(aircraft_id:int, command:str, value:int, with_size:bool=False):
+ def set_command(aircraft_id:int, command:str, value:int|str, with_size:bool=False):
"""
This will set the command of the aircraft, useful if you want to
set the engine power, fuel, etc.
diff --git a/lib/PacketManager/packets/FSNETCMD_AIRPLANESTATE.py b/lib/PacketManager/packets/FSNETCMD_AIRPLANESTATE.py
index 2282367..3ebf8d6 100644
--- a/lib/PacketManager/packets/FSNETCMD_AIRPLANESTATE.py
+++ b/lib/PacketManager/packets/FSNETCMD_AIRPLANESTATE.py
@@ -299,3 +299,15 @@ class FSNETCMD_AIRPLANESTATE: #11
if with_size:
return pack("I",len(buffer))+buffer
return buffer
+
+ def __str__(self):
+ return f"Player ID : {self.player_id}; Remote Time : {self.remote_time}; \
+ Position : {self.position}; Attitude : {self.atti}; Velocity : {self.velocity}; \
+ Attitude Velocity : {self.atti_velocity}; Smoke Oil : {self.smoke_oil}; Fuel : {self.fuel}; \
+ Payload : {self.payload}; Flight State : {self.flight_state}; VGW : {self.vgw}; \
+ Spoiler : {self.spoiler}; Landing Gear : {self.landing_gear}; Flap : {self.flap}; \
+ Brake : {self.brake}; Flags : {self.flags}; Gun Ammo : {self.gun_ammo}; \
+ Rocket Ammo : {self.rocket_ammo}; AAM : {self.aam}; AGM : {self.agm}; Bomb : {self.bomb}; \
+ Life : {self.life}; G Value : {self.g_value}; Throttle : {self.throttle}; Elev : {self.elev}; \
+ Ail : {self.ail}; Rud : {self.rud}; Trim : {self.trim}; Thrust Vector : {self.thrust_vector}; \
+ Bomb Bay Info : {self.bomb_bay_info}"
diff --git a/proxy.py b/proxy.py
index 552c34f..f600a22 100644
--- a/proxy.py
+++ b/proxy.py
@@ -12,18 +12,39 @@ from lib.PacketManager.packets import *
import logging
from logging import critical, warning, info, debug
from config import *
-from time import sleep
# Configuration
SERVER_HOST = SERVER_HOST
SERVER_PORT = SERVER_PORT
PROXY_PORT = PROXY_PORT
-CONNECTED_PLAYERS = [] # List of connected players
+
+# ANSI escape codes for colors
+COLORS = {
+ "DEBUG": "\033[92m", # Green
+ "INFO": "\033[94m", # Blue
+ "WARNING": "\033[93m", # Yellow
+ "ERROR": "\033[91m", # Red
+ "CRITICAL": "\033[91;1m", # Bold Red
+ "RESET": "\033[0m" # Reset color
+}
+
+class ColoredFormatter(logging.Formatter):
+ def format(self, record):
+ log_color = COLORS.get(record.levelname, COLORS["RESET"])
+ reset = COLORS["RESET"]
+ log_message = f"{log_color}{record.levelname}: {record.getMessage()}{reset}"
+ return log_message
+
logging.basicConfig(level=LOGGING_LEVEL)
+# Get the default handler and set the colored formatter
+handler = logging.getLogger().handlers[0]
+handler.setFormatter(ColoredFormatter("%(levelname)s: %(message)c"))
+
info("Welcome to Sakuya AC")
-info("Perfect and Elegant Proxy for your Ysflight Server")
+info("Perfect and Elegant Proxy for your YSFlight Server")
info("Lisenced under GPLv3")
+info("Press CTRL+C to stop the proxy")
# Handle client connections
async def handle_client(client_reader, client_writer):
@@ -55,7 +76,16 @@ async def handle_client(client_reader, client_writer):
await server_writer.drain()
if not reader.at_eof(): # Connection closed
- header = await reader.readexactly(4) # Ensures we always get 4 bytes
+ try:
+ header = await reader.readexactly(4) # Ensures we always get 4 bytes
+ except asyncio.IncompleteReadError:
+ break
+ except ConnectionResetError:
+ break
+ except Exception as e:
+ critical(f"Error reading header: {e}")
+ break
+
if not header:
break # Connection closed
@@ -76,17 +106,18 @@ async def handle_client(client_reader, client_writer):
if packet_type == "FSNETCMD_LOGON":
player.login(FSNETCMD_LOGON(packet))
+ if player.version != YSF_VERSION and VIA_VERSION:
+ info(f"ViaVersion enabled : Porting {player.username} from {player.version} to {YSF_VERSION}")
+ message_to_server.append(YSchat.message(f"Porting you to YSFlight {YSF_VERSION}, This is currently Experimental"))
+ message_to_server.append(YSchat.message(f"Please report any bugs to the server admin or join with the correct version"))
+ data = YSviaversion.genViaVersion(player.username, YSF_VERSION)
+ writer.write(data)
+ continue
elif packet_type == "FSNETCMD_AIRPLANESTATE":
- # print("Damaging!")
- # damageData = FSNETCMD_GETDAMAGE.encode(player.aircraft.id, 1, 1, player.aircraft.id, 1, 11, 0, True)
- # print("custom", damageData)
- # message_to_server.append(damageData)
- # message_to_client.append(damageData)
-
packet = player.aircraft.add_state(FSNETCMD_AIRPLANESTATE(packet))
- if player.aircraft.last_packet.g_value > G_LIM:
+ if abs(player.aircraft.last_packet.g_value) > G_LIM:
debug("G Value exceeded : ", player.aircraft.last_packet.g_value)
# We make a packet which damages the aircraft using the same pilot ID, using a gun
damageData = FSNETCMD_GETDAMAGE.encode(player.aircraft.id, 1, 1, player.aircraft.id, 1, 11, 0, True)
@@ -94,16 +125,17 @@ async def handle_client(client_reader, client_writer):
message_to_client.append(damageData)
message_to_client.append(warnMsg)
- prev_life = player.aircraft.prev_life
if player.aircraft.life == -1: #Uninitialised
- player.aircraft.life = prev_life
+ player.aircraft.prev_life = player.aircraft.life
- elif prev_life > player.aircraft.life:
+ elif player.aircraft.prev_life < player.aircraft.life and player.aircraft.prev_life != -1 and not player.aircraft.just_repaired:
cheatingMsg = YSchat.message(f"{HEALTH_HACK_MESSAGE} by {player.username}")
- message_to_client.append(cheatingMsg)
+ warning(f"Health hack detected for {player.username}, Connected from {player.ip}")
+ message_to_server.append(cheatingMsg)
elif player.aircraft.life < SMOKE_LIFE and SMOKE_PLANE:
-
+ # We patch the packet to have smoke forcefully
+ data = FSNETCMD_AIRPLANESTATE(data[4:]).smoke()
if not player.aircraft.damage_engine_warn_sent:
warningMsg = YSchat.message(f"Your engine has been damaged! You can't turn on afterburner")
debug(f"Sending warning to {player.username}")
@@ -111,11 +143,17 @@ async def handle_client(client_reader, client_writer):
player.aircraft.damage_engine_warn_sent = True
message_to_client.append(FSNETCMD_AIRCMD.set_afterburner(player.aircraft.id, False, True))
- player.aircraft.life = prev_life
+ player.aircraft.prev_life = player.aircraft.life
+ player.aircraft.just_repaired = False
elif packet_type == "FSNETCMD_UNJOIN":
player.aircraft.reset()
+ elif packet_type == "FSNETCMD_WEAPONCONFIG":
+ player.aircraft.just_repaired = True
+ if player.aircraft.get_initial_config_value("AFTBURNR") == "TRUE": message_to_client.append(player.aircraft.set_afterburner(True))
+ debug("Aircraft repaired!")
+
# elif packet_type == "FSNETCMD_GETDAMAGE":
# h = FSNETCMD_GETDAMAGE(packet, True)
@@ -237,7 +275,7 @@ async def handle_client(client_reader, client_writer):
writer.write(data)
await writer.drain()
except (asyncio.CancelledError, ConnectionResetError, BrokenPipeError) as e:
- if e == BrokenPipeError:
+ 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}")
@@ -249,13 +287,15 @@ async def handle_client(client_reader, client_writer):
forward(server_reader, client_writer, "server_to_client"),
)
except (asyncio.CancelledError, ConnectionResetError, BrokenPipeError) as e:
- critical(f"Connection error: {e}")
+ if not isinstance(e, BrokenPipeError):
+ critical(f"Connection error: {e}")
finally:
try:
client_writer.close()
await client_writer.wait_closed()
except Exception as e:
- critical(f"Error closing client connection: {e}")
+ if not isinstance(e, BrokenPipeError):
+ critical(f"Error closing client connection: {e}")
# Start the proxy server
@@ -267,4 +307,7 @@ async def start_proxy():
if __name__ == "__main__":
- asyncio.run(start_proxy())
+ try:
+ asyncio.run(start_proxy())
+ except KeyboardInterrupt:
+ info("Goodbye!")