aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRitabrata Das <[email protected]>2025-02-11 00:11:56 +0530
committerRitabrata Das <[email protected]>2025-02-11 00:11:56 +0530
commit3d29b59dae6b93c28c321c2df3cbc49d20d5661c (patch)
treed6348b5eeed358f2dad5a8e4dc2e66bafbbce1b5
parent2a0fc41e642228b10502ff83036cd79195ea92c0 (diff)
Work on G Limiter
-rw-r--r--.gitignore1
-rw-r--r--README.md7
-rw-r--r--config.py6
-rw-r--r--lib/Aircraft.py28
-rw-r--r--lib/PacketManager/packets/FSNETCMD_AIRCMD.py5
-rw-r--r--lib/PacketManager/packets/FSNETCMD_AIRPLANESTATE.py20
-rw-r--r--lib/PacketManager/packets/FSNETCMD_GETDAMAGE.py13
-rw-r--r--lib/Player.py5
-rw-r--r--proxy.py76
9 files changed, 106 insertions, 55 deletions
diff --git a/.gitignore b/.gitignore
index 509d35b..35e3958 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,3 @@ __pycache__/
lib/__pycache__/
venv/
flightPacketParser.ipynb
-config.py
diff --git a/README.md b/README.md
index b0bfba9..683e67f 100644
--- a/README.md
+++ b/README.md
@@ -16,6 +16,13 @@ Sakuya AC and G Limiter at 20. It also has all the experimental options turned o
---
+## Contributors
+
+- Skipper
+- Biry (Emotional Support)
+
+---
+
## **Features**
- Intercepts and parses network packets to monitor gameplay.
- Adds features like G Limiter and Smoke Emission on Death.
diff --git a/config.py b/config.py
index e9fb1fd..37c8edc 100644
--- a/config.py
+++ b/config.py
@@ -12,6 +12,12 @@ SERVER_PORT = 7914 # Please put where the normal YSFlight server is running
# Port for the proxy server
PROXY_PORT = 7915
+# Welcome Message to the playe
+# For formatting use {username}
+# eg. "Welcome {username} to the server!"
+# > Welcome Sakuya to the server!
+WELCOME_MESSAGE = "Welcome {username} to the server!"
+
# Native YSFlight Server
# Please select the YSFlight server version for the
# local ysflight server
diff --git a/lib/Aircraft.py b/lib/Aircraft.py
index 3b79947..215a1cb 100644
--- a/lib/Aircraft.py
+++ b/lib/Aircraft.py
@@ -1,4 +1,6 @@
from lib.PacketManager.packets import FSNETCMD_AIRPLANESTATE, FSNETCMD_AIRCMD
+from logging import debug
+
class Aircraft:
"""
An aircraft class - this will hold the info from the Airplane state, weapons etc packets."""
@@ -13,7 +15,8 @@ class Aircraft:
self.prev_life = -1
self.id = -1
self.last_packet = None
-
+ self.damage_engine_warn_sent = False
+
def reset(self):
"""Resets the aircraft"""
self.name = ""
@@ -25,7 +28,8 @@ class Aircraft:
self.prev_life = -1
self.id = -1
self.last_packet = None
-
+ self.damage_engine_warn_sent = False
+
def set_position(self, position:list):
"""Sets the position of the aircraft from the Airplane state packet"""
self.position = position
@@ -33,36 +37,36 @@ class Aircraft:
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:
@@ -73,11 +77,11 @@ class Aircraft:
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}")
+ debug(f"Command: {command.command}")
diff --git a/lib/PacketManager/packets/FSNETCMD_AIRCMD.py b/lib/PacketManager/packets/FSNETCMD_AIRCMD.py
index 98d782c..094da7d 100644
--- a/lib/PacketManager/packets/FSNETCMD_AIRCMD.py
+++ b/lib/PacketManager/packets/FSNETCMD_AIRCMD.py
@@ -40,7 +40,7 @@ class FSNETCMD_AIRCMD: #30
if with_size:
return pack("I",len(buffer))+buffer
return buffer
-
+
@staticmethod
def setPayload(aircraft_id:int, payload:int, units:str='kg', with_size:bool=False):
"""
@@ -51,3 +51,6 @@ class FSNETCMD_AIRCMD: #30
payload = str(payload)
message = f"INITLOAD {payload} {units}"
return FSNETCMD_AIRCMD.encode(aircraft_id, message, with_size)
+
+ def __str__(self):
+ return "Aircraft ID : {self.aircraft_id}; Message : {self.message}; Command : {self.command}"
diff --git a/lib/PacketManager/packets/FSNETCMD_AIRPLANESTATE.py b/lib/PacketManager/packets/FSNETCMD_AIRPLANESTATE.py
index 071db5e..2282367 100644
--- a/lib/PacketManager/packets/FSNETCMD_AIRPLANESTATE.py
+++ b/lib/PacketManager/packets/FSNETCMD_AIRPLANESTATE.py
@@ -1,6 +1,7 @@
from struct import pack, unpack
from math import pi
import math
+from logging import debug
class FSNETCMD_AIRPLANESTATE: #11
"""
@@ -73,8 +74,8 @@ class FSNETCMD_AIRPLANESTATE: #11
# self.atti = list(unpack("HHH", self.buffer[26:32]))
self.atti = list(map(lambda x: x * (pi / 32768.0),
unpack("HHH", self.buffer[26:32])))
- print(self.atti)
-
+ debug(self.atti)
+
self.velocity = list(map(lambda x: x/10,
unpack("HHH", self.buffer[32:38])))
self.atti_velocity = list(map(lambda x: x * (pi / 32768.0),
@@ -101,12 +102,11 @@ class FSNETCMD_AIRPLANESTATE: #11
self.flags["firing"] = bool(flags &8)
self.flags["smoke"] = 0
if flags & 2:
-
- self.flags["smoke"] = (flags >> 8) & 255 # bitshift 8 to the right,
+ self.flags["smoke"] = (flags >> 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:
@@ -140,10 +140,10 @@ class FSNETCMD_AIRPLANESTATE: #11
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])))
-
+
self.atti_velocity = list(map(lambda x: x / (pi / 32768.0),
unpack("HHH", self.buffer[40:46])))
self.g_value = unpack("h", self.buffer[46:48])[0]/100.0
@@ -199,13 +199,13 @@ class FSNETCMD_AIRPLANESTATE: #11
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)
+ debug(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]
diff --git a/lib/PacketManager/packets/FSNETCMD_GETDAMAGE.py b/lib/PacketManager/packets/FSNETCMD_GETDAMAGE.py
index 1becb40..165da4d 100644
--- a/lib/PacketManager/packets/FSNETCMD_GETDAMAGE.py
+++ b/lib/PacketManager/packets/FSNETCMD_GETDAMAGE.py
@@ -19,8 +19,8 @@ class FSNETCMD_GETDAMAGE: #22
def decode(self):
variables = unpack("IIIIIHHH", self.buffer[0:26])
- self.victim_id = variables[2]
self.victim_type = variables[1]
+ self.victim_id = variables[2]
self.attacker_type = variables[3]
self.attacker_id = variables[4]
self.damage = variables[5]
@@ -28,7 +28,7 @@ class FSNETCMD_GETDAMAGE: #22
self.weapon_type = variables[7]
if self.weapon_type in FSWEAPON_DICT:
self.weapon_type = FSWEAPON_DICT[self.weapon_type]
-
+
@staticmethod
def encode(victim_id, victim_type, attacker_type, attacker_id, damage, died_of,
@@ -36,8 +36,13 @@ class FSNETCMD_GETDAMAGE: #22
if weapon_type in FSWEAPON_DICT and not isinstance(weapon_type,int):
weapon_type = list(FSWEAPON_DICT.keys())[list(FSWEAPON_DICT.values()).index(weapon_type)]
- buffer = pack("I",22)+pack("IIIIIHHH", victim_id, victim_type, attacker_type,
- attacker_id, damage, died_of, weapon_type)
+ buffer = pack("I",22)+pack("4I3H", victim_type, victim_id, attacker_type,attacker_id,
+ damage, died_of, weapon_type)
if with_size:
return pack("I", len(buffer))+buffer
return buffer
+
+ def __str__(self):
+ return f"Victim ID : {self.victim_id}; Victim Type : {self.victim_type}; \
+ Attacker Type : {self.attacker_type}; Attacker ID : {self.attacker_id} \
+ Damage : {self.damage}; Died Of : {self.died_of}; weapon : {self.weapon_type}"
diff --git a/lib/Player.py b/lib/Player.py
index be49746..bc94bf2 100644
--- a/lib/Player.py
+++ b/lib/Player.py
@@ -3,13 +3,14 @@ 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):
+ def __init__(self, server_messages, client_messages, streamWriterObject):
self.username = ""
self.alias = ""
self.aircraft = Aircraft()
self.version = 0
self.ip = ""
+ self.streamWriterObject = streamWriterObject
def set_aircraft(self, aircraft:Aircraft):
self.aircraft = aircraft
@@ -32,4 +33,4 @@ class Player:
"IFF": packet.iff
})
return True
- return False \ No newline at end of file
+ return False
diff --git a/proxy.py b/proxy.py
index 221f4cf..b1160df 100644
--- a/proxy.py
+++ b/proxy.py
@@ -29,8 +29,8 @@ info("Lisenced under GPLv3")
async def handle_client(client_reader, client_writer):
message_to_client = []
message_to_server = []
- player = Player.Player(message_to_server, message_to_client) #Initialise the player.
-
+ player = Player.Player(message_to_server, message_to_client, client_writer) #Initialise the player.
+
try:
# Connect to the actual server
@@ -69,40 +69,68 @@ async def handle_client(client_reader, client_writer):
data = header + packet
packet_type = PacketManager().get_packet_type(packet)
if direction == "client_to_server":
+ debug("C2S" + str(packet_type))
+ debug(data)
+
try:
-
+
if packet_type == "FSNETCMD_LOGON":
player.login(FSNETCMD_LOGON(packet))
-
-
-
+ 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)
- if packet_type == "FSNETCMD_AIRPLANESTATE":
packet = player.aircraft.add_state(FSNETCMD_AIRPLANESTATE(packet))
+
+ """
+ Just for fun!
if packet.flags['firing']:
bomb_drop = FSNETCMD_MISSILELAUNCH.drop_bombs(player.aircraft)
message_to_server.append(bomb_drop)
message_to_client.append(bomb_drop)
+ """
+ if 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)
+ warnMsg = YSchat.message(f"You are exceeding the G Limit for the aircraft!, gValue = {player.aircraft.last_packet.g_value}!")
+ 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
+
elif prev_life > player.aircraft.life:
cheatingMsg = YSchat.message(f"{HEALTH_HACK_MESSAGE} by {player.username}")
writer.write(cheatingMsg)
await writer.drain()
+
+ elif player.aircraft.life < SMOKE_LIFE and SMOKE_PLANE:
+
+ 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}")
+ message_to_client.append(warningMsg)
+ player.aircraft.damage_engine_warn_sent = True
+
player.aircraft.life = prev_life
-
+
elif packet_type == "FSNETCMD_UNJOIN":
player.aircraft.reset()
-
- elif packet_type == "FSNETCMD_MISSILELAUNCH":
- print(packet)
- length, packet_type = unpack("<I I", data[:8])
- debug("C2S" + str(packet_type))
- debug(data)
+ elif packet_type == "FSNETCMD_AIRCMD":
+ h = FSNETCMD_AIRCMD(packet)
+ print(h.decode)
+
+ # elif packet_type == "FSNETCMD_GETDAMAGE":
+ # h = FSNETCMD_GETDAMAGE(packet, True)
+ # print(h)
+
# if packet_type == 11: # Flight data packet
# playerData = parseFlightData(data)
# player.playerId = playerData[1]
@@ -194,28 +222,26 @@ async def handle_client(client_reader, client_writer):
except Exception as e:
warning(f"Error parsing flight data: {e}", exc_info=True)
-
+
else :
+ debug("S2C" + str(packet_type))
+ debug(data)
+
#Coming from the server to the client
if packet_type == "FSNETCMD_ADDOBJECT":
if player.check_add_object(FSNETCMD_ADDOBJECT(packet)):
info(f"{player.username} has spawned an aircraft")
addSmoke = FSNETCMD_WEAPONCONFIG.addSmoke(player.aircraft.id)
message_to_server.append(addSmoke)
-
+
elif packet_type == "FSNETCMD_AIRCMD":
#Check the configs against the current aircraft
command = FSNETCMD_AIRCMD(packet)
player.aircraft.check_command(command)
-
- length, packet_type = unpack("<I I", data[:8])
- debug("S2C" + str(packet_type))
- debug(data)
- if packet_type == 36:
- # print("S2C ", str(data))
- pass
-
+ elif packet_type == "FSNETCMD_PREPARESIMULATION":
+ welcomeMsg = YSchat.message(WELCOME_MESSAGE.format(username=player.username))
+ message_to_server.append(welcomeMsg)
# Forward the packet to the other endpoint
writer.write(data)
@@ -251,4 +277,4 @@ async def start_proxy():
if __name__ == "__main__":
- asyncio.run(start_proxy()) \ No newline at end of file
+ asyncio.run(start_proxy())