diff --git a/Client/COOPAPI.cs b/Client/COOPAPI.cs index 086979f..c4c63bb 100644 --- a/Client/COOPAPI.cs +++ b/Client/COOPAPI.cs @@ -45,10 +45,6 @@ namespace RageCoop.Client /// ? /// public static event ChatMessage OnChatMessage; - /// - /// ? - /// - public static event ModEvent OnModPacketReceived; public static void Connected() { @@ -60,9 +56,9 @@ namespace RageCoop.Client OnConnection?.Invoke(false, GetPlayerID(), reason); } - public static void Connected(long netHandle) + public static void Connected(int playerID) { - OnConnection?.Invoke(true, netHandle); + OnConnection?.Invoke(true, playerID); } public static void Disconnected(long netHandle) @@ -70,11 +66,6 @@ namespace RageCoop.Client OnConnection?.Invoke(false, netHandle); } - public static void ModPacketReceived(long from, string mod, byte customID, byte[] bytes) - { - OnModPacketReceived?.Invoke(from, mod, customID, bytes); - } - public static bool ChatMessageReceived(string from, string message) { CancelEventArgs args = new CancelEventArgs(false); @@ -127,20 +118,6 @@ namespace RageCoop.Client return Main.LocalPlayerID; } - /* - - /// - /// Get a player using their Lidgren Network net handle - /// - /// Lidgren-Network net handle - public static CharacterEntity GetPed(int ID) - { - lock (Main.Characters) - { - return Main.Characters.ContainsKey(ID) ? Main.Characters[ID] : null; - } - } - */ /// /// Check if a RAGECOOP menu is visible /// @@ -149,7 +126,7 @@ namespace RageCoop.Client #if NON_INTERACTIVE return false; #else - return Main.MainMenu.MenuPool.AreAnyVisible; + return Menus.CoopMenu.MenuPool.AreAnyVisible; #endif } @@ -177,40 +154,6 @@ namespace RageCoop.Client return Main.CurrentVersion; } - /// - /// Send any data (bytes) to the server - /// - /// The name of this modification (script) - /// The ID to know what the data is - /// Your class, structure or whatever in bytes - public static void SendDataToServer(string modName, byte customID, byte[] bytes) - { - Networking.SendModData(-1, modName, customID, bytes); - } - - /// - /// Send any data (bytes) to the all player - /// - /// The name of this modification (script) - /// The ID to know what the data is - /// Your class, structure or whatever in bytes - public static void SendDataToAll(string modName, byte customID, byte[] bytes) - { - Networking.SendModData(0, modName, customID, bytes); - } - - /// - /// Send any data (bytes) to a player - /// - /// The Lidgren Network net handle that receives the data - /// The name of this modification (script) - /// The ID to know what the data is - /// Your class, structure or whatever in bytes - public static void SendDataToPlayer(long netHandle, string modName, byte customID, byte[] bytes) - { - Networking.SendModData(netHandle, modName, customID, bytes); - } - /// /// Get that player's local username /// @@ -236,35 +179,13 @@ namespace RageCoop.Client return true; } - /// - /// Enable or disable the local traffic for this player + /// Get or set the client's settings. /// - /// true to disable traffic - public static void SetLocalTraffic(bool enable) + /// The client's settings, you should NEVER change settings without notifying the player. + public static Settings Settings() { - Main.Settings.DisableTraffic = !enable; + return Main.Settings; } - - /// - /// Sets the alignment for the player list, if set to true it will align left, - /// otherwise it will align right - /// - /// true to move the player list to the left - public static void SetPlayerListLeftAlign(bool leftAlign) - { - PlayerList.LeftAlign = leftAlign; - } - -#if DEBUG - /// - /// ? - /// - /// - public static void SetDebug(bool value) - { - Main.UseDebug = value; - } -#endif } } diff --git a/Client/Main.cs b/Client/Main.cs index bcbe8e2..925d8c7 100644 --- a/Client/Main.cs +++ b/Client/Main.cs @@ -26,13 +26,12 @@ namespace RageCoop.Client public static readonly string CurrentVersion = "V0_3"; public static int LocalPlayerID=0; - public static bool NPCsAllowed = false; + internal static RelationshipGroup SyncedPedsGroup; public static new Settings Settings = null; #if !NON_INTERACTIVE - public static RageCoopMenu MainMenu = null; #endif public static Chat MainChat = null; public static Stopwatch Counter = new Stopwatch(); @@ -71,7 +70,6 @@ namespace RageCoop.Client Settings = Util.ReadSettings(); Networking.Start(); #if !NON_INTERACTIVE - MainMenu = new RageCoopMenu(); #endif MainChat = new Chat(); #if DEBUG @@ -107,7 +105,7 @@ namespace RageCoop.Client } #if !NON_INTERACTIVE - MainMenu.MenuPool.Process(); + CoopMenu.MenuPool.Process(); #endif @@ -193,14 +191,20 @@ namespace RageCoop.Client } if (e.KeyCode == Settings.MenuKey) { - if (MainMenu.MenuPool.AreAnyVisible) + if (CoopMenu.MenuPool.AreAnyVisible) { - MainMenu.MainMenu.Visible = false; - MainMenu.SubSettings.Menu.Visible = false; + CoopMenu.MenuPool.ForEach(x => + { + if (x.Visible) + { + CoopMenu.LastMenu=x; + x.Visible=false; + } + }); } else { - MainMenu.MainMenu.Visible = true; + CoopMenu.LastMenu.Visible = true; } } else if (Game.IsControlJustPressed(GTA.Control.MultiplayerInfo)) @@ -234,7 +238,7 @@ namespace RageCoop.Client if (V!=null) { - var seat = Util.GetNearestSeat(P, V); + var seat = P.GetNearestSeat(V); P.Task.EnterVehicle(V, seat); } } diff --git a/Client/Menus/RageCoopMenu.cs b/Client/Menus/CoopMenu.cs similarity index 59% rename from Client/Menus/RageCoopMenu.cs rename to Client/Menus/CoopMenu.cs index 4b95987..7b0ea00 100644 --- a/Client/Menus/RageCoopMenu.cs +++ b/Client/Menus/CoopMenu.cs @@ -10,24 +10,20 @@ namespace RageCoop.Client.Menus /// /// Don't use it! /// - public class RageCoopMenu + internal static class CoopMenu { - public ObjectPool MenuPool = new ObjectPool(); - - public NativeMenu MainMenu = new NativeMenu("RAGECOOP", "MAIN") + public static ObjectPool MenuPool = new ObjectPool(); + public static NativeMenu Menu = new NativeMenu("RAGECOOP", "MAIN") { UseMouse = false, Alignment = Main.Settings.FlipMenu ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left }; - #region SUB - public SettingsMenu SubSettings = new SettingsMenu(); - #endregion - + public static NativeMenu LastMenu { get; set; } = Menu; #region ITEMS - private readonly NativeItem _usernameItem = new NativeItem("Username") { AltTitle = Main.Settings.Username }; - public readonly NativeItem ServerIpItem = new NativeItem("Server IP") { AltTitle = Main.Settings.LastServerAddress }; - private readonly NativeItem _serverConnectItem = new NativeItem("Connect"); - private readonly NativeItem _aboutItem = new NativeItem("About", "~y~SOURCE~s~~n~" + + private static readonly NativeItem _usernameItem = new NativeItem("Username") { AltTitle = Main.Settings.Username }; + public static readonly NativeItem ServerIpItem = new NativeItem("Server IP") { AltTitle = Main.Settings.LastServerAddress }; + private static readonly NativeItem _serverConnectItem = new NativeItem("Connect"); + private static readonly NativeItem _aboutItem = new NativeItem("About", "~y~SOURCE~s~~n~" + "https://github.com/RAGECOOP~n~" + "~y~VERSION~s~~n~" + Main.CurrentVersion.Replace("_", ".")) { LeftBadge = new LemonUI.Elements.ScaledTexture("commonmenu", "shop_new_star") }; @@ -38,35 +34,35 @@ namespace RageCoop.Client.Menus /// /// Don't use it! /// - public RageCoopMenu() + static CoopMenu() { - MainMenu.Banner.Color = Color.FromArgb(225, 0, 0, 0); - MainMenu.Title.Color = Color.FromArgb(255, 165, 0); + Menu.Banner.Color = Color.FromArgb(225, 0, 0, 0); + Menu.Title.Color = Color.FromArgb(255, 165, 0); _usernameItem.Activated += UsernameActivated; ServerIpItem.Activated += ServerIpActivated; _serverConnectItem.Activated += (sender, item) => { Networking.DisConnectFromServer(Main.Settings.LastServerAddress); }; - MainMenu.Add(_usernameItem); - MainMenu.Add(ServerIpItem); - MainMenu.Add(_serverConnectItem); + Menu.Add(_usernameItem); + Menu.Add(ServerIpItem); + Menu.Add(_serverConnectItem); - MainMenu.AddSubMenu(SubSettings.Menu); - MainMenu.AddSubMenu(DevToolMenu.Menu); - MainMenu.AddSubMenu(DebugMenu.Menu); + Menu.AddSubMenu(SettingsMenu.Menu); + Menu.AddSubMenu(DevToolMenu.Menu); + Menu.AddSubMenu(DebugMenu.Menu); - MenuPool.Add(MainMenu); - MenuPool.Add(SubSettings.Menu); + MenuPool.Add(Menu); + MenuPool.Add(SettingsMenu.Menu); MenuPool.Add(DevToolMenu.Menu); MenuPool.Add(DebugMenu.Menu); MenuPool.Add(DebugMenu.DiagnosticMenu); - MainMenu.Add(_aboutItem); + Menu.Add(_aboutItem); } - public void UsernameActivated(object a, System.EventArgs b) + public static void UsernameActivated(object a, System.EventArgs b) { string newUsername = Game.GetUserInput(WindowTitle.EnterMessage20, _usernameItem.AltTitle, 20); if (!string.IsNullOrWhiteSpace(newUsername)) @@ -78,7 +74,7 @@ namespace RageCoop.Client.Menus } } - public void ServerIpActivated(object a, System.EventArgs b) + public static void ServerIpActivated(object a, System.EventArgs b) { string newServerIp = Game.GetUserInput(WindowTitle.EnterMessage60, ServerIpItem.AltTitle, 60); if (!string.IsNullOrWhiteSpace(newServerIp) && newServerIp.Contains(":")) @@ -90,21 +86,21 @@ namespace RageCoop.Client.Menus } } - public void InitiateConnectionMenuSetting() + public static void InitiateConnectionMenuSetting() { _usernameItem.Enabled = false; ServerIpItem.Enabled = false; _serverConnectItem.Enabled = false; } - public void ConnectedMenuSetting() + public static void ConnectedMenuSetting() { _serverConnectItem.Enabled = true; _serverConnectItem.Title = "Disconnect"; - MainMenu.Visible = false; + Menu.Visible = false; } - public void DisconnectedMenuSetting() + public static void DisconnectedMenuSetting() { _usernameItem.Enabled = true; ServerIpItem.Enabled = true; diff --git a/Client/Menus/Sub/DevToolMenu.cs b/Client/Menus/Sub/DevToolMenu.cs index 74763fb..3ce7e7d 100644 --- a/Client/Menus/Sub/DevToolMenu.cs +++ b/Client/Menus/Sub/DevToolMenu.cs @@ -9,7 +9,7 @@ using System.Drawing; namespace RageCoop.Client { - internal class DevToolMenu + internal static class DevToolMenu { public static NativeMenu Menu = new NativeMenu("RAGECOOP", "DevTool", "Help with the development") { diff --git a/Client/Menus/Sub/SettingsMenu.cs b/Client/Menus/Sub/SettingsMenu.cs index c9f9827..c3f77e7 100644 --- a/Client/Menus/Sub/SettingsMenu.cs +++ b/Client/Menus/Sub/SettingsMenu.cs @@ -9,19 +9,19 @@ namespace RageCoop.Client.Menus /// /// Don't use it! /// - public class SettingsMenu + internal static class SettingsMenu { - public NativeMenu Menu = new NativeMenu("RAGECOOP", "Settings", "Go to the settings") + public static NativeMenu Menu = new NativeMenu("RAGECOOP", "Settings", "Go to the settings") { UseMouse = false, Alignment = Main.Settings.FlipMenu ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left }; - private readonly NativeCheckboxItem _disableTrafficItem = new NativeCheckboxItem("Disable Traffic (NPCs/Vehicles)", "Local traffic only", Main.Settings.DisableTraffic); - private readonly NativeCheckboxItem _flipMenuItem = new NativeCheckboxItem("Flip menu", Main.Settings.FlipMenu); - private readonly NativeCheckboxItem _disablePauseAlt = new NativeCheckboxItem("Disable Alternate Pause", "Don't freeze game time when Esc pressed", Main.Settings.DisableTraffic); + private static readonly NativeCheckboxItem _disableTrafficItem = new NativeCheckboxItem("Disable Traffic (NPCs/Vehicles)", "Local traffic only", Main.Settings.DisableTraffic); + private static readonly NativeCheckboxItem _flipMenuItem = new NativeCheckboxItem("Flip menu", Main.Settings.FlipMenu); + private static readonly NativeCheckboxItem _disablePauseAlt = new NativeCheckboxItem("Disable Alternate Pause", "Don't freeze game time when Esc pressed", Main.Settings.DisableTraffic); - private readonly NativeCheckboxItem _showNetworkInfoItem = new NativeCheckboxItem("Show Network Info", Networking.ShowNetworkInfo); + private static readonly NativeCheckboxItem _showNetworkInfoItem = new NativeCheckboxItem("Show Network Info", Networking.ShowNetworkInfo); private static NativeItem _menuKey = new NativeItem("Menu Key","The key to open menu", Main.Settings.MenuKey.ToString()); private static NativeItem _passengerKey = new NativeItem("Passenger Key", "The key to enter a vehicle as passenger", Main.Settings.PassengerKey.ToString()); @@ -30,7 +30,7 @@ namespace RageCoop.Client.Menus /// /// Don't use it! /// - public SettingsMenu() + static SettingsMenu() { Menu.Banner.Color = Color.FromArgb(225, 0, 0, 0); Menu.Title.Color = Color.FromArgb(255, 165, 0); @@ -52,14 +52,14 @@ namespace RageCoop.Client.Menus Menu.Add(_vehicleSoftLimit); } - - private void _disablePauseAlt_CheckboxChanged(object sender, EventArgs e) + + private static void _disablePauseAlt_CheckboxChanged(object sender, EventArgs e) { Main.Settings.DisableAlternatePause=_disablePauseAlt.Checked; Util.SaveSettings(); } - private void vehicleSoftLimit_Activated(object sender, EventArgs e) + private static void vehicleSoftLimit_Activated(object sender, EventArgs e) { try { @@ -71,7 +71,7 @@ namespace RageCoop.Client.Menus } catch { } } - private void ChaneMenuKey(object sender, EventArgs e) + private static void ChaneMenuKey(object sender, EventArgs e) { try { @@ -85,7 +85,7 @@ namespace RageCoop.Client.Menus catch { } } - private void ChangePassengerKey(object sender, EventArgs e) + private static void ChangePassengerKey(object sender, EventArgs e) { try { @@ -99,22 +99,22 @@ namespace RageCoop.Client.Menus catch { } } - public void DisableTrafficCheckboxChanged(object a, System.EventArgs b) + public static void DisableTrafficCheckboxChanged(object a, System.EventArgs b) { Main.Settings.DisableTraffic = _disableTrafficItem.Checked; Util.SaveSettings() ; } - public void FlipMenuCheckboxChanged(object a, System.EventArgs b) + public static void FlipMenuCheckboxChanged(object a, System.EventArgs b) { - Main.MainMenu.MainMenu.Alignment = _flipMenuItem.Checked ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left; + CoopMenu.Menu.Alignment = _flipMenuItem.Checked ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left; Menu.Alignment = _flipMenuItem.Checked ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left; Main.Settings.FlipMenu = _flipMenuItem.Checked; Util.SaveSettings(); } - public void ShowNetworkInfoCheckboxChanged(object a, System.EventArgs b) + public static void ShowNetworkInfoCheckboxChanged(object a, System.EventArgs b) { Networking.ShowNetworkInfo = _showNetworkInfoItem.Checked; diff --git a/Client/Misc/Util.cs b/Client/Misc/Util.cs deleted file mode 100644 index 7dfdf6b..0000000 --- a/Client/Misc/Util.cs +++ /dev/null @@ -1,982 +0,0 @@ -using System; -using System.IO; -using System.Xml.Serialization; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using RageCoop.Core; -using GTA; -using GTA.Native; -using GTA.Math; -using System.Linq; -using System.Diagnostics; - -namespace RageCoop.Client -{ - /// - /// - /// - - internal static partial class Util - { - #region -- POINTER -- - private static int _steeringAngleOffset { get; set; } - - public static unsafe void NativeMemory() - { - IntPtr address; - - address = Game.FindPattern("\x74\x0A\xF3\x0F\x11\xB3\x1C\x09\x00\x00\xEB\x25", "xxxxxx????xx"); - if (address != IntPtr.Zero) - { - _steeringAngleOffset = *(int*)(address + 6) + 8; - } - - // breaks some stuff. - /* - address = Game.FindPattern("\x32\xc0\xf3\x0f\x11\x09", "xxxxxx"); // Weapon / Radio slowdown - if (address != IntPtr.Zero) - { - for (int i = 0; i < 6; i++) - { - *(byte*)(address + i).ToPointer() = 0x90; - } - } - */ - } - - public static unsafe void CustomSteeringAngle(this Vehicle veh, float value) - { - IntPtr address = new IntPtr((long)veh.MemoryAddress); - if (address == IntPtr.Zero || _steeringAngleOffset == 0) - { - return; - } - - *(float*)(address + _steeringAngleOffset).ToPointer() = value; - } - #endregion - - public static Settings ReadSettings() - { - XmlSerializer ser = new XmlSerializer(typeof(Settings)); - - string path = Directory.GetCurrentDirectory() + "\\Scripts\\RageCoop\\RageCoop.Client.Settings.xml"; - Settings settings = null; - - if (File.Exists(path)) - { - using (FileStream stream = File.OpenRead(path)) - { - settings = (RageCoop.Client.Settings)ser.Deserialize(stream); - } - - using (FileStream stream = new FileStream(path, FileMode.Truncate, FileAccess.ReadWrite)) - { - ser.Serialize(stream, settings); - } - } - else - { - using (FileStream stream = File.OpenWrite(path)) - { - ser.Serialize(stream, settings = new Settings()); - } - } - - return settings; - } - public static void SaveSettings() - { - try - { - string path = Directory.GetCurrentDirectory() + "\\Scripts\\RageCoop\\RageCoop.Client.Settings.xml"; - - using (FileStream stream = new FileStream(path, File.Exists(path) ? FileMode.Truncate : FileMode.Create, FileAccess.ReadWrite)) - { - XmlSerializer ser = new XmlSerializer(typeof(Settings)); - ser.Serialize(stream, Main.Settings); - } - } - catch (Exception ex) - { - GTA.UI.Notification.Show("Error saving player settings: " + ex.Message); - } - } - - - - - public static bool IsBetween(this T item, T start, T end) - { - return Comparer.Default.Compare(item, start) >= 0 && Comparer.Default.Compare(item, end) <= 0; - } - - public static bool Compare(this Dictionary item, Dictionary item2) - { - if (item == null || item2 == null || item.Count != item2.Count) - { - return false; - } - - foreach (KeyValuePair pair in item) - { - if (item2.TryGetValue(pair.Key, out Y value) && Equals(value, pair.Value)) - { - continue; - } - - // TryGetValue() or Equals failed - return false; - } - - // No difference between item and item2 - return true; - } - - #region MATH - public static Vector3 LinearVectorLerp(Vector3 start, Vector3 end, ulong currentTime, int duration) - { - return new Vector3() - { - X = LinearFloatLerp(start.X, end.X, currentTime, duration), - Y = LinearFloatLerp(start.Y, end.Y, currentTime, duration), - Z = LinearFloatLerp(start.Z, end.Z, currentTime, duration), - }; - } - - public static float LinearFloatLerp(float start, float end, ulong currentTime, int duration) - { - return (end - start) * currentTime / duration + start; - } - - public static float Lerp(float from, float to, float fAlpha) - { - return (from * (1.0f - fAlpha)) + (to * fAlpha); //from + (to - from) * fAlpha - } - - public static Vector3 RotationToDirection(Vector3 rotation) - { - double z = MathExtensions.DegToRad(rotation.Z); - double x = MathExtensions.DegToRad(rotation.X); - double num = Math.Abs(Math.Cos(x)); - - return new Vector3 - { - X = (float)(-Math.Sin(z) * num), - Y = (float)(Math.Cos(z) * num), - Z = (float)Math.Sin(x) - }; - } - - - #endregion - - public static Model ModelRequest(this int hash) - { - Model model = new Model(hash); - - if (!model.IsValid) - { - //GTA.UI.Notification.Show("~y~Not valid!"); - return null; - } - - if (!model.IsLoaded) - { - return model.Request(1000) ? model : null; - } - - return model; - } - - #region PED - - public static byte GetPedSpeed(this Ped ped) - { - if (ped.IsSprinting) - { - return 3; - } - if (ped.IsRunning) - { - return 2; - } - if (ped.IsWalking) - { - return 1; - } - - return 0; - } - - public static Dictionary GetPedClothes(this Ped ped) - { - Dictionary result = new Dictionary(); - for (byte i = 0; i < 11; i++) - { - short mod = Function.Call(Hash.GET_PED_DRAWABLE_VARIATION, ped.Handle, i); - result.Add(i, mod); - } - return result; - } - - public static PedDataFlags GetPedFlags(this Ped ped) - { - PedDataFlags flags = PedDataFlags.None; - - if (ped.IsAiming || ped.IsOnTurretSeat()) - { - flags |= PedDataFlags.IsAiming; - } - - - if (ped.IsReloading) - { - flags |= PedDataFlags.IsReloading; - } - - if (ped.IsJumping) - { - flags |= PedDataFlags.IsJumping; - } - - if (ped.IsRagdoll) - { - flags |= PedDataFlags.IsRagdoll; - } - - if (ped.IsOnFire) - { - flags |= PedDataFlags.IsOnFire; - } - - if (ped.IsInParachuteFreeFall) - { - flags |= PedDataFlags.IsInParachuteFreeFall; - } - - if (ped.ParachuteState == ParachuteState.Gliding) - { - flags |= PedDataFlags.IsParachuteOpen; - } - - bool climbingLadder = ped.IsTaskActive(TaskType.CTaskGoToAndClimbLadder); - if (climbingLadder) - { - flags |= PedDataFlags.IsOnLadder; - } - - if (ped.IsVaulting && !climbingLadder) - { - flags |= PedDataFlags.IsVaulting; - } - - if (ped.IsInCover || ped.IsGoingIntoCover) - { - flags |=PedDataFlags.IsInCover; - } - if (ped.IsPlayer) - { - flags|=PedDataFlags.IsPlayer; - } - return flags; - } - - public static string[] GetReloadingAnimation(this Ped ped) - { - switch (ped.Weapons.Current.Hash) - { - case WeaponHash.Revolver: - case WeaponHash.RevolverMk2: - case WeaponHash.DoubleActionRevolver: - case WeaponHash.NavyRevolver: - return new string[2] { "anim@weapons@pistol@revolver_str", "reload_aim" }; - case WeaponHash.APPistol: - return new string[2] { "weapons@pistol@ap_pistol_str", "reload_aim" }; - case WeaponHash.Pistol50: - return new string[2] { "weapons@pistol@pistol_50_str", "reload_aim" }; - case WeaponHash.Pistol: - case WeaponHash.PistolMk2: - case WeaponHash.PericoPistol: - case WeaponHash.SNSPistol: - case WeaponHash.SNSPistolMk2: - case WeaponHash.HeavyPistol: - case WeaponHash.VintagePistol: - case WeaponHash.CeramicPistol: - case WeaponHash.MachinePistol: - return new string[2] { "weapons@pistol@pistol_str", "reload_aim" }; - case WeaponHash.AssaultRifle: - case WeaponHash.AssaultrifleMk2: - return new string[2] { "weapons@rifle@hi@assault_rifle_str", "reload_aim" }; - case WeaponHash.SniperRifle: - return new string[2] { "weapons@rifle@hi@sniper_rifle_str", "reload_aim" }; - case WeaponHash.HeavySniper: - case WeaponHash.HeavySniperMk2: - return new string[2] { "weapons@rifle@lo@sniper_heavy_str", "reload_aim" }; - case WeaponHash.PumpShotgun: - case WeaponHash.PumpShotgunMk2: - return new string[2] { "weapons@rifle@pump_str", "reload_aim" }; - case WeaponHash.Railgun: - return new string[2] { "weapons@rifle@lo@rail_gun_str", "reload_aim" }; - case WeaponHash.SawnOffShotgun: - return new string[2] { "weapons@rifle@lo@sawnoff_str", "reload_aim" }; - case WeaponHash.AssaultShotgun: - return new string[2] { "weapons@rifle@lo@shotgun_assault_str", "reload_aim" }; - case WeaponHash.BullpupShotgun: - return new string[2] { "weapons@rifle@lo@shotgun_bullpup_str", "reload_aim" }; - case WeaponHash.AdvancedRifle: - return new string[2] { "weapons@submg@advanced_rifle_str", "reload_aim" }; - case WeaponHash.CarbineRifle: - case WeaponHash.CarbineRifleMk2: - case WeaponHash.CompactRifle: - return new string[2] { "weapons@rifle@lo@carbine_str", "reload_aim" }; - case WeaponHash.Gusenberg: - return new string[2] { "anim@weapons@machinegun@gusenberg_str", "reload_aim" }; - case WeaponHash.Musket: - return new string[2] { "anim@weapons@musket@musket_str", "reload_aim" }; - case WeaponHash.FlareGun: - return new string[2] { "anim@weapons@pistol@flare_str", "reload_aim" }; - case WeaponHash.SpecialCarbine: - case WeaponHash.SpecialCarbineMk2: - return new string[2] { "anim@weapons@rifle@lo@spcarbine_str", "reload_aim" }; - case WeaponHash.CombatPDW: - return new string[2] { "anim@weapons@rifle@lo@pdw_str", "reload_aim" }; - case WeaponHash.BullpupRifle: - case WeaponHash.BullpupRifleMk2: - return new string[2] { "anim@weapons@submg@bullpup_rifle_str", "reload_aim" }; - case WeaponHash.AssaultSMG: - return new string[2] { "weapons@submg@assault_smg_str", "reload_aim" }; - case WeaponHash.MicroSMG: - case WeaponHash.MiniSMG: - return new string[2] { "weapons@submg@lo@micro_smg_str", "reload_aim" }; - case WeaponHash.SMG: - case WeaponHash.SMGMk2: - return new string[2] { "weapons@rifle@smg_str", "reload_aim" }; - case WeaponHash.GrenadeLauncher: - case WeaponHash.GrenadeLauncherSmoke: - case WeaponHash.CompactGrenadeLauncher: - return new string[2] { "weapons@heavy@grenade_launcher_str", "reload_aim" }; - case WeaponHash.RPG: - case WeaponHash.Firework: - return new string[2] { "weapons@heavy@rpg_str", "reload_aim" }; - case WeaponHash.CombatMG: - case WeaponHash.CombatMGMk2: - return new string[2] { "weapons@machinegun@combat_mg_str", "reload_aim" }; - case WeaponHash.MG: - return new string[2] { "weapons@machinegun@mg_str", "reload_aim" }; - default: - Main.Logger.Warning($"~r~Reloading failed! Weapon ~g~[{ped.Weapons.Current.Hash}]~r~ could not be found!"); - return null; - } - } - - public static VehicleSeat GetNearestSeat(Ped ped, Vehicle veh, float distanceToignoreDoors = 50f) - { - float num = 99f; - int result = -2; - Dictionary dictionary = new Dictionary(); - dictionary.Add("door_dside_f", -1); - dictionary.Add("door_pside_f", 0); - dictionary.Add("door_dside_r", 1); - dictionary.Add("door_pside_r", 2); - foreach (string text in dictionary.Keys) - { - bool flag = veh.Bones[text].Position != Vector3.Zero; - if (flag) - { - float num2 = ped.Position.DistanceTo(Function.Call(Hash.GET_WORLD_POSITION_OF_ENTITY_BONE, new InputArgument[] - { - veh, - veh.Bones[text].Index - })); - bool flag2 = (num2 < distanceToignoreDoors) && (num2 < num)&& IsSeatUsableByPed(ped, veh, dictionary[text]); - if (flag2) - { - num = num2; - result = dictionary[text]; - } - } - } - return (VehicleSeat)result; - } - public static bool IsSeatUsableByPed(Ped ped, Vehicle veh, int _seat) - { - VehicleSeat seat = (VehicleSeat)_seat; - bool result = false; - bool flag = veh.IsSeatFree(seat); - if (flag) - { - result = true; - } - else - { - - bool isDead = veh.GetPedOnSeat(seat).IsDead; - if (isDead) - { - result = true; - } - else - { - int num = Function.Call(Hash.GET_RELATIONSHIP_BETWEEN_PEDS, new InputArgument[] - { - ped, - veh.GetPedOnSeat(seat) - }); - bool flag2 = num > 2; - if (flag2) - { - result = true; - } - } - - } - return result; - } - public static bool IsTaskActive(this Ped p,TaskType task) - { - return Function.Call(Hash.GET_IS_TASK_ACTIVE, p.Handle, task); - } - public static Vector3 GetAimCoord(this Ped p) - { - var weapon = p.Weapons.CurrentWeaponObject; - - var v = p.CurrentVehicle; - // Rhino - if (v!=null && v.Model.Hash==782665360) - { - return v.Bones[35].Position+v.Bones[35].ForwardVector*100; - } - if (p.IsOnTurretSeat()) { return p.GetLookingCoord(); } - if (weapon!=null) - { - // Not very accurate, but doesn't matter - Vector3 dir = weapon.RightVector; - return weapon.Position+dir*20; - - } - return GetLookingCoord(p); - } - public static Vector3 GetLookingCoord(this Ped p) - { - EntityBone b = p.Bones[Bone.FacialForehead]; - Vector3 v = b.UpVector.Normalized; - return b.Position+200*v; - } - - public static void StayInCover(this Ped p) - { - Function.Call(Hash.TASK_STAY_IN_COVER, p); - } - public static VehicleSeat GetSeatTryingToEnter(this Ped p) - { - return (VehicleSeat)Function.Call(Hash.GET_SEAT_PED_IS_TRYING_TO_ENTER, p); - } - - - - #endregion - - #region VEHICLE - - public static VehicleDataFlags GetVehicleFlags(this Vehicle veh) - { - VehicleDataFlags flags = 0; - - if (veh.IsEngineRunning) - { - flags |= VehicleDataFlags.IsEngineRunning; - } - - if (veh.AreLightsOn) - { - flags |= VehicleDataFlags.AreLightsOn; - } - - if (veh.BrakePower >= 0.01f) - { - flags |= VehicleDataFlags.AreBrakeLightsOn; - } - - if (veh.AreHighBeamsOn) - { - flags |= VehicleDataFlags.AreHighBeamsOn; - } - - if (veh.IsSirenActive) - { - flags |= VehicleDataFlags.IsSirenActive; - } - - if (veh.IsDead) - { - flags |= VehicleDataFlags.IsDead; - } - - if (Function.Call(Hash.IS_HORN_ACTIVE, veh.Handle)) - { - flags |= VehicleDataFlags.IsHornActive; - } - - if (veh.IsSubmarineCar && Function.Call(Hash._GET_IS_SUBMARINE_VEHICLE_TRANSFORMED, veh.Handle)) - { - flags |= VehicleDataFlags.IsTransformed; - } - - if (veh.HasRoof && (veh.RoofState == VehicleRoofState.Opened || veh.RoofState == VehicleRoofState.Opening)) - { - flags |= VehicleDataFlags.RoofOpened; - } - - - if (veh.IsAircraft) - { - flags |= VehicleDataFlags.IsAircraft; - } - if (veh.Model.Hash==1483171323 && veh.IsDeluxoHovering()) - { - flags|= VehicleDataFlags.IsDeluxoHovering; - } - - - - return flags; - } - public static bool HasFlag(this PedDataFlags flagToCheck,PedDataFlags flag) - { - return (flagToCheck & flag)!=0; - } - - public static bool HasFlag(this VehicleDataFlags flagToCheck, VehicleDataFlags flag) - { - return (flagToCheck & flag)!=0; - } - - - public static Dictionary GetWeaponComponents(this Weapon weapon) - { - Dictionary result = null; - - if (weapon.Components.Count > 0) - { - result = new Dictionary(); - - foreach (var comp in weapon.Components) - { - result.Add((uint)comp.ComponentHash, comp.Active); - } - } - - return result; - } - - public static Dictionary GetVehicleMods(this VehicleModCollection mods) - { - Dictionary result = new Dictionary(); - foreach (VehicleMod mod in mods.ToArray()) - { - result.Add((int)mod.Type, mod.Index); - } - return result; - } - - public static VehicleDamageModel GetVehicleDamageModel(this Vehicle veh) - { - // Broken windows - byte brokenWindows = 0; - for (int i = 0; i < 8; i++) - { - if (!veh.Windows[(VehicleWindowIndex)i].IsIntact) - { - brokenWindows |= (byte)(1 << i); - } - } - - // Broken doors - byte brokenDoors = 0; - byte openedDoors = 0; - foreach (VehicleDoor door in veh.Doors) - { - if (door.IsBroken) - { - brokenDoors |= (byte)(1 << (byte)door.Index); - } - else if (door.IsOpen) - { - openedDoors |= (byte)(1 << (byte)door.Index); - } - } - - - // Bursted tires - short burstedTires = 0; - foreach (VehicleWheel wheel in veh.Wheels.GetAllWheels()) - { - if (wheel.IsBursted) - { - burstedTires |= (short)(1 << (int)wheel.BoneId); - } - } - - return new VehicleDamageModel() - { - BrokenDoors = brokenDoors, - OpenedDoors = openedDoors, - BrokenWindows = brokenWindows, - BurstedTires = burstedTires, - LeftHeadLightBroken = (byte)(veh.IsLeftHeadLightBroken ? 1 : 0), - RightHeadLightBroken = (byte)(veh.IsRightHeadLightBroken ? 1 : 0) - }; - } - - public static Dictionary GetPassengers(this Vehicle veh) - { - Dictionary ps=new Dictionary(); - var d = veh.Driver; - if (d!=null&&d.IsSittingInVehicle()) - { - ps.Add(-1, d.GetSyncEntity().ID); - } - foreach(Ped p in veh.Passengers) - { - if (p.IsSittingInVehicle()) - { - ps.Add((int)p.SeatIndex, (int)p.GetSyncEntity().ID); - } - } - return ps; - } - - - public static void SetDeluxoHoverState(this Vehicle deluxo,bool hover) - { - Function.Call(Hash._SET_VEHICLE_HOVER_TRANSFORM_PERCENTAGE, deluxo, hover? 1f: 0f); - } - public static bool IsDeluxoHovering(this Vehicle deluxo) - { - return Math.Abs(deluxo.Bones[27].ForwardVector.GetCosTheta(deluxo.ForwardVector)-1)>0.05; - } - - public static float GetNozzleAngel(this Vehicle plane) - { - return Function.Call(Hash._GET_VEHICLE_FLIGHT_NOZZLE_POSITION, plane); - } - public static bool HasNozzle(this Vehicle v) - { - - switch (v.Model.Hash) - { - // Hydra - case 970385471: - return true; - - // Avenger - case -2118308144: - return true; - - // Avenger - case 408970549: - return true; - - } - return false; - } - public static void SetNozzleAngel(this Vehicle plane,float ratio) - { - Function.Call(Hash.SET_VEHICLE_FLIGHT_NOZZLE_POSITION, plane, ratio); - } - public static void SetDamageModel(this Vehicle veh, VehicleDamageModel model, bool leavedoors = true) - { - for (int i = 0; i < 8; i++) - { - var door = veh.Doors[(VehicleDoorIndex)i]; - if ((model.BrokenDoors & (byte)(1 << i)) != 0) - { - door.Break(leavedoors); - } - else if (door.IsBroken) - { - // The vehicle can only fix a door if the vehicle was completely fixed - veh.Repair(); - return; - } - if ((model.OpenedDoors & (byte)(1 << i)) != 0) - { - if ((!door.IsOpen)&&(!door.IsBroken)) - { - door.Open(); - } - } - else if (door.IsOpen) - { - if (!door.IsBroken) { door.Close(); } - } - - if ((model.BrokenWindows & (byte)(1 << i)) != 0) - { - veh.Windows[(VehicleWindowIndex)i].Smash(); - } - else if (!veh.Windows[(VehicleWindowIndex)i].IsIntact) - { - veh.Windows[(VehicleWindowIndex)i].Repair(); - } - } - - foreach (VehicleWheel wheel in veh.Wheels) - { - if ((model.BurstedTires & (short)(1 << (int)wheel.BoneId)) != 0) - { - if (!wheel.IsBursted) - { - wheel.Puncture(); - wheel.Burst(); - } - } - else if (wheel.IsBursted) - { - wheel.Fix(); - } - } - - veh.IsLeftHeadLightBroken = model.LeftHeadLightBroken > 0; - veh.IsRightHeadLightBroken = model.RightHeadLightBroken > 0; - } - public static Vector3 PredictPosition(this Entity e,bool applyDefault=true) - { - return e.Position+e.Velocity*((applyDefault?SyncParameters.PositioinPredictionDefault:0)+Networking.Latency); - } - - #endregion - - public static void SetOnFire(this Entity e,bool toggle) - { - if (toggle) - { - Function.Call(Hash.START_ENTITY_FIRE, e.Handle); - } - else - { - Function.Call(Hash.STOP_ENTITY_FIRE, e.Handle); - } - } - - public static SyncedPed GetSyncEntity(this Ped p) - { - if(p == null) { return null; } - var c = EntityPool.GetPedByHandle(p.Handle); - if(c==null) { EntityPool.Add(c=new SyncedPed(p)); } - return c; - } - - public static SyncedVehicle GetSyncEntity(this Vehicle veh) - { - if(veh == null) { return null; } - var v=EntityPool.GetVehicleByHandle(veh.Handle); - if (v==null) { EntityPool.Add(v=new SyncedVehicle(veh)); } - return v; - } - - - - - - - public static bool IsTurretSeat(this Vehicle veh, int seat) - { - if (!Function.Call(Hash.DOES_VEHICLE_HAVE_WEAPONS, veh.Handle)) - { - return false; - } - - switch (seat) - { - case -1: - return (VehicleHash)veh.Model.Hash == VehicleHash.Rhino - || (VehicleHash)veh.Model.Hash == VehicleHash.Khanjari - || (VehicleHash)veh.Model.Hash == VehicleHash.FireTruck - || (VehicleHash)veh.Model.Hash == VehicleHash.Riot2 - || (VehicleHash)veh.Model.Hash == VehicleHash.Cerberus - || (VehicleHash)veh.Model.Hash == VehicleHash.Cerberus2 - || (VehicleHash)veh.Model.Hash == VehicleHash.Cerberus3; - case 0: - return (VehicleHash)veh.Model.Hash == VehicleHash.Apc; - case 1: - return (VehicleHash)veh.Model.Hash == VehicleHash.Valkyrie - || (VehicleHash)veh.Model.Hash == VehicleHash.Valkyrie2 - || (VehicleHash)veh.Model.Hash == VehicleHash.Technical - || (VehicleHash)veh.Model.Hash == VehicleHash.Technical2 - || (VehicleHash)veh.Model.Hash == VehicleHash.Technical3 - || (VehicleHash)veh.Model.Hash == VehicleHash.HalfTrack - || (VehicleHash)veh.Model.Hash == VehicleHash.Barrage; - case 2: - return (VehicleHash)veh.Model.Hash == VehicleHash.Valkyrie - || (VehicleHash)veh.Model.Hash == VehicleHash.Valkyrie2 - || (VehicleHash)veh.Model.Hash == VehicleHash.Barrage; - case 3: - return (VehicleHash)veh.Model.Hash == VehicleHash.Limo2 - || (VehicleHash)veh.Model.Hash == VehicleHash.Dinghy5; - case 7: - return (VehicleHash)veh.Model.Hash == VehicleHash.Insurgent; - } - - return false; - } - public static bool IsOnTurretSeat(this Ped P) - { - if (P.CurrentVehicle == null) { return false; } - return IsTurretSeat(P.CurrentVehicle, (int)P.SeatIndex); - } - - - - [DllImport("kernel32.dll")] - public static extern ulong GetTickCount64(); - - } - /// - /// - /// - public static class MathExtensions - { - /// - /// - /// - public static Vector3 ToVector(this Quaternion vec) - { - return new Vector3() - { - X = vec.X, - Y = vec.Y, - Z = vec.Z - }; - } - - /// - /// - /// - public static Quaternion ToQuaternion(this Vector3 vec, float vW = 0.0f) - { - return new Quaternion() - { - X = vec.X, - Y = vec.Y, - Z = vec.Z, - W = vW - }; - } - - public static float Denormalize(this float h) - { - return h < 0f ? h + 360f : h; - } - - public static float ToRadians(this float val) - { - return (float)(Math.PI / 180) * val; - } - - public static Vector3 ToRadians(this Vector3 i) - { - return new Vector3() - { - X = ToRadians(i.X), - Y = ToRadians(i.Y), - Z = ToRadians(i.Z), - }; - } - - public static Quaternion ToQuaternion(this Vector3 vect) - { - vect = new Vector3() - { - X = vect.X.Denormalize() * -1, - Y = vect.Y.Denormalize() - 180f, - Z = vect.Z.Denormalize() - 180f, - }; - - vect = vect.ToRadians(); - - float rollOver2 = vect.Z * 0.5f; - float sinRollOver2 = (float)Math.Sin((double)rollOver2); - float cosRollOver2 = (float)Math.Cos((double)rollOver2); - float pitchOver2 = vect.Y * 0.5f; - float sinPitchOver2 = (float)Math.Sin((double)pitchOver2); - float cosPitchOver2 = (float)Math.Cos((double)pitchOver2); - float yawOver2 = vect.X * 0.5f; // pitch - float sinYawOver2 = (float)Math.Sin((double)yawOver2); - float cosYawOver2 = (float)Math.Cos((double)yawOver2); - Quaternion result = new Quaternion() - { - X = cosYawOver2 * cosPitchOver2 * cosRollOver2 + sinYawOver2 * sinPitchOver2 * sinRollOver2, - Y = cosYawOver2 * cosPitchOver2 * sinRollOver2 - sinYawOver2 * sinPitchOver2 * cosRollOver2, - Z = cosYawOver2 * sinPitchOver2 * cosRollOver2 + sinYawOver2 * cosPitchOver2 * sinRollOver2, - W = sinYawOver2 * cosPitchOver2 * cosRollOver2 - cosYawOver2 * sinPitchOver2 * sinRollOver2 - }; - return result; - } - public static double DegToRad(double deg) - { - return deg * Math.PI / 180.0; - } - public static Vector3 ToEulerRotation(this Vector3 dir,Vector3 up) - { - var rot = Quaternion.LookRotation(dir.Normalized,up).ToEulerAngles().ToDegree(); - return rot; - - } - public static Vector3 ToDegree(this Vector3 radian) - { - return radian*(float)(180/Math.PI); - } - public static Vector3 ToEulerAngles(this Quaternion q) - { - Vector3 angles = new Vector3(); - - // roll / x - double sinr_cosp = 2 * (q.W * q.X + q.Y * q.Z); - double cosr_cosp = 1 - 2 * (q.X * q.X + q.Y * q.Y); - angles.X = (float)Math.Atan2(sinr_cosp, cosr_cosp); - - // pitch / y - double sinp = 2 * (q.W * q.Y - q.Z * q.X); - if (Math.Abs(sinp) >= 1) - { - angles.Y = CopySign(Math.PI / 2, sinp); - } - else - { - angles.Y = (float)Math.Asin(sinp); - } - - // yaw / z - double siny_cosp = 2 * (q.W * q.Z + q.X * q.Y); - double cosy_cosp = 1 - 2 * (q.Y * q.Y + q.Z * q.Z); - angles.Z = (float)Math.Atan2(siny_cosp, cosy_cosp); - - return angles; - } - private static float CopySign(double x, double y) - { - bool isPositive = y>=0; - if (isPositive) - { - if (x>=0) { return (float)x; } else { return (float)-x; } - } - else - { - if (x>=0) { return (float)-x; } else { return (float)x; } - - } - } - public static double AngelTo(this Vector3 v1, Vector3 v2) - { - return Math.Acos(v1.GetCosTheta(v2)); - } - public static float GetCosTheta(this Vector3 v1, Vector3 v2) - { - - return Vector3.Dot(v1, v2)/(v1.Length()*v2.Length()); - } - } - -} diff --git a/Client/Networking/Chat.cs b/Client/Networking/Chat.cs index 3950c8d..10d66e6 100644 --- a/Client/Networking/Chat.cs +++ b/Client/Networking/Chat.cs @@ -8,7 +8,7 @@ using GTA.Native; namespace RageCoop.Client { - public class Chat + internal class Chat { private readonly Scaleform MainScaleForm; diff --git a/Client/Networking/DownloadManager.cs b/Client/Networking/DownloadManager.cs index 2751a0b..34625ff 100644 --- a/Client/Networking/DownloadManager.cs +++ b/Client/Networking/DownloadManager.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; namespace RageCoop.Client { - public static class DownloadManager + internal static class DownloadManager { private static readonly List _downloadFiles = new List(); private static readonly Dictionary _streams = new Dictionary(); diff --git a/Client/Networking/Networking.cs b/Client/Networking/Networking.cs index 57f8b9e..400ce9f 100644 --- a/Client/Networking/Networking.cs +++ b/Client/Networking/Networking.cs @@ -31,7 +31,7 @@ namespace RageCoop.Client // 623c92c287cc392406e7aaaac1c0f3b0 = RAGECOOP NetPeerConfiguration config = new NetPeerConfiguration("623c92c287cc392406e7aaaac1c0f3b0") { - AutoFlushSendQueue = true + AutoFlushSendQueue = false }; config.EnableMessageType(NetIncomingMessageType.ConnectionLatencyUpdated); @@ -62,7 +62,6 @@ namespace RageCoop.Client PedID = Main.LocalPlayerID, Username = Main.Settings.Username, ModVersion = Main.CurrentVersion, - NPCsAllowed = false }.Pack(outgoingMessage); Client.Connect(ip[0], short.Parse(ip[1]), outgoingMessage); @@ -80,6 +79,7 @@ namespace RageCoop.Client { try { + Client.FlushSendQueue(); ReceiveMessages(); } catch (Exception ex) diff --git a/Client/Networking/Receive.cs b/Client/Networking/Receive.cs index 6ce7f3a..bda3306 100644 --- a/Client/Networking/Receive.cs +++ b/Client/Networking/Receive.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using Lidgren.Network; using RageCoop.Core; using GTA; +using RageCoop.Client.Menus; using GTA.Math; using GTA.Native; @@ -36,7 +37,7 @@ namespace RageCoop.Client { case NetConnectionStatus.InitiatedConnect: #if !NON_INTERACTIVE - Main.MainMenu.InitiateConnectionMenuSetting(); + CoopMenu.InitiateConnectionMenuSetting(); #endif Main.QueueAction(() => { GTA.UI.Notification.Show("~y~Trying to connect..."); return true; }); break; @@ -53,17 +54,13 @@ namespace RageCoop.Client Packets.Handshake handshakePacket = new Packets.Handshake(); handshakePacket.Unpack(data); - // Main.LocalNetHandle = handshakePacket.NetHandle; - Main.NPCsAllowed = handshakePacket.NPCsAllowed; - - #if !NON_INTERACTIVE #endif COOPAPI.Connected(); Main.QueueAction(() => { - Main.MainMenu.ConnectedMenuSetting(); + CoopMenu.ConnectedMenuSetting(); Main.MainChat.Init(); PlayerList.Cleanup(); GTA.UI.Notification.Show("~g~Connected!"); @@ -78,9 +75,7 @@ namespace RageCoop.Client // Reset all values Latency = 0; - Main.QueueAction(() => { Main.CleanUpWorld();}); - - Main.NPCsAllowed = false; + Main.QueueAction(() => Main.CleanUpWorld()); if (Main.MainChat.Focused) { @@ -90,7 +85,7 @@ namespace RageCoop.Client Main.QueueAction(() => Main.CleanUp()); #if !NON_INTERACTIVE - Main.MainMenu.DisconnectedMenuSetting(); + CoopMenu.DisconnectedMenuSetting(); #endif COOPAPI.Disconnected(reason); @@ -227,8 +222,7 @@ namespace RageCoop.Client { Packets.Mod packet = new Packets.Mod(); packet.Unpack(data); - COOPAPI.ModPacketReceived(packet.NetHandle, packet.Name, packet.CustomPacketID, packet.Bytes); - + // Need to do some stuff here } break; case PacketTypes.FileTransferTick: @@ -370,6 +364,7 @@ namespace RageCoop.Client v.BrakePower=packet.BrakePower; v.Velocity=packet.Velocity; v.RotationVelocity=packet.RotationVelocity; + v.DeluxoWingRatio=packet.DeluxoWingRatio; v.LastSynced=Main.Ticked; } private static void VehicleStateSync(Packets.VehicleStateSync packet) diff --git a/Client/Networking/Send.cs b/Client/Networking/Send.cs index ec4f26e..5c0771a 100644 --- a/Client/Networking/Send.cs +++ b/Client/Networking/Send.cs @@ -83,6 +83,7 @@ namespace RageCoop.Client ThrottlePower = veh.ThrottlePower, BrakePower = veh.BrakePower, }; + if (v.MainVehicle.Model.Hash==1483171323) { packet.DeluxoWingRatio=v.MainVehicle.GetDeluxoWingRatio(); } Send(packet,ConnectionChannel.VehicleSync); } public static void SendVehicleState(SyncedVehicle v) @@ -149,27 +150,6 @@ namespace RageCoop.Client Client.SendMessage(outgoingMessage, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Chat); Client.FlushSendQueue(); -#if DEBUG - if (ShowNetworkInfo) - { - BytesSend += outgoingMessage.LengthBytes; - } -#endif - } - public static void SendModData(long target, string modName, byte customID, byte[] bytes) - { - NetOutgoingMessage outgoingMessage = Client.CreateMessage(); - new Packets.Mod() - { - // NetHandle = Main.LocalNetHandle, - Target = target, - Name = modName, - CustomPacketID = customID, - Bytes = bytes - }.Pack(outgoingMessage); - Client.SendMessage(outgoingMessage, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Mod); - Client.FlushSendQueue(); - #if DEBUG if (ShowNetworkInfo) { @@ -193,19 +173,6 @@ namespace RageCoop.Client } #endif } - public static void SendTriggerEvent(string eventName, params object[] args) - { - NetOutgoingMessage outgoingMessage = Client.CreateMessage(); - - new Packets.ServerClientEvent() - { - EventName = eventName, - Args = new List(args) - }.Pack(outgoingMessage); - - Client.SendMessage(outgoingMessage, NetDeliveryMethod.ReliableUnordered, (byte)ConnectionChannel.Event); - Client.FlushSendQueue(); - } #endregion } } diff --git a/Client/PlayerList.cs b/Client/PlayerList.cs index d13942b..4643eb9 100644 --- a/Client/PlayerList.cs +++ b/Client/PlayerList.cs @@ -30,7 +30,7 @@ namespace RageCoop.Client if ((Util.GetTickCount64() - Pressed) < 5000 && !Main.MainChat.Focused #if !NON_INTERACTIVE - && !Main.MainMenu.MenuPool.AreAnyVisible + && !Menus.CoopMenu.MenuPool.AreAnyVisible #endif ) { diff --git a/Client/RageCoop.Client.csproj b/Client/RageCoop.Client.csproj index 6639004..38558f9 100644 --- a/Client/RageCoop.Client.csproj +++ b/Client/RageCoop.Client.csproj @@ -123,12 +123,15 @@ - + + + + - + @@ -142,13 +145,13 @@ - + - + diff --git a/Client/Sync/Entities/SyncedEntity.cs b/Client/Sync/Entities/SyncedEntity.cs index 69372e8..f11b457 100644 --- a/Client/Sync/Entities/SyncedEntity.cs +++ b/Client/Sync/Entities/SyncedEntity.cs @@ -8,7 +8,7 @@ using GTA.Math; namespace RageCoop.Client { - public abstract class SyncedEntity + internal abstract class SyncedEntity { /// diff --git a/Client/Sync/Entities/SyncedPed.cs b/Client/Sync/Entities/SyncedPed.cs index b031fac..1d8ed25 100644 --- a/Client/Sync/Entities/SyncedPed.cs +++ b/Client/Sync/Entities/SyncedPed.cs @@ -14,7 +14,7 @@ namespace RageCoop.Client /// /// ? /// - public partial class SyncedPed:SyncedEntity + internal class SyncedPed:SyncedEntity { #region CONSTRUCTORS diff --git a/Client/Sync/Entities/SyncedVehicle.cs b/Client/Sync/Entities/SyncedVehicle.cs index 8e573a3..ed3cbb2 100644 --- a/Client/Sync/Entities/SyncedVehicle.cs +++ b/Client/Sync/Entities/SyncedVehicle.cs @@ -11,7 +11,7 @@ using RageCoop.Core; namespace RageCoop.Client { - public class SyncedVehicle : SyncedEntity + internal class SyncedVehicle : SyncedEntity { #region -- CONSTRUCTORS -- @@ -89,7 +89,7 @@ namespace RageCoop.Client /// VehicleSeat,PedID /// public Dictionary Passengers { get; set; } - + public float DeluxoWingRatio { get; set; } = -1; private long _lastPositionCalibrated { get; set; } #endregion @@ -148,9 +148,11 @@ namespace RageCoop.Client MainVehicle.Rotation = Rotation; MainVehicle.RotationVelocity = RotationVelocity; } - _vehicleStopTime = Util.GetTickCount64(); + if (DeluxoWingRatio!=-1) + { + MainVehicle.SetDeluxoWingRatio(DeluxoWingRatio); + } #endregion - if (LastStateSynced>LastUpdated) { #region -- SYNC STATE -- diff --git a/Client/Util/MathExtensions.cs b/Client/Util/MathExtensions.cs new file mode 100644 index 0000000..2836f29 --- /dev/null +++ b/Client/Util/MathExtensions.cs @@ -0,0 +1,149 @@ +using System; +using GTA.Math; + +namespace RageCoop.Client +{ + + internal static class MathExtensions + { + /// + /// + /// + public static Vector3 ToVector(this Quaternion vec) + { + return new Vector3() + { + X = vec.X, + Y = vec.Y, + Z = vec.Z + }; + } + + /// + /// + /// + public static Quaternion ToQuaternion(this Vector3 vec, float vW = 0.0f) + { + return new Quaternion() + { + X = vec.X, + Y = vec.Y, + Z = vec.Z, + W = vW + }; + } + + public static float Denormalize(this float h) + { + return h < 0f ? h + 360f : h; + } + + public static float ToRadians(this float val) + { + return (float)(Math.PI / 180) * val; + } + + public static Vector3 ToRadians(this Vector3 i) + { + return new Vector3() + { + X = ToRadians(i.X), + Y = ToRadians(i.Y), + Z = ToRadians(i.Z), + }; + } + + public static Quaternion ToQuaternion(this Vector3 vect) + { + vect = new Vector3() + { + X = vect.X.Denormalize() * -1, + Y = vect.Y.Denormalize() - 180f, + Z = vect.Z.Denormalize() - 180f, + }; + + vect = vect.ToRadians(); + + float rollOver2 = vect.Z * 0.5f; + float sinRollOver2 = (float)Math.Sin((double)rollOver2); + float cosRollOver2 = (float)Math.Cos((double)rollOver2); + float pitchOver2 = vect.Y * 0.5f; + float sinPitchOver2 = (float)Math.Sin((double)pitchOver2); + float cosPitchOver2 = (float)Math.Cos((double)pitchOver2); + float yawOver2 = vect.X * 0.5f; // pitch + float sinYawOver2 = (float)Math.Sin((double)yawOver2); + float cosYawOver2 = (float)Math.Cos((double)yawOver2); + Quaternion result = new Quaternion() + { + X = cosYawOver2 * cosPitchOver2 * cosRollOver2 + sinYawOver2 * sinPitchOver2 * sinRollOver2, + Y = cosYawOver2 * cosPitchOver2 * sinRollOver2 - sinYawOver2 * sinPitchOver2 * cosRollOver2, + Z = cosYawOver2 * sinPitchOver2 * cosRollOver2 + sinYawOver2 * cosPitchOver2 * sinRollOver2, + W = sinYawOver2 * cosPitchOver2 * cosRollOver2 - cosYawOver2 * sinPitchOver2 * sinRollOver2 + }; + return result; + } + public static double DegToRad(double deg) + { + return deg * Math.PI / 180.0; + } + public static Vector3 ToEulerRotation(this Vector3 dir, Vector3 up) + { + var rot = Quaternion.LookRotation(dir.Normalized, up).ToEulerAngles().ToDegree(); + return rot; + + } + public static Vector3 ToDegree(this Vector3 radian) + { + return radian*(float)(180/Math.PI); + } + public static Vector3 ToEulerAngles(this Quaternion q) + { + Vector3 angles = new Vector3(); + + // roll / x + double sinr_cosp = 2 * (q.W * q.X + q.Y * q.Z); + double cosr_cosp = 1 - 2 * (q.X * q.X + q.Y * q.Y); + angles.X = (float)Math.Atan2(sinr_cosp, cosr_cosp); + + // pitch / y + double sinp = 2 * (q.W * q.Y - q.Z * q.X); + if (Math.Abs(sinp) >= 1) + { + angles.Y = CopySign(Math.PI / 2, sinp); + } + else + { + angles.Y = (float)Math.Asin(sinp); + } + + // yaw / z + double siny_cosp = 2 * (q.W * q.Z + q.X * q.Y); + double cosy_cosp = 1 - 2 * (q.Y * q.Y + q.Z * q.Z); + angles.Z = (float)Math.Atan2(siny_cosp, cosy_cosp); + + return angles; + } + private static float CopySign(double x, double y) + { + bool isPositive = y>=0; + if (isPositive) + { + if (x>=0) { return (float)x; } else { return (float)-x; } + } + else + { + if (x>=0) { return (float)-x; } else { return (float)x; } + + } + } + public static double AngelTo(this Vector3 v1, Vector3 v2) + { + return Math.Acos(v1.GetCosTheta(v2)); + } + public static float GetCosTheta(this Vector3 v1, Vector3 v2) + { + + return Vector3.Dot(v1, v2)/(v1.Length()*v2.Length()); + } + } +} diff --git a/Client/Util/PedExtensions.cs b/Client/Util/PedExtensions.cs new file mode 100644 index 0000000..fd43f83 --- /dev/null +++ b/Client/Util/PedExtensions.cs @@ -0,0 +1,389 @@ +using System; +using System.IO; +using System.Xml.Serialization; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using RageCoop.Core; +using GTA; +using GTA.Native; +using GTA.Math; +using System.Linq; +using System.Diagnostics; + +namespace RageCoop.Client +{ + internal static partial class PedExtensions + { + + public static bool IsBetween(this T item, T start, T end) + { + return Comparer.Default.Compare(item, start) >= 0 && Comparer.Default.Compare(item, end) <= 0; + } + + public static bool Compare(this Dictionary item, Dictionary item2) + { + if (item == null || item2 == null || item.Count != item2.Count) + { + return false; + } + + foreach (KeyValuePair pair in item) + { + if (item2.TryGetValue(pair.Key, out Y value) && Equals(value, pair.Value)) + { + continue; + } + + // TryGetValue() or Equals failed + return false; + } + + // No difference between item and item2 + return true; + } + + + + + #region PED + + public static byte GetPedSpeed(this Ped ped) + { + if (ped.IsSprinting) + { + return 3; + } + if (ped.IsRunning) + { + return 2; + } + if (ped.IsWalking) + { + return 1; + } + + return 0; + } + + public static Dictionary GetPedClothes(this Ped ped) + { + Dictionary result = new Dictionary(); + for (byte i = 0; i < 11; i++) + { + short mod = Function.Call(Hash.GET_PED_DRAWABLE_VARIATION, ped.Handle, i); + result.Add(i, mod); + } + return result; + } + + public static PedDataFlags GetPedFlags(this Ped ped) + { + PedDataFlags flags = PedDataFlags.None; + + if (ped.IsAiming || ped.IsOnTurretSeat()) + { + flags |= PedDataFlags.IsAiming; + } + + + if (ped.IsReloading) + { + flags |= PedDataFlags.IsReloading; + } + + if (ped.IsJumping) + { + flags |= PedDataFlags.IsJumping; + } + + if (ped.IsRagdoll) + { + flags |= PedDataFlags.IsRagdoll; + } + + if (ped.IsOnFire) + { + flags |= PedDataFlags.IsOnFire; + } + + if (ped.IsInParachuteFreeFall) + { + flags |= PedDataFlags.IsInParachuteFreeFall; + } + + if (ped.ParachuteState == ParachuteState.Gliding) + { + flags |= PedDataFlags.IsParachuteOpen; + } + + bool climbingLadder = ped.IsTaskActive(TaskType.CTaskGoToAndClimbLadder); + if (climbingLadder) + { + flags |= PedDataFlags.IsOnLadder; + } + + if (ped.IsVaulting && !climbingLadder) + { + flags |= PedDataFlags.IsVaulting; + } + + if (ped.IsInCover || ped.IsGoingIntoCover) + { + flags |=PedDataFlags.IsInCover; + } + return flags; + } + + public static string[] GetReloadingAnimation(this Ped ped) + { + switch (ped.Weapons.Current.Hash) + { + case WeaponHash.Revolver: + case WeaponHash.RevolverMk2: + case WeaponHash.DoubleActionRevolver: + case WeaponHash.NavyRevolver: + return new string[2] { "anim@weapons@pistol@revolver_str", "reload_aim" }; + case WeaponHash.APPistol: + return new string[2] { "weapons@pistol@ap_pistol_str", "reload_aim" }; + case WeaponHash.Pistol50: + return new string[2] { "weapons@pistol@pistol_50_str", "reload_aim" }; + case WeaponHash.Pistol: + case WeaponHash.PistolMk2: + case WeaponHash.PericoPistol: + case WeaponHash.SNSPistol: + case WeaponHash.SNSPistolMk2: + case WeaponHash.HeavyPistol: + case WeaponHash.VintagePistol: + case WeaponHash.CeramicPistol: + case WeaponHash.MachinePistol: + return new string[2] { "weapons@pistol@pistol_str", "reload_aim" }; + case WeaponHash.AssaultRifle: + case WeaponHash.AssaultrifleMk2: + return new string[2] { "weapons@rifle@hi@assault_rifle_str", "reload_aim" }; + case WeaponHash.SniperRifle: + return new string[2] { "weapons@rifle@hi@sniper_rifle_str", "reload_aim" }; + case WeaponHash.HeavySniper: + case WeaponHash.HeavySniperMk2: + return new string[2] { "weapons@rifle@lo@sniper_heavy_str", "reload_aim" }; + case WeaponHash.PumpShotgun: + case WeaponHash.PumpShotgunMk2: + return new string[2] { "weapons@rifle@pump_str", "reload_aim" }; + case WeaponHash.Railgun: + return new string[2] { "weapons@rifle@lo@rail_gun_str", "reload_aim" }; + case WeaponHash.SawnOffShotgun: + return new string[2] { "weapons@rifle@lo@sawnoff_str", "reload_aim" }; + case WeaponHash.AssaultShotgun: + return new string[2] { "weapons@rifle@lo@shotgun_assault_str", "reload_aim" }; + case WeaponHash.BullpupShotgun: + return new string[2] { "weapons@rifle@lo@shotgun_bullpup_str", "reload_aim" }; + case WeaponHash.AdvancedRifle: + return new string[2] { "weapons@submg@advanced_rifle_str", "reload_aim" }; + case WeaponHash.CarbineRifle: + case WeaponHash.CarbineRifleMk2: + case WeaponHash.CompactRifle: + return new string[2] { "weapons@rifle@lo@carbine_str", "reload_aim" }; + case WeaponHash.Gusenberg: + return new string[2] { "anim@weapons@machinegun@gusenberg_str", "reload_aim" }; + case WeaponHash.Musket: + return new string[2] { "anim@weapons@musket@musket_str", "reload_aim" }; + case WeaponHash.FlareGun: + return new string[2] { "anim@weapons@pistol@flare_str", "reload_aim" }; + case WeaponHash.SpecialCarbine: + case WeaponHash.SpecialCarbineMk2: + return new string[2] { "anim@weapons@rifle@lo@spcarbine_str", "reload_aim" }; + case WeaponHash.CombatPDW: + return new string[2] { "anim@weapons@rifle@lo@pdw_str", "reload_aim" }; + case WeaponHash.BullpupRifle: + case WeaponHash.BullpupRifleMk2: + return new string[2] { "anim@weapons@submg@bullpup_rifle_str", "reload_aim" }; + case WeaponHash.AssaultSMG: + return new string[2] { "weapons@submg@assault_smg_str", "reload_aim" }; + case WeaponHash.MicroSMG: + case WeaponHash.MiniSMG: + return new string[2] { "weapons@submg@lo@micro_smg_str", "reload_aim" }; + case WeaponHash.SMG: + case WeaponHash.SMGMk2: + return new string[2] { "weapons@rifle@smg_str", "reload_aim" }; + case WeaponHash.GrenadeLauncher: + case WeaponHash.GrenadeLauncherSmoke: + case WeaponHash.CompactGrenadeLauncher: + return new string[2] { "weapons@heavy@grenade_launcher_str", "reload_aim" }; + case WeaponHash.RPG: + case WeaponHash.Firework: + return new string[2] { "weapons@heavy@rpg_str", "reload_aim" }; + case WeaponHash.CombatMG: + case WeaponHash.CombatMGMk2: + return new string[2] { "weapons@machinegun@combat_mg_str", "reload_aim" }; + case WeaponHash.MG: + return new string[2] { "weapons@machinegun@mg_str", "reload_aim" }; + default: + Main.Logger.Warning($"~r~Reloading failed! Weapon ~g~[{ped.Weapons.Current.Hash}]~r~ could not be found!"); + return null; + } + } + + public static VehicleSeat GetNearestSeat(this Ped ped, Vehicle veh, float distanceToignoreDoors = 50f) + { + float num = 99f; + int result = -2; + Dictionary dictionary = new Dictionary(); + dictionary.Add("door_dside_f", -1); + dictionary.Add("door_pside_f", 0); + dictionary.Add("door_dside_r", 1); + dictionary.Add("door_pside_r", 2); + foreach (string text in dictionary.Keys) + { + bool flag = veh.Bones[text].Position != Vector3.Zero; + if (flag) + { + float num2 = ped.Position.DistanceTo(Function.Call(Hash.GET_WORLD_POSITION_OF_ENTITY_BONE, new InputArgument[] + { + veh, + veh.Bones[text].Index + })); + bool flag2 = (num2 < distanceToignoreDoors) && (num2 < num)&& IsSeatUsableByPed(ped, veh, dictionary[text]); + if (flag2) + { + num = num2; + result = dictionary[text]; + } + } + } + return (VehicleSeat)result; + } + public static bool IsSeatUsableByPed(Ped ped, Vehicle veh, int _seat) + { + VehicleSeat seat = (VehicleSeat)_seat; + bool result = false; + bool flag = veh.IsSeatFree(seat); + if (flag) + { + result = true; + } + else + { + + bool isDead = veh.GetPedOnSeat(seat).IsDead; + if (isDead) + { + result = true; + } + else + { + int num = Function.Call(Hash.GET_RELATIONSHIP_BETWEEN_PEDS, new InputArgument[] + { + ped, + veh.GetPedOnSeat(seat) + }); + bool flag2 = num > 2; + if (flag2) + { + result = true; + } + } + + } + return result; + } + public static bool IsTaskActive(this Ped p,TaskType task) + { + return Function.Call(Hash.GET_IS_TASK_ACTIVE, p.Handle, task); + } + public static Vector3 GetAimCoord(this Ped p) + { + var weapon = p.Weapons.CurrentWeaponObject; + + var v = p.CurrentVehicle; + // Rhino + if (v!=null && v.Model.Hash==782665360) + { + return v.Bones[35].Position+v.Bones[35].ForwardVector*100; + } + if (p.IsOnTurretSeat()) { return p.GetLookingCoord(); } + if (weapon!=null) + { + // Not very accurate, but doesn't matter + Vector3 dir = weapon.RightVector; + return weapon.Position+dir*20; + + } + return GetLookingCoord(p); + } + public static Vector3 GetLookingCoord(this Ped p) + { + EntityBone b = p.Bones[Bone.FacialForehead]; + Vector3 v = b.UpVector.Normalized; + return b.Position+200*v; + } + + public static void StayInCover(this Ped p) + { + Function.Call(Hash.TASK_STAY_IN_COVER, p); + } + public static VehicleSeat GetSeatTryingToEnter(this Ped p) + { + return (VehicleSeat)Function.Call(Hash.GET_SEAT_PED_IS_TRYING_TO_ENTER, p); + } + + + + #endregion + + + + + + + + + public static bool IsTurretSeat(this Vehicle veh, int seat) + { + if (!Function.Call(Hash.DOES_VEHICLE_HAVE_WEAPONS, veh.Handle)) + { + return false; + } + + switch (seat) + { + case -1: + return (VehicleHash)veh.Model.Hash == VehicleHash.Rhino + || (VehicleHash)veh.Model.Hash == VehicleHash.Khanjari + || (VehicleHash)veh.Model.Hash == VehicleHash.FireTruck + || (VehicleHash)veh.Model.Hash == VehicleHash.Riot2 + || (VehicleHash)veh.Model.Hash == VehicleHash.Cerberus + || (VehicleHash)veh.Model.Hash == VehicleHash.Cerberus2 + || (VehicleHash)veh.Model.Hash == VehicleHash.Cerberus3; + case 0: + return (VehicleHash)veh.Model.Hash == VehicleHash.Apc; + case 1: + return (VehicleHash)veh.Model.Hash == VehicleHash.Valkyrie + || (VehicleHash)veh.Model.Hash == VehicleHash.Valkyrie2 + || (VehicleHash)veh.Model.Hash == VehicleHash.Technical + || (VehicleHash)veh.Model.Hash == VehicleHash.Technical2 + || (VehicleHash)veh.Model.Hash == VehicleHash.Technical3 + || (VehicleHash)veh.Model.Hash == VehicleHash.HalfTrack + || (VehicleHash)veh.Model.Hash == VehicleHash.Barrage; + case 2: + return (VehicleHash)veh.Model.Hash == VehicleHash.Valkyrie + || (VehicleHash)veh.Model.Hash == VehicleHash.Valkyrie2 + || (VehicleHash)veh.Model.Hash == VehicleHash.Barrage; + case 3: + return (VehicleHash)veh.Model.Hash == VehicleHash.Limo2 + || (VehicleHash)veh.Model.Hash == VehicleHash.Dinghy5; + case 7: + return (VehicleHash)veh.Model.Hash == VehicleHash.Insurgent; + } + + return false; + } + public static bool IsOnTurretSeat(this Ped P) + { + if (P.CurrentVehicle == null) { return false; } + return IsTurretSeat(P.CurrentVehicle, (int)P.SeatIndex); + } + + + + + } +} diff --git a/Client/Misc/TaskType.cs b/Client/Util/TaskType.cs similarity index 100% rename from Client/Misc/TaskType.cs rename to Client/Util/TaskType.cs diff --git a/Client/Util/Util.cs b/Client/Util/Util.cs new file mode 100644 index 0000000..654d2cc --- /dev/null +++ b/Client/Util/Util.cs @@ -0,0 +1,190 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using GTA.Math; +using GTA; +using GTA.Native; +using System.IO; +using System.Xml.Serialization; +using System.Runtime.InteropServices; + +namespace RageCoop.Client +{ + internal static class Util + { + #region -- POINTER -- + private static int _steeringAngleOffset { get; set; } + + public static unsafe void NativeMemory() + { + IntPtr address; + + address = Game.FindPattern("\x74\x0A\xF3\x0F\x11\xB3\x1C\x09\x00\x00\xEB\x25", "xxxxxx????xx"); + if (address != IntPtr.Zero) + { + _steeringAngleOffset = *(int*)(address + 6) + 8; + } + + // breaks some stuff. + /* + address = Game.FindPattern("\x32\xc0\xf3\x0f\x11\x09", "xxxxxx"); // Weapon / Radio slowdown + if (address != IntPtr.Zero) + { + for (int i = 0; i < 6; i++) + { + *(byte*)(address + i).ToPointer() = 0x90; + } + } + */ + } + + public static unsafe void CustomSteeringAngle(this Vehicle veh, float value) + { + IntPtr address = new IntPtr((long)veh.MemoryAddress); + if (address == IntPtr.Zero || _steeringAngleOffset == 0) + { + return; + } + + *(float*)(address + _steeringAngleOffset).ToPointer() = value; + } + #endregion + #region MATH + public static Vector3 LinearVectorLerp(Vector3 start, Vector3 end, ulong currentTime, int duration) + { + return new Vector3() + { + X = LinearFloatLerp(start.X, end.X, currentTime, duration), + Y = LinearFloatLerp(start.Y, end.Y, currentTime, duration), + Z = LinearFloatLerp(start.Z, end.Z, currentTime, duration), + }; + } + + public static float LinearFloatLerp(float start, float end, ulong currentTime, int duration) + { + return (end - start) * currentTime / duration + start; + } + + public static float Lerp(float from, float to, float fAlpha) + { + return (from * (1.0f - fAlpha)) + (to * fAlpha); //from + (to - from) * fAlpha + } + + public static Vector3 RotationToDirection(Vector3 rotation) + { + double z = MathExtensions.DegToRad(rotation.Z); + double x = MathExtensions.DegToRad(rotation.X); + double num = Math.Abs(Math.Cos(x)); + + return new Vector3 + { + X = (float)(-Math.Sin(z) * num), + Y = (float)(Math.Cos(z) * num), + Z = (float)Math.Sin(x) + }; + } + + + #endregion + public static Settings ReadSettings() + { + XmlSerializer ser = new XmlSerializer(typeof(Settings)); + + string path = Directory.GetCurrentDirectory() + "\\Scripts\\RageCoop\\RageCoop.Client.Settings.xml"; + Settings settings = null; + + if (File.Exists(path)) + { + using (FileStream stream = File.OpenRead(path)) + { + settings = (RageCoop.Client.Settings)ser.Deserialize(stream); + } + + using (FileStream stream = new FileStream(path, FileMode.Truncate, FileAccess.ReadWrite)) + { + ser.Serialize(stream, settings); + } + } + else + { + using (FileStream stream = File.OpenWrite(path)) + { + ser.Serialize(stream, settings = new Settings()); + } + } + + return settings; + } + public static void SaveSettings() + { + try + { + string path = Directory.GetCurrentDirectory() + "\\Scripts\\RageCoop\\RageCoop.Client.Settings.xml"; + + using (FileStream stream = new FileStream(path, File.Exists(path) ? FileMode.Truncate : FileMode.Create, FileAccess.ReadWrite)) + { + XmlSerializer ser = new XmlSerializer(typeof(Settings)); + ser.Serialize(stream, Main.Settings); + } + } + catch (Exception ex) + { + GTA.UI.Notification.Show("Error saving player settings: " + ex.Message); + } + } + + [DllImport("kernel32.dll")] + public static extern ulong GetTickCount64(); + public static Vector3 PredictPosition(this Entity e, bool applyDefault = true) + { + return e.Position+e.Velocity*((applyDefault ? SyncParameters.PositioinPredictionDefault : 0)+Networking.Latency); + } + + public static Model ModelRequest(this int hash) + { + Model model = new Model(hash); + + if (!model.IsValid) + { + //GTA.UI.Notification.Show("~y~Not valid!"); + return null; + } + + if (!model.IsLoaded) + { + return model.Request(1000) ? model : null; + } + + return model; + } + public static void SetOnFire(this Entity e, bool toggle) + { + if (toggle) + { + Function.Call(Hash.START_ENTITY_FIRE, e.Handle); + } + else + { + Function.Call(Hash.STOP_ENTITY_FIRE, e.Handle); + } + } + + public static SyncedPed GetSyncEntity(this Ped p) + { + if (p == null) { return null; } + var c = EntityPool.GetPedByHandle(p.Handle); + if (c==null) { EntityPool.Add(c=new SyncedPed(p)); } + return c; + } + + public static SyncedVehicle GetSyncEntity(this Vehicle veh) + { + if (veh == null) { return null; } + var v = EntityPool.GetVehicleByHandle(veh.Handle); + if (v==null) { EntityPool.Add(v=new SyncedVehicle(veh)); } + return v; + } + } +} diff --git a/Client/Util/VehicleExtensions.cs b/Client/Util/VehicleExtensions.cs new file mode 100644 index 0000000..438348c --- /dev/null +++ b/Client/Util/VehicleExtensions.cs @@ -0,0 +1,289 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using GTA; +using GTA.Native; +using RageCoop.Core; +using GTA.Math; + +namespace RageCoop.Client +{ + internal static class VehicleExtensions + { + #region VEHICLE + + public static VehicleDataFlags GetVehicleFlags(this Vehicle veh) + { + VehicleDataFlags flags = 0; + + if (veh.IsEngineRunning) + { + flags |= VehicleDataFlags.IsEngineRunning; + } + + if (veh.AreLightsOn) + { + flags |= VehicleDataFlags.AreLightsOn; + } + + if (veh.BrakePower >= 0.01f) + { + flags |= VehicleDataFlags.AreBrakeLightsOn; + } + + if (veh.AreHighBeamsOn) + { + flags |= VehicleDataFlags.AreHighBeamsOn; + } + + if (veh.IsSirenActive) + { + flags |= VehicleDataFlags.IsSirenActive; + } + + if (veh.IsDead) + { + flags |= VehicleDataFlags.IsDead; + } + + if (Function.Call(Hash.IS_HORN_ACTIVE, veh.Handle)) + { + flags |= VehicleDataFlags.IsHornActive; + } + + if (veh.IsSubmarineCar && Function.Call(Hash._GET_IS_SUBMARINE_VEHICLE_TRANSFORMED, veh.Handle)) + { + flags |= VehicleDataFlags.IsTransformed; + } + + if (veh.HasRoof && (veh.RoofState == VehicleRoofState.Opened || veh.RoofState == VehicleRoofState.Opening)) + { + flags |= VehicleDataFlags.RoofOpened; + } + + + if (veh.IsAircraft) + { + flags |= VehicleDataFlags.IsAircraft; + } + if (veh.Model.Hash==1483171323 && veh.IsDeluxoHovering()) + { + flags|= VehicleDataFlags.IsDeluxoHovering; + } + + + + return flags; + } + public static bool HasFlag(this PedDataFlags flagToCheck, PedDataFlags flag) + { + return (flagToCheck & flag)!=0; + } + + public static bool HasFlag(this VehicleDataFlags flagToCheck, VehicleDataFlags flag) + { + return (flagToCheck & flag)!=0; + } + + + public static Dictionary GetWeaponComponents(this Weapon weapon) + { + Dictionary result = null; + + if (weapon.Components.Count > 0) + { + result = new Dictionary(); + + foreach (var comp in weapon.Components) + { + result.Add((uint)comp.ComponentHash, comp.Active); + } + } + + return result; + } + + public static Dictionary GetVehicleMods(this VehicleModCollection mods) + { + Dictionary result = new Dictionary(); + foreach (VehicleMod mod in mods.ToArray()) + { + result.Add((int)mod.Type, mod.Index); + } + return result; + } + + public static VehicleDamageModel GetVehicleDamageModel(this Vehicle veh) + { + // Broken windows + byte brokenWindows = 0; + for (int i = 0; i < 8; i++) + { + if (!veh.Windows[(VehicleWindowIndex)i].IsIntact) + { + brokenWindows |= (byte)(1 << i); + } + } + + // Broken doors + byte brokenDoors = 0; + byte openedDoors = 0; + foreach (VehicleDoor door in veh.Doors) + { + if (door.IsBroken) + { + brokenDoors |= (byte)(1 << (byte)door.Index); + } + else if (door.IsOpen) + { + openedDoors |= (byte)(1 << (byte)door.Index); + } + } + + + // Bursted tires + short burstedTires = 0; + foreach (VehicleWheel wheel in veh.Wheels.GetAllWheels()) + { + if (wheel.IsBursted) + { + burstedTires |= (short)(1 << (int)wheel.BoneId); + } + } + + return new VehicleDamageModel() + { + BrokenDoors = brokenDoors, + OpenedDoors = openedDoors, + BrokenWindows = brokenWindows, + BurstedTires = burstedTires, + LeftHeadLightBroken = (byte)(veh.IsLeftHeadLightBroken ? 1 : 0), + RightHeadLightBroken = (byte)(veh.IsRightHeadLightBroken ? 1 : 0) + }; + } + + public static Dictionary GetPassengers(this Vehicle veh) + { + Dictionary ps = new Dictionary(); + var d = veh.Driver; + if (d!=null&&d.IsSittingInVehicle()) + { + ps.Add(-1, d.GetSyncEntity().ID); + } + foreach (Ped p in veh.Passengers) + { + if (p.IsSittingInVehicle()) + { + ps.Add((int)p.SeatIndex, (int)p.GetSyncEntity().ID); + } + } + return ps; + } + + + public static void SetDeluxoHoverState(this Vehicle deluxo, bool hover) + { + Function.Call(Hash._SET_VEHICLE_HOVER_TRANSFORM_PERCENTAGE, deluxo, hover ? 1f : 0f); + } + public static bool IsDeluxoHovering(this Vehicle deluxo) + { + return Math.Abs(deluxo.Bones[27].ForwardVector.GetCosTheta(deluxo.ForwardVector)-1)>0.05; + } + public static void SetDeluxoWingRatio(this Vehicle v, float ratio) + { + Function.Call(Hash._SET_SPECIALFLIGHT_WING_RATIO, v, ratio); + } + public static float GetDeluxoWingRatio(this Vehicle v) + { + return v.Bones[99].Position.DistanceTo(v.Bones[92].Position)-1.43f; + } + public static float GetNozzleAngel(this Vehicle plane) + { + return Function.Call(Hash._GET_VEHICLE_FLIGHT_NOZZLE_POSITION, plane); + } + public static bool HasNozzle(this Vehicle v) + { + + switch (v.Model.Hash) + { + // Hydra + case 970385471: + return true; + + // Avenger + case -2118308144: + return true; + + // Avenger + case 408970549: + return true; + + } + return false; + } + public static void SetNozzleAngel(this Vehicle plane, float ratio) + { + Function.Call(Hash.SET_VEHICLE_FLIGHT_NOZZLE_POSITION, plane, ratio); + } + public static void SetDamageModel(this Vehicle veh, VehicleDamageModel model, bool leavedoors = true) + { + for (int i = 0; i < 8; i++) + { + var door = veh.Doors[(VehicleDoorIndex)i]; + if ((model.BrokenDoors & (byte)(1 << i)) != 0) + { + door.Break(leavedoors); + } + else if (door.IsBroken) + { + // The vehicle can only fix a door if the vehicle was completely fixed + veh.Repair(); + return; + } + if ((model.OpenedDoors & (byte)(1 << i)) != 0) + { + if ((!door.IsOpen)&&(!door.IsBroken)) + { + door.Open(); + } + } + else if (door.IsOpen) + { + if (!door.IsBroken) { door.Close(); } + } + + if ((model.BrokenWindows & (byte)(1 << i)) != 0) + { + veh.Windows[(VehicleWindowIndex)i].Smash(); + } + else if (!veh.Windows[(VehicleWindowIndex)i].IsIntact) + { + veh.Windows[(VehicleWindowIndex)i].Repair(); + } + } + + foreach (VehicleWheel wheel in veh.Wheels) + { + if ((model.BurstedTires & (short)(1 << (int)wheel.BoneId)) != 0) + { + if (!wheel.IsBursted) + { + wheel.Puncture(); + wheel.Burst(); + } + } + else if (wheel.IsBursted) + { + wheel.Fix(); + } + } + + veh.IsLeftHeadLightBroken = model.LeftHeadLightBroken > 0; + veh.IsRightHeadLightBroken = model.RightHeadLightBroken > 0; + } + + #endregion + } +} diff --git a/Client/Misc/WeaponUtil.cs b/Client/Util/WeaponUtil.cs similarity index 100% rename from Client/Misc/WeaponUtil.cs rename to Client/Util/WeaponUtil.cs diff --git a/Core/Packets/Packets.cs b/Core/Packets/Packets.cs index 9e147eb..67b3b46 100644 --- a/Core/Packets/Packets.cs +++ b/Core/Packets/Packets.cs @@ -191,7 +191,6 @@ namespace RageCoop.Core IsOnLadder = 1 << 8, IsVaulting = 1 << 9, IsInCover=1<< 10, - IsPlayer=1<<11, } #region ===== VEHICLE DATA ===== @@ -239,10 +238,6 @@ namespace RageCoop.Core { public class Mod : Packet { - public long NetHandle { get; set; } - - public long Target { get; set; } - public string Name { get; set; } public byte CustomPacketID { get; set; } @@ -256,12 +251,6 @@ namespace RageCoop.Core List byteArray = new List(); - // Write NetHandle - byteArray.AddRange(BitConverter.GetBytes(NetHandle)); - - // Write Target - byteArray.AddRange(BitConverter.GetBytes(Target)); - // Write Name byte[] nameBytes = Encoding.UTF8.GetBytes(Name); byteArray.AddRange(BitConverter.GetBytes(nameBytes.Length)); @@ -286,12 +275,6 @@ namespace RageCoop.Core #region NetIncomingMessageToPacket BitReader reader = new BitReader(array); - // Read NetHandle - NetHandle = reader.ReadLong(); - - // Read Target - Target = reader.ReadLong(); - // Read Name int nameLength = reader.ReadInt(); Name = reader.ReadString(nameLength); @@ -683,9 +666,6 @@ namespace RageCoop.Core #endregion // ===== NATIVECALL ===== } - /// - /// ? - /// public static class CoopSerializer { /// diff --git a/Core/Packets/PlayerPackets.cs b/Core/Packets/PlayerPackets.cs index 6b2a06c..0c58af9 100644 --- a/Core/Packets/PlayerPackets.cs +++ b/Core/Packets/PlayerPackets.cs @@ -16,8 +16,6 @@ namespace RageCoop.Core public string ModVersion { get; set; } - public bool NPCsAllowed { get; set; } - public override void Pack(NetOutgoingMessage message) { #region PacketToNetOutGoingMessage @@ -38,9 +36,6 @@ namespace RageCoop.Core byteArray.AddRange(BitConverter.GetBytes(modVersionBytes.Length)); byteArray.AddRange(modVersionBytes); - // Write NpcsAllowed - byteArray.Add(NPCsAllowed ? (byte)0x01 : (byte)0x00); - byte[] result = byteArray.ToArray(); message.Write(result.Length); @@ -63,9 +58,6 @@ namespace RageCoop.Core // Read ModVersion int modVersionLength = reader.ReadInt(); ModVersion = reader.ReadString(modVersionLength); - - // Read NPCsAllowed - NPCsAllowed = reader.ReadBool(); #endregion } } diff --git a/Core/Packets/VehiclePackets.cs b/Core/Packets/VehiclePackets.cs index db160fa..566f9ba 100644 --- a/Core/Packets/VehiclePackets.cs +++ b/Core/Packets/VehiclePackets.cs @@ -219,7 +219,7 @@ namespace RageCoop.Core public float ThrottlePower { get; set; } public float BrakePower { get; set; } public float SteeringAngle { get; set; } - + public float DeluxoWingRatio { get; set; } = -1; public override void Pack(NetOutgoingMessage message) { @@ -252,6 +252,10 @@ namespace RageCoop.Core // Write vehicle steering angle byteArray.AddFloat(SteeringAngle); + if (DeluxoWingRatio!=-1) + { + byteArray.AddFloat(DeluxoWingRatio); + } byte[] result = byteArray.ToArray(); @@ -289,6 +293,10 @@ namespace RageCoop.Core // Read steering angle SteeringAngle = reader.ReadFloat(); + if (reader.CanRead(4)) + { + DeluxoWingRatio= reader.ReadFloat(); + } #endregion } } diff --git a/Core/PlayerData.cs b/Core/PlayerData.cs index 003e2aa..e51e7ad 100644 --- a/Core/PlayerData.cs +++ b/Core/PlayerData.cs @@ -1,30 +1,33 @@ using System.Linq; +using System.Runtime.CompilerServices; using GTA.Math; + +[assembly: InternalsVisibleTo("RageCoop.Server")] +[assembly: InternalsVisibleTo("RageCoop.Client")] namespace RageCoop.Core { public class PlayerData { - public string Username { get; set; } + public string Username { get; internal set; } /// /// Universal character ID. /// public int PedID { - get; set; + get; internal set; } /// - /// Universal vehicle ID. + /// The ID of player's last vehicle. /// - public int VehicleID { get; set; } - public bool IsInVehicle { get; internal set; } - public Vector3 Position { get; set; } + public int VehicleID { get; internal set; } + public Vector3 Position { get;internal set; } /// /// Player Latency in second. /// - public float Latency { get; set; } - public int Health { get; set; } + public float Latency { get; internal set; } + public int Health { get; internal set; } } } diff --git a/Server/Client.cs b/Server/Client.cs index 7c55e5f..326d314 100644 --- a/Server/Client.cs +++ b/Server/Client.cs @@ -8,19 +8,19 @@ namespace RageCoop.Server { public class Client { - public long ClientID = 0; + public long NetID = 0; private float _currentLatency = 0f; public NetConnection Connection { get; set; } public float Latency { get => _currentLatency; - set + internal set { _currentLatency = value; if ((value * 1000f) > Server.MainSettings.MaxLatency) { - Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == ClientID)?.Disconnect($"Too high latency [{value * 1000f}/{(float)Server.MainSettings.MaxLatency}]"); + Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == NetID)?.Disconnect($"Too high latency [{value * 1000f}/{(float)Server.MainSettings.MaxLatency}]"); } } } @@ -28,7 +28,7 @@ namespace RageCoop.Server private readonly Dictionary _customData = new(); private long _callbacksCount = 0; public readonly Dictionary> Callbacks = new(); - public bool FilesReceived { get; set; } = false; + public bool FilesReceived { get;internal set; } = false; public bool FilesSent = false; #region CUSTOMDATA FUNCTIONS @@ -66,7 +66,7 @@ namespace RageCoop.Server #region FUNCTIONS public void Kick(string reason) { - Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == ClientID)?.Disconnect(reason); + Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == NetID)?.Disconnect(reason); } public void Kick(string[] reason) { @@ -77,7 +77,7 @@ namespace RageCoop.Server { try { - NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == ClientID); + NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == NetID); if (userConnection == null) { return; @@ -95,10 +95,10 @@ namespace RageCoop.Server { try { - NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == ClientID); + NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == NetID); if (userConnection == null) { - Logging.Error($"[Client->SendNativeCall(ulong hash, params object[] args)]: Connection \"{ClientID}\" not found!"); + Logging.Error($"[Client->SendNativeCall(ulong hash, params object[] args)]: Connection \"{NetID}\" not found!"); return; } @@ -128,10 +128,10 @@ namespace RageCoop.Server { try { - NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == ClientID); + NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == NetID); if (userConnection == null) { - Logging.Error($"[Client->SendNativeResponse(Action callback, ulong hash, Type type, params object[] args)]: Connection \"{ClientID}\" not found!"); + Logging.Error($"[Client->SendNativeResponse(Action callback, ulong hash, Type type, params object[] args)]: Connection \"{NetID}\" not found!"); return; } @@ -189,10 +189,10 @@ namespace RageCoop.Server public void SendCleanUpWorld() { - NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == ClientID); + NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == NetID); if (userConnection == null) { - Logging.Error($"[Client->SendCleanUpWorld()]: Connection \"{ClientID}\" not found!"); + Logging.Error($"[Client->SendCleanUpWorld()]: Connection \"{NetID}\" not found!"); return; } @@ -205,7 +205,7 @@ namespace RageCoop.Server { try { - NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == ClientID); + NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == NetID); if (userConnection == null) { return; @@ -214,8 +214,6 @@ namespace RageCoop.Server NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage(); new Packets.Mod() { - NetHandle = 0, - Target = 0, Name = modName, CustomPacketID = customID, Bytes = bytes @@ -239,7 +237,7 @@ namespace RageCoop.Server try { - NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == ClientID); + NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == NetID); if (userConnection == null) { return; diff --git a/Server/Server.cs b/Server/Server.cs index 4b7a315..a47d960 100644 --- a/Server/Server.cs +++ b/Server/Server.cs @@ -122,8 +122,6 @@ namespace RageCoop.Server "\"players\": \"" + MainNetServer.ConnectionsCount + "\", " + "\"maxPlayers\": \"" + MainSettings.MaxPlayers + "\", " + "\"allowlist\": \"" + _mainAllowlist.Username.Any() + "\", " + - "\"mods\": \"" + MainSettings.ModsAllowed + "\", " + - "\"npcs\": \"" + MainSettings.NpcsAllowed + "\"" + " }"; HttpResponseMessage response = null; @@ -237,7 +235,7 @@ namespace RageCoop.Server { if (!client.FilesSent) { - DownloadManager.InsertClient(client.ClientID); + DownloadManager.InsertClient(client.NetID); client.FilesSent = true; } }); @@ -446,63 +444,6 @@ namespace RageCoop.Server } } break; - case PacketTypes.Mod: - { - if (MainSettings.ModsAllowed) - { - try - { - int len = message.ReadInt32(); - byte[] data = message.ReadBytes(len); - - Packets.Mod packet = new Packets.Mod(); - packet.Unpack(data); - - bool resourceResult = false; - if (RunningResource != null) - { - if (RunningResource.InvokeModPacketReceived(packet.NetHandle, packet.Target, packet.Name, packet.CustomPacketID, packet.Bytes)) - { - resourceResult = true; - } - } - - if (!resourceResult && packet.Target != -1) - { - NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage(); - packet.Pack(outgoingMessage); - - if (packet.Target != 0) - { - NetConnection target = MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == packet.Target); - if (target == null) - { - Logging.Error($"[ModPacket] target \"{packet.Target}\" not found!"); - } - else - { - // Send back to target - MainNetServer.SendMessage(outgoingMessage, target, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Mod); - } - } - else - { - // Send back to all players - MainNetServer.SendMessage(outgoingMessage, MainNetServer.Connections, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Mod); - } - } - } - catch (Exception e) - { - DisconnectAndLog(message.SenderConnection, type, e); - } - } - else - { - message.SenderConnection.Disconnect("Mods are not allowed!"); - } - } - break; case PacketTypes.FileTransferComplete: { try @@ -518,7 +459,7 @@ namespace RageCoop.Server Client client = Util.GetClientByID(message.SenderConnection.RemoteUniqueIdentifier); if (client != null && !client.FilesReceived) { - DownloadManager.TryToRemoveClient(client.ClientID, packet.ID); + DownloadManager.TryToRemoveClient(client.NetID, packet.ID); } } } @@ -656,7 +597,7 @@ namespace RageCoop.Server { foreach(Client c in Clients.Values) { - MainNetServer.Connections.FindAll(x => x.RemoteUniqueIdentifier != c.ClientID).ForEach(x => + MainNetServer.Connections.FindAll(x => x.RemoteUniqueIdentifier != c.NetID).ForEach(x => { NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage(); new Packets.PlayerInfoUpdate() @@ -734,7 +675,7 @@ namespace RageCoop.Server Clients.Add(local.RemoteUniqueIdentifier, tmpClient = new Client() { - ClientID = local.RemoteUniqueIdentifier, + NetID = local.RemoteUniqueIdentifier, Connection=local, Player = new() { @@ -753,7 +694,6 @@ namespace RageCoop.Server PedID = packet.PedID, Username = string.Empty, ModVersion = string.Empty, - NPCsAllowed = MainSettings.NpcsAllowed }.Pack(outgoingMessage); // Accept the connection and send back a new handshake packet with the connection ID @@ -846,7 +786,7 @@ namespace RageCoop.Server return; } - Clients.Remove(localClient.ClientID); + Clients.Remove(localClient.NetID); if (RunningResource != null) { @@ -870,14 +810,13 @@ namespace RageCoop.Server } + NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage(); + packet.Pack(outgoingMessage); foreach (var c in Clients.Values) { - if (c.ClientID==client.ClientID) { continue; } - NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage(); - packet.Pack(outgoingMessage); + if (c.NetID==client.NetID) { continue; } MainNetServer.SendMessage(outgoingMessage, c.Connection, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.PedSync); } - if (RunningResource != null && packet.ID==client.Player.PedID) { RunningResource.InvokePlayerUpdate(client); @@ -899,7 +838,7 @@ namespace RageCoop.Server foreach (var c in Clients.Values) { - if (c.ClientID==client.ClientID) { continue; } + if (c.NetID==client.NetID) { continue; } NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage(); packet.Pack(outgoingMessage); MainNetServer.SendMessage(outgoingMessage, c.Connection, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.PedSync); @@ -912,13 +851,15 @@ namespace RageCoop.Server { return; } - bool isPlayer = packet.Flag.HasFlag(PedDataFlags.IsPlayer); + bool isPlayer = packet.ID==client.Player.PedID; if (isPlayer) { client.Player.Position=packet.Position; } + NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage(); + packet.Pack(outgoingMessage); foreach (var c in Clients.Values) { // Don't send data back - if (c.ClientID==client.ClientID) { continue; } + if (c.NetID==client.NetID) { continue; } // Check streaming distance if (isPlayer) @@ -932,12 +873,10 @@ namespace RageCoop.Server { continue; } - NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage(); - packet.Pack(outgoingMessage); MainNetServer.SendMessage(outgoingMessage,c.Connection, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.PedSync); } - if (RunningResource != null && packet.ID==client.Player.PedID) + if (RunningResource != null && isPlayer) { RunningResource.InvokePlayerUpdate(client); } @@ -952,7 +891,7 @@ namespace RageCoop.Server bool isPlayer = packet.ID==client.Player.VehicleID; foreach (var c in Clients.Values) { - if (c.ClientID==client.ClientID) { continue; } + if (c.NetID==client.NetID) { continue; } if (isPlayer) { // Player's vehicle @@ -981,7 +920,7 @@ namespace RageCoop.Server foreach (var c in Clients.Values) { - if (c.ClientID==client.ClientID) { continue; } + if (c.NetID==client.NetID) { continue; } NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage(); packet.Pack(outgoingMessage); MainNetServer.SendMessage(outgoingMessage, c.Connection, NetDeliveryMethod.UnreliableSequenced, (byte)ConnectionChannel.PedSync); diff --git a/Server/ServerScript.cs b/Server/ServerScript.cs index ffe26f1..9c0a5f5 100644 --- a/Server/ServerScript.cs +++ b/Server/ServerScript.cs @@ -55,8 +55,8 @@ namespace RageCoop.Server (localQueue.Dequeue() as Action)?.Invoke(); } - // 16 milliseconds to sleep to reduce CPU usage - Thread.Sleep(1000 / 60); + // 15 milliseconds to sleep to reduce CPU usage + Thread.Sleep(15); } _script.API.InvokeStop(); @@ -167,25 +167,6 @@ namespace RageCoop.Server /// Called when a new player sends data like health /// public event PlayerEvent OnPlayerUpdate; - /// - /// Called when a player has a new health value - /// - public event PlayerEvent OnPlayerHealthUpdate; - /// - /// Called when a player has a new position - /// - public event PlayerEvent OnPlayerPositionUpdate; - /// - /// Called when a player has a new position - /// - public event PlayerEvent OnPlayerPedHandleUpdate; - /// - /// Called when a player has a new position - /// - public event PlayerEvent OnPlayerVehicleHandleUpdate; - /// - /// Called when a player sends a packet from another modification - /// public event ModEvent OnModPacketReceived; public void InvokeTick(long tick) @@ -245,31 +226,35 @@ namespace RageCoop.Server /// The name of the modification that will receive the data /// The ID to check what this data is /// The serialized data - /// The list of connections (players) that will receive the data - public static void SendModPacketToAll(string modName, byte customID, byte[] bytes, List netHandleList = null) + /// The list of player ID (PedID) that will receive the data + public static void SendModPacketToAll(string modName, byte customID, byte[] bytes, List playerList = null) { try - { - List connections = netHandleList == null - ? Server.MainNetServer.Connections - : Server.MainNetServer.Connections.FindAll(c => netHandleList.Contains(c.RemoteUniqueIdentifier)); - // A resource can be calling this function on disconnect of the last player in the server and we will + {// A resource can be calling this function on disconnect of the last player in the server and we will // get an empty connection list, make sure connections has at least one handle in it - if (connections.Count > 0) + NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage(); + new Packets.Mod() { - NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage(); - new Packets.Mod() - { - NetHandle = 0, - Target = 0, - Name = modName, - CustomPacketID = customID, - Bytes = bytes - }.Pack(outgoingMessage); - Logging.Debug($"SendModPacketToAll recipients list {connections.Count}"); - Server.MainNetServer.SendMessage(outgoingMessage, connections, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Mod); - Server.MainNetServer.FlushSendQueue(); + Name = modName, + CustomPacketID = customID, + Bytes = bytes + }.Pack(outgoingMessage); + if (playerList==null) + { + Server.MainNetServer.SendMessage(outgoingMessage, Server.MainNetServer.Connections, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Mod); } + else + { + foreach(var c in Server.Clients.Values) + { + if (playerList.Contains(c.Player.PedID)) + { + Server.MainNetServer.SendMessage(outgoingMessage, c.Connection, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Mod); + } + } + + } + Server.MainNetServer.FlushSendQueue(); } catch (Exception e) { @@ -314,32 +299,10 @@ namespace RageCoop.Server } } - /// - /// Get all connections as a list of NetHandle(long) - /// - /// All connections(NetHandle) as a List - public static List GetAllConnections() - { - List result = new(); - - Server.MainNetServer.Connections.ForEach(x => result.Add(x.RemoteUniqueIdentifier)); - - return result; - } - - /// - /// Get the count of all connections - /// - /// The count of all connections as an integer - public static int GetAllClientsCount() - { - return Server.Clients.Count; - } - /// /// Get a list of all Clients /// - /// All Clients as a dictionary indexed by ClientID + /// All clients as a dictionary indexed by NetID public static Dictionary GetAllClients() { return Server.Clients; diff --git a/Server/Settings.cs b/Server/Settings.cs index bc64456..a922e65 100644 --- a/Server/Settings.cs +++ b/Server/Settings.cs @@ -8,8 +8,6 @@ public string Name { get; set; } = "RAGECOOP server"; public string WelcomeMessage { get; set; } = "Welcome on this server :)"; public string Resource { get; set; } = ""; - public bool NpcsAllowed { get; set; } = true; - public bool ModsAllowed { get; set; } = false; public bool UPnP { get; set; } = true; public bool AnnounceSelf { get; set; } = false; public string MasterServer { get; set; } = "https://ragecoop.online/gtav/servers"; diff --git a/Server/Util.cs b/Server/Util.cs index 9247897..0650b47 100644 --- a/Server/Util.cs +++ b/Server/Util.cs @@ -53,7 +53,7 @@ namespace RageCoop.Server return null; } - return Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == client.ClientID); + return Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == client.NetID); } // Return a list of all connections but not the local connection