summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/PacketManager/packets/FSNETCMD_AIRPLANESTATE.py149
-rw-r--r--lib/PacketManager/packets/FSNETCMD_JOINREQUEST.py8
-rw-r--r--lib/Player.py1
-rw-r--r--lib/plugin_manager.py11
-rw-r--r--plugins/radar.py78
-rw-r--r--plugins/refuel.py70
-rw-r--r--plugins/smoke_on_damage/Plugin.py4
-rw-r--r--proxy.py6
8 files changed, 211 insertions, 116 deletions
diff --git a/lib/PacketManager/packets/FSNETCMD_AIRPLANESTATE.py b/lib/PacketManager/packets/FSNETCMD_AIRPLANESTATE.py
index ebb2a6d..8c5aec7 100644
--- a/lib/PacketManager/packets/FSNETCMD_AIRPLANESTATE.py
+++ b/lib/PacketManager/packets/FSNETCMD_AIRPLANESTATE.py
@@ -74,6 +74,7 @@ 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])))
+ debug(self.atti)
self.velocity = list(map(lambda x: x/10,
unpack("HHH", self.buffer[32:38])))
@@ -217,12 +218,6 @@ class FSNETCMD_AIRPLANESTATE: #11
packet = self.buffer[:74] + pack('h',flag) + self.buffer[76:]
return pack('I',len(packet)) + packet
- def to_packet(self, with_size:bool=True):
- return FSNETCMD_AIRPLANESTATE.encode(self.remote_time, self.player_id, self.packet_version, self.position, self.atti, self.velocity, self.atti_velocity,
- self.smoke_oil, self.fuel, self.payload, self.flight_state, self.vgw, self.spoiler, self.landing_gear, self.flap, self.brake,
- self.flags, self.gun_ammo, self.rocket_ammo, self.aam, self.agm, self.bomb, self.life, self.g_value, self.throttle, self.elev, self.ail, self.rud,
- self.trim, self.thrust_vector, self.bomb_bay_info, with_size)
-
@staticmethod
def get_life(buffer:bytes):
version = unpack("h", buffer[12:14])[0]
@@ -237,81 +232,73 @@ class FSNETCMD_AIRPLANESTATE: #11
smoke_oil, fuel, payload, flight_state, vgw, spoiler, landing_gear, flap, brake,
flags, gun_ammo, rocket_ammo, aam, agm, bomb, life, g_value, throttle, elev, ail, rud,
trim, thrust_vector, bomb_bay_info, with_size:bool=False):
- try:
- buffer = pack("IfI", 11, remote_time, player_id)
- buffer += pack("H", packet_version)
- if packet_version == 4 or packet_version == 5:
- buffer += pack("fffhhhhhhhhh", *position, *atti, *velocity, *atti_velocity)
- buffer += pack("hhhh", smoke_oil, fuel, payload, 0)
- buffer += pack("BB", flight_state, int(vgw*255))
- buffer += pack("BB", int(spoiler*15)<<4 | int(landing_gear*15), int(flap*15)<<4 | int(brake*15))
- flagschar = 0
- if flags["ab"]:
- flagschar |= 1
- if flags["firing"]:
- flagschar |= 8
- if flags["smoke"]:
- flagschar |= flags["smoke"] << 8
- if flags["beacon"]:
- flagschar |= 16
- if flags["nav_lights"]:
- flagschar |= 32
- if flags["strobe"]:
- flagschar |= 64
- if flags["landing_lights"]:
- flagschar |= 128
- buffer += pack("h", flagschar)
- buffer += pack("HHBBB", gun_ammo, rocket_ammo, aam, agm, bomb)
- buffer += pack("B", life)
- buffer += pack("b", int(g_value*10))
- buffer += pack("B", int(throttle*99))
- buffer += pack("b", int(elev*99))
- buffer += pack("b", int(ail*99))
- buffer += pack("b", int(rud*99))
- buffer += pack("b", int(trim*99))
-
- if packet_version == 4:
- buffer += pack("BB", int(thrust_vector["vector"]*15)<<4 | int(thrust_vector["reverser"]*15),
- int(bomb_bay_info*15))
-
- else:
- buffer += pack("fff", *position)
- buffer += pack("HHH", *map(lambda x: int(x*32768.0/pi), atti))
- buffer += pack("HHH", *map(lambda x: int(x*10), velocity))
- buffer += pack("HHH", *map(lambda x: int(x*32768.0/pi), atti_velocity))
- buffer += pack("H", int(g_value))
- buffer += pack("HHHHH", gun_ammo, aam, agm, bomb, smoke_oil)
- buffer += pack("f", payload)
- buffer += pack("H", life)
- buffer += pack("BB", flight_state, int(vgw*255))
- buffer += pack("BBBB", int(spoiler*15), int(landing_gear*15),
- int(flap*15), int(brake*15))
- flagschar = 0
- if flags["ab"]:
- flagschar |= 1
- if flags["firing"]:
- flagschar |= 8
- if flags["smoke"]:
- flagschar |= flags["smoke"] << 8
- buffer += pack("H", flagschar)
- buffer += pack("B", int(throttle*99))
- buffer += pack("b", int(elev*99))
- buffer += pack("b", int(ail*99))
- buffer += pack("b", int(rud*99))
- buffer += pack("b", int(trim*99))
- buffer += pack("H", rocket_ammo)
- if packet_version >= 1:
- buffer += pack("fff", *atti_velocity)
- if packet_version >= 2:
- buffer += pack("BBB", int(thrust_vector["vector"]*255), int(thrust_vector["reverser"]*255),
- int(bomb_bay_info*255))
-
- if with_size:
- return pack("I",len(buffer))+buffer
- return buffer
- except Exception as e:
- import traceback
- traceback.print_exc()
+ buffer = pack("IfI", 11, remote_time, player_id)
+ buffer += pack("H", packet_version)
+ if packet_version == 4 or packet_version == 5:
+ buffer += pack("3f9H", *position, *atti, *velocity, *atti_velocity)
+ buffer += pack("hhhh", smoke_oil, fuel, payload, 0)
+ buffer += pack("BB", flight_state, int(vgw*255))
+ buffer += pack("BB", int(spoiler*15)<<4 | int(landing_gear*15), int(flap*15)<<4 | int(brake*15))
+ flagschar = 0
+ if flags["ab"]:
+ flagschar |= 1
+ if flags["firing"]:
+ flagschar |= 8
+ if flags["smoke"]:
+ flagschar |= flags["smoke"] << 8
+ if flags["beacon"]:
+ flagschar |= 16
+ if flags["nav_lights"]:
+ flagschar |= 32
+ if flags["strobe"]:
+ flagschar |= 64
+ if flags["landing_lights"]:
+ flagschar |= 128
+ buffer += pack("h", flagschar)
+ buffer += pack("HHBBB", gun_ammo, rocket_ammo, aam, agm, bomb)
+ buffer += pack("B", life)
+ buffer += pack("b", int(g_value*10))
+ buffer += pack("B", int(throttle*99))
+ buffer += pack("b", int(elev*99))
+ buffer += pack("b", int(ail*99))
+ buffer += pack("b", int(rud*99))
+ buffer += pack("b", int(trim*99))
+
+ if packet_version == 4:
+ buffer += pack("BB", int(thrust_vector["vector"]*15)<<4 | int(thrust_vector["reverser"]*15),
+ int(bomb_bay_info*15))
+
+ else:
+ buffer += pack("fffhhhfff", *position, *atti, *velocity, *atti_velocity)
+ buffer += pack("HHHHH", gun_ammo, aam, agm, bomb, smoke_oil)
+ buffer += pack("f", payload)
+ buffer += pack("H", life)
+ buffer += pack("BB", flight_state, int(vgw*255))
+ buffer += pack("BBBB", int(spoiler*15), int(landing_gear*15),
+ int(flap*15), int(brake*15))
+ flagschar = 0
+ if flags["ab"]:
+ flagschar |= 1
+ if flags["firing"]:
+ flagschar |= 8
+ if flags["smoke"]:
+ flagschar |= flags["smoke"] << 8
+ buffer += pack("H", flagschar)
+ buffer += pack("B", int(throttle*99))
+ buffer += pack("b", int(elev*99))
+ buffer += pack("b", int(ail*99))
+ buffer += pack("b", int(rud*99))
+ buffer += pack("b", int(trim*99))
+ buffer += pack("H", rocket_ammo)
+ if packet_version >= 1:
+ buffer += pack("fff", *atti_velocity)
+ if packet_version >= 2:
+ buffer += pack("BBB", int(thrust_vector["vector"]*255), int(thrust_vector["reverser"]*255),
+ int(bomb_bay_info*255))
+
+ 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}; \
diff --git a/lib/PacketManager/packets/FSNETCMD_JOINREQUEST.py b/lib/PacketManager/packets/FSNETCMD_JOINREQUEST.py
index 15848fa..f24c94a 100644
--- a/lib/PacketManager/packets/FSNETCMD_JOINREQUEST.py
+++ b/lib/PacketManager/packets/FSNETCMD_JOINREQUEST.py
@@ -7,7 +7,7 @@ class FSNETCMD_JOINREQUEST: #8
"""
def __init__(self, buffer:bytes, should_decode:bool=True):
self.buffer = buffer
- self.iff = None
+ self.iff = 0 # The IFF sent is 1 subtracted from the selected value by the player
self.aircraft = None
self.start_pos = None #It's the STP name
self.fuel = None
@@ -20,9 +20,6 @@ class FSNETCMD_JOINREQUEST: #8
self.start_pos = self.start_pos.decode().strip('\x00')
self.aircraft = self.aircraft.decode().strip('\x00')
- def to_packet(self, with_size:bool=True):
- return FSNETCMD_JOINREQUEST.encode(self.iff, self.aircraft, self.start_pos, self.fuel, self.smoke, with_size)
-
@staticmethod
def encode(iff, aircraft, start_pos, fuel, smoke, with_size:bool=False):
buffer = pack("IHH32s32sHHH", 8, iff, 0, aircraft.encode(),
@@ -30,6 +27,3 @@ class FSNETCMD_JOINREQUEST: #8
if with_size:
return pack("I",len(buffer))+buffer
return buffer
-
- def __str__(self):
- return f"JoinRequest: {self.iff} {self.aircraft} {self.start_pos} {self.fuel} {self.smoke}" \ No newline at end of file
diff --git a/lib/Player.py b/lib/Player.py
index 7f54914..8e2250a 100644
--- a/lib/Player.py
+++ b/lib/Player.py
@@ -12,6 +12,7 @@ class Player:
self.ip = ""
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
def set_aircraft(self, aircraft:Aircraft):
self.aircraft = aircraft
diff --git a/lib/plugin_manager.py b/lib/plugin_manager.py
index 279d601..07e28e6 100644
--- a/lib/plugin_manager.py
+++ b/lib/plugin_manager.py
@@ -58,13 +58,16 @@ class PluginManager:
If a callback returns False, then the original data is set to None
and not forwarded to the destination. This is useful for modifying
packets."""
- keep_original = True
+ keep_orignal = True
if hook_name in self.hooks:
for callback in self.hooks[hook_name]:
keep = callback(data, *args, **kwargs)
- if keep == False:
- keep_original = False
- return keep_original
+ if type(keep) == bool:
+ if keep == False:
+ keep_orignal = False
+ else:
+ warning(f"Return value of {callback} is not a boolean")
+ return keep_orignal
def trigger_command(self, command:str, player, full_message:str, message_to_client:list, message_to_server:list):
"""Triggers the command"""
diff --git a/plugins/radar.py b/plugins/radar.py
new file mode 100644
index 0000000..cacc6c4
--- /dev/null
+++ b/plugins/radar.py
@@ -0,0 +1,78 @@
+"""
+This plugin allows you have to Radar features similar to that of
+original WW3 server.
+"""
+import math
+from lib.PacketManager.packets import FSNETCMD_AIRPLANESTATE
+from lib.YSchat import send
+import struct
+import traceback
+
+ENABLED = True
+RADIUS = 500 # in meters, within this range planes with different IFF can see each other on radar
+
+flying_players = {}
+
+class Plugin:
+ def __init__(self):
+ self.plugin_manager = None
+
+ def register(self, plugin_manager):
+ self.plugin_manager = plugin_manager
+ self.plugin_manager.register_hook('on_flight_data_server', self.on_flight_data_server)
+ self.plugin_manager.register_hook('on_flight_data', self.on_flight_data)
+ self.plugin_manager.register_hook('on_unjoin', self.on_unjoin)
+
+ def on_flight_data(self, data, player, message_to_client, message_to_server):
+ flying_players[player.aircraft.id][1] = FSNETCMD_AIRPLANESTATE(data).position
+ return True
+
+ def on_flight_data_server(self, data, player, message_to_client, message_to_server):
+ # TODO : This is very primitive, we need to implement a better way to keep track of players
+ try:
+ if player.aircraft.id not in flying_players and player.aircraft.id != -1:
+ flying_players[player.aircraft.id] = [player, []]
+ elif player.aircraft.id == -1:
+ return True
+
+ decode = FSNETCMD_AIRPLANESTATE(data)
+
+ if decode.player_id == player.aircraft.id:
+ return True
+ elif self.get_player_by_pilotid(int(decode.player_id)).iff == player.iff:
+ return True
+ elif self.in_range(flying_players[player.aircraft.id][1], decode.position):
+ print(flying_players[player.aircraft.id][1], decode.position)
+ print("HERE")
+ return True
+ else:
+ try:
+ position_data = struct.pack("3f", -1, 1000.0, 1000.0)
+ if decode.packet_version == 4 or 5:
+ updated_data = data[:14] + position_data + data[26:]
+ else:
+ updated_data = data[:16] + position_data + data[28:]
+ except:
+ traceback.print_exc()
+
+ player.streamWriterObject.write(send(updated_data))
+ player.streamWriterObject.drain()
+ return False
+ except:
+ traceback.print_exc()
+
+ def on_unjoin(self, data, player, message_to_client, message_to_server):
+ return True
+
+ @staticmethod
+ def in_range(pos1, pos2):
+ # pos1 and pos2 are lists of [x,y,z]
+ dist = math.sqrt((pos1[0] - pos2[0])**2 + (pos1[1] - pos2[1])**2 + (pos1[2] - pos2[2])**2)
+ return dist <= RADIUS
+
+ @staticmethod
+ def get_player_by_pilotid(pilotid:int):
+ for playerid in flying_players:
+ if playerid == pilotid:
+ return flying_players[playerid][0]
+ return None
diff --git a/plugins/refuel.py b/plugins/refuel.py
index e171953..12af66a 100644
--- a/plugins/refuel.py
+++ b/plugins/refuel.py
@@ -3,60 +3,91 @@ This plugin enables you to perform air to air refueling.
"""
import math
from lib.PacketManager.packets import FSNETCMD_AIRCMD, FSNETCMD_AIRPLANESTATE
+from lib import YSchat
ENABLED = True
-REFUEL_RADIUS = 100 # in meters
+REFUEL_RADIUS = 500
+# in meters, recomended to set +100-200m more than
+# required range to compensate for distance lag caused by network.
+FUEL_RATE = 50 # in kg/s (aprroximately a second, timing is not accurate)
refuelers = {}
refueling = {}
class Plugin:
def __init__(self):
- def __init__(self):
- self.plugin_manager = None
+ self.plugin_manager = None
def register(self, plugin_manager):
self.plugin_manager = plugin_manager
self.plugin_manager.register_command('refuel', self.refuel)
- self.plugin_manager.register_command('k', self.refueler)
+ self.plugin_manager.register_command('refueler', self.refueler)
self.plugin_manager.register_hook('on_flight_data', self.on_flight_data)
+ self.plugin_manager.register_hook('on_unjoin', self.on_unjoin)
def refueler(self, full_message, player, message_to_client, message_to_server):
- if player in refuelers:
+ if player in refueling:
+ a = YSchat.message("You cannot be refueled while being a refueler")
+
+ elif player in refuelers:
+ a = YSchat.message("You are no more refueling!")
refuelers.pop(player)
else:
+ a = YSchat.message(f"You are now refueling other players! To refuel the plane must be within {REFUEL_RADIUS}m and have same IFF")
refuelers[player] = [0, [], False]
+ message_to_client.append(a)
def refuel(self, full_message, player, message_to_client, message_to_server):
#a = FSNETCMD_AIRCMD.set_command(player.aircraft.id, "INITFUEL", "3750kg", True)
#message_to_client.append(a)
#print(player in refueling)
- if player in refueling:
+ if player in refuelers:
+ a = YSchat.message("You cannot be a refueler while being refueled")
+ elif player in refueling:
+ a = YSchat.message("You are no more refueling!")
refueling.pop(player)
else:
+ a = YSchat.message(f"You can now be refueled by other players! To refuel the plane must be within {REFUEL_RADIUS}m and have same IFF")
refueling[player] = [0, []]
+ message_to_client.append(a)
def on_flight_data(self, data, player, message_to_client, message_to_server):
decode = FSNETCMD_AIRPLANESTATE(data)
if player in refueling:
- for player in refuelers:
- refueling[player] = [decode.fuel, decode.position]
- if self.in_range(refuelers[player][1], decode.position):
- print("here!")
- refuelers[player][2] = True
- max_lim = int((player.aircraft.initial_config['WEIGFUEL'])[:-2])
- if decode.fuel < max_lim:
- a = FSNETCMD_AIRCMD.set_command(player.aircraft.id, "INITFUEL", f"{decode.fuel+100}kg", True)
- message_to_client.append(a)
- else:
- refuelers[player][2] = False
+ for refueler in refuelers:
+ if refueler.iff == player.iff:
+ refueling[player] = [decode.fuel, decode.position]
+ if self.in_range(refuelers[refueler][1], decode.position):
+ refuelers[refueler][2] = True
+ max_lim = int((player.aircraft.initial_config['WEIGFUEL'])[:-2])
+ if decode.fuel < max_lim:
+ a = FSNETCMD_AIRCMD.set_command(player.aircraft.id, "INITFUEL", f"{decode.fuel+FUEL_RATE}kg", True)
+ message_to_client.append(a)
+ elif decode.fuel >= max_lim:
+ a = YSchat.message("The plane is full!")
+ refuelers[refueler][2] = False # No longer refueling
+ message_to_client.append(a)
+
+ if refuelers[refueler][0] < FUEL_RATE:
+ a = YSchat.message("The refueler ran out of fuel!")
+ message_to_client.append(a)
+ else:
+ refuelers[refueler][2] = False # No longer refueling
elif player in refuelers:
refuelers[player] = [decode.fuel, decode.position, refuelers[player][2]]
- if decode.fuel-100 > 0 and refuelers[player][2]:
- a = FSNETCMD_AIRCMD.set_command(player.aircraft.id, "INITFUEL", f"{decode.fuel-5}kg", True)
+ if decode.fuel-FUEL_RATE > 0 and refuelers[player][2]:
+ a = FSNETCMD_AIRCMD.set_command(player.aircraft.id, "INITFUEL", f"{decode.fuel-FUEL_RATE}kg", True)
message_to_client.append(a)
+ return True
+
+ def on_unjoin(self, data, player, message_to_client, message_to_server):
+ if player in refuelers:
+ refuelers.pop(player)
+ elif player in refueling:
+ refueling.pop(player)
+ return True
@staticmethod
def in_range(refueler_cord:list, refueled_cord:list):
@@ -65,7 +96,6 @@ class Plugin:
# implement this later
# for now we just use distance formula in a 3d space
dist = math.sqrt((refueler_cord[0]-refueled_cord[0])**2 + (refueler_cord[1]-refueled_cord[1])**2 + (refueler_cord[2]-refueled_cord[2])**2)
- print(dist)
if dist < REFUEL_RADIUS:
return True
else:
diff --git a/plugins/smoke_on_damage/Plugin.py b/plugins/smoke_on_damage/Plugin.py
index 12effc8..ed7fcf7 100644
--- a/plugins/smoke_on_damage/Plugin.py
+++ b/plugins/smoke_on_damage/Plugin.py
@@ -38,7 +38,9 @@ class Plugin:
message_to_client.append(FSNETCMD_AIRCMD.set_afterburner(player.aircraft.id, False, True))
- return False
+ return False
+ else:
+ return True
def on_weapon_config(self, data, player, message_to_client, message_to_server):
if ENABLED:
diff --git a/proxy.py b/proxy.py
index 37af393..9cb6a5e 100644
--- a/proxy.py
+++ b/proxy.py
@@ -117,9 +117,6 @@ async def handle_client(client_reader, client_writer):
try:
- if packet_type == "FSNETCMD_AIRCMD":
- print(FSNETCMD_AIRCMD.decode(packet))
-
if packet_type == "FSNETCMD_LOGON":
# keep_message = plugin_manager.triggar_hook('on_login', packet, player, message_to_client, message_to_server)
# if not keep_message:
@@ -133,6 +130,9 @@ async def handle_client(client_reader, client_writer):
writer.write(data)
continue
+ elif packet_type == "FSNETCMD_JOINREQUEST":
+ player.iff = FSNETCMD_JOINREQUEST(packet).iff + 1
+
elif packet_type == "FSNETCMD_AIRPLANESTATE":
player.aircraft.add_state(FSNETCMD_AIRPLANESTATE(packet)) #TODO: Do we want to convert all this to plugins? Probably not, but there is duplicated functionality
# keep_message = plugin_manager.triggar_hook('on_flight_data', packet, player, message_to_client, message_to_server)