diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..74b5b13 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +[*.cs] + +# CS0649: Field 'VehicleInfo.Name' is never assigned to, and will always have its default value null +dotnet_diagnostic.CS0649.severity = silent diff --git a/Client/DataDumper/Program.cs b/Client/DataDumper/Program.cs new file mode 100644 index 0000000..2594c3d --- /dev/null +++ b/Client/DataDumper/Program.cs @@ -0,0 +1,27 @@ +using RageCoop.Core; +using Newtonsoft.Json; +using System.Data.HashFunction.Jenkins; +using System; + +namespace RageCoop.Client.DataDumper +{ + public static class Program + { + + static UInt32 Hash(string key) + { + int i = 0; + uint hash = 0; + while (i != key.Length) + { + hash += key[i++]; + hash += hash << 10; + hash ^= hash >> 6; + } + hash += hash << 3; + hash ^= hash >> 11; + hash += hash << 15; + return hash; + } + } +} \ No newline at end of file diff --git a/Client/DataDumper/RageCoop.Client.DataDumper.csproj b/Client/DataDumper/RageCoop.Client.DataDumper.csproj new file mode 100644 index 0000000..c90ff82 --- /dev/null +++ b/Client/DataDumper/RageCoop.Client.DataDumper.csproj @@ -0,0 +1,19 @@ + + + + net6.0 + enable + exe + ..\..\bin\Debug\Client.DataDumper + + + + + + + + + + + + diff --git a/Client/Loader/LoaderContext.cs b/Client/Loader/LoaderContext.cs index d9404ee..57ea0be 100644 --- a/Client/Loader/LoaderContext.cs +++ b/Client/Loader/LoaderContext.cs @@ -189,7 +189,11 @@ namespace RageCoop.Client.Loader { CurrentDomain.DoKeyEvent(keys, status); } - + public override object InitializeLifetimeService() + { + // Return null to avoid lifetime restriction on the marshaled object. + return null; + } public void Dispose() { lock (this) diff --git a/Client/Scripts/DevTools/DevTool.cs b/Client/Scripts/DevTools/DevTool.cs index 638bdd5..c8c59c9 100644 --- a/Client/Scripts/DevTools/DevTool.cs +++ b/Client/Scripts/DevTools/DevTool.cs @@ -1,5 +1,6 @@ using GTA; using GTA.Math; +using GTA.Native; using System; using System.Drawing; using System.Threading; @@ -11,174 +12,80 @@ namespace RageCoop.Client internal class DevTool : Script { public static Vehicle ToMark; - public static bool UseSecondary = false; - public static int Current = 0; - public static int Secondary = 0; - public static MuzzleDir Direction = MuzzleDir.Forward; public static Script Instance; public DevTool() { Util.StartUpCheck(); Instance = this; Tick += OnTick; - KeyDown += OnKeyDown; Pause(); } - - private void OnKeyDown(object sender, KeyEventArgs e) - { - if (ToMark == null || (!ToMark.Exists())) { return; } - if (DevToolMenu.Menu.SelectedItem == DevToolMenu.boneIndexItem) - { - - switch (e.KeyCode) - { - case Keys.Right: - Current++; - break; - case Keys.Left: - Current--; - break; - } - } - else if (DevToolMenu.Menu.SelectedItem == DevToolMenu.secondaryBoneIndexItem) - { - - switch (e.KeyCode) - { - case Keys.Right: - Secondary++; - break; - case Keys.Left: - Secondary--; - break; - } - } - Update(); - } - private static void Update() - { - - if (Current > ToMark.Bones.Count - 1) - { - Current = 0; - } - else if (Current < 0) - { - Current = ToMark.Bones.Count - 1; - } - DevToolMenu.boneIndexItem.AltTitle = Current.ToString(); - if (Secondary > ToMark.Bones.Count - 1) - { - Secondary = 0; - } - else if (Secondary < 0) - { - Secondary = ToMark.Bones.Count - 1; - } - DevToolMenu.secondaryBoneIndexItem.AltTitle = Secondary.ToString(); - } private void OnTick(object sender, EventArgs e) { - if (ToMark == null || !ToMark.Exists()) { return; } - Update(); - Draw(Current); - if (UseSecondary) + var wb = Game.Player.Character?.Weapons?.CurrentWeaponObject?.Bones["gun_muzzle"]; + if (wb?.IsValid==true) { - Draw(Secondary); + World.DrawLine(wb.Position, wb.Position + wb.RightVector, Color.Blue); } - - } - private static void Draw(int boneindex) - { - var bone = ToMark.Bones[boneindex]; - World.DrawLine(bone.Position, bone.Position + 2 * bone.ForwardVector, Color.Blue); - World.DrawLine(bone.Position, bone.Position + 2 * bone.UpVector, Color.Green); - World.DrawLine(bone.Position, bone.Position + 2 * bone.RightVector, Color.Yellow); - Vector3 todraw = bone.ForwardVector; - switch ((byte)Direction) + if (ToMark == null) return; + if (WeaponUtil.VehicleWeapons.TryGetValue((uint)(int)ToMark.Model, out var info)) { - case 0: - todraw = bone.ForwardVector; - break; - case 1: - todraw = bone.RightVector; - break; - case 2: - todraw = bone.UpVector; - break; - case 3: - todraw = bone.ForwardVector * -1; - break; - case 4: - todraw = bone.RightVector * -1; - break; - case 5: - todraw = bone.UpVector * -1; - break; - } - World.DrawLine(bone.Position, bone.Position + 10 * todraw, Color.Red); - } - public static void CopyToClipboard(MuzzleDir dir) - { - - if (ToMark != null) - { - string s; - if (UseSecondary) + foreach (var ws in info.Weapons) { - if ((byte)dir < 3) + foreach (var w in ws.Value.Bones) { - s = $@" - // {ToMark.DisplayName} - case {ToMark.Model.Hash}: - return BulletsShot%2==0 ? {Current} : {Secondary}; - "; - } - else - { - s = $@" - // {ToMark.DisplayName} - case {ToMark.Model.Hash}: - return BulletsShot%2==0 ? {Current} : {Secondary}; - "; + DrawBone(w.BoneName, ws.Value.Name); } } - else - { - if ((byte)dir < 3) - { - s = $@" - // {ToMark.DisplayName} - case {ToMark.Model.Hash}: - return {Current}; - "; - } - else - { - s = $@" - // {ToMark.DisplayName} - case {ToMark.Model.Hash}: - return {Current}; - "; - } - } - Thread thread = new Thread(() => Clipboard.SetText(s)); - thread.SetApartmentState(ApartmentState.STA); - thread.Start(); - thread.Join(); - GTA.UI.Notification.Show("Copied to clipboard, please paste it on the GitHub issue page!"); + } + } + void FindAndDraw() + { + DrawBone("weapon_1a"); + DrawBone("weapon_1b"); + DrawBone("weapon_1c"); + DrawBone("weapon_1d"); + DrawBone("weapon_2a"); + DrawBone("weapon_2b"); + DrawBone("weapon_2c"); + DrawBone("weapon_2d"); + DrawBone("weapon_3a"); + DrawBone("weapon_3b"); + DrawBone("weapon_3c"); + DrawBone("weapon_3d"); + DrawBone("weapon_4a"); + DrawBone("weapon_4b"); + DrawBone("weapon_4c"); + DrawBone("weapon_4d"); + DrawBone("weapon_1e"); + DrawBone("weapon_1f"); + DrawBone("weapon_1g"); + DrawBone("weapon_1h"); + DrawBone("weapon_2e"); + DrawBone("weapon_2f"); + DrawBone("weapon_2g"); + DrawBone("weapon_2h"); + DrawBone("weapon_3e"); + DrawBone("weapon_3f"); + DrawBone("weapon_3g"); + DrawBone("weapon_3h"); + DrawBone("weapon_4e"); + DrawBone("weapon_4f"); + DrawBone("weapon_4g"); + DrawBone("weapon_4h"); + } + void DrawBone(string name, string text = null) + { + text = text ?? name; + var b = ToMark.Bones[name]; + if (b.IsValid) + { + var start = b.Position; + var end = b.Position + b.ForwardVector * 5; + World.DrawLine(start, end, Color.AliceBlue); + Util.DrawTextFromCoord(end, text, 0.35f); } } } - internal enum MuzzleDir : byte - { - Forward = 0, - Right = 1, - Up = 2, - Backward = 3, - Left = 4, - Down = 5, - } } diff --git a/Client/Scripts/Menus/Sub/DevToolMenu.cs b/Client/Scripts/Menus/Sub/DevToolMenu.cs index a08bdf9..9d441a4 100644 --- a/Client/Scripts/Menus/Sub/DevToolMenu.cs +++ b/Client/Scripts/Menus/Sub/DevToolMenu.cs @@ -1,24 +1,37 @@ using GTA; using LemonUI.Menus; using System; +using System.Threading.Tasks; using System.Drawing; +using RageCoop.Client.Scripting; +using Console = GTA.Console; +using System.IO; +using Newtonsoft.Json; +using GTA.Native; namespace RageCoop.Client { + class AnimDic + { + public string DictionaryName; + public string[] Animations; + } internal static class DevToolMenu { - public static NativeMenu Menu = new NativeMenu("RAGECOOP", "DevTool", "Help with the development") + const string AnimationsPath = @"RageCoop\Data\animDictsCompact.json"; + public static NativeMenu Menu = new NativeMenu("RAGECOOP", "DevTool", "Internal testing tools") { UseMouse = false, Alignment = Main.Settings.FlipMenu ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left }; private static readonly NativeCheckboxItem enableItem = new NativeCheckboxItem("Enable"); + public static readonly NativeItem dumpItem = new NativeItem("Dump vehicle weapons"); + public static readonly NativeItem dumpFixItem = new NativeItem("Dump weapon fixes"); + public static readonly NativeItem dumpWHashItem = new NativeItem("Dump WeaponHash.cs"); + public static readonly NativeItem getAnimItem = new NativeItem("Get current animation"); + + public static readonly NativeItem dumpVWHashItem = new NativeItem("Dump VehicleWeaponHash.cs"); - private static readonly NativeCheckboxItem enableSecondaryItem = new NativeCheckboxItem("Secondary", "Enable if this vehicle have two muzzles"); - public static NativeItem boneIndexItem = new NativeItem("Current bone index"); - public static NativeItem secondaryBoneIndexItem = new NativeItem("Secondary bone index"); - public static NativeItem clipboardItem = new NativeItem("Copy to clipboard"); - public static NativeListItem dirItem = new NativeListItem("Direction"); static DevToolMenu() { Menu.Banner.Color = Color.FromArgb(225, 0, 0, 0); @@ -26,55 +39,70 @@ namespace RageCoop.Client enableItem.Activated += enableItem_Activated; enableItem.Checked = false; - enableSecondaryItem.CheckboxChanged += EnableSecondaryItem_Changed; - secondaryBoneIndexItem.Enabled = false; - clipboardItem.Activated += ClipboardItem_Activated; - dirItem.ItemChanged += DirItem_ItemChanged; - foreach (var d in Enum.GetValues(typeof(MuzzleDir))) + dumpItem.Activated += DumpItem_Activated; + dumpVWHashItem.Activated += (s,e)=> WeaponUtil.DumpVehicleWeaponHashes(); + dumpWHashItem.Activated += (s, e) => WeaponUtil.DumpWeaponHashes(); + dumpFixItem.Activated += (s, e) => WeaponUtil.DumpWeaponFix(); + getAnimItem.Activated += (s, e) => { - dirItem.Items.Add((MuzzleDir)d); - } - dirItem.SelectedIndex = 0; + if (File.Exists(AnimationsPath)) + { + var anims = JsonConvert.DeserializeObject(File.ReadAllText(AnimationsPath)); + foreach(var anim in anims) + { + foreach(var a in anim.Animations) + { + if (Function.Call(Hash.IS_ENTITY_PLAYING_ANIM, Main.P,anim.DictionaryName,a,3)) + { + Console.Info(anim.DictionaryName + " : " + a); + GTA.UI.Notification.Show(anim.DictionaryName+" : "+a); + } + } + } + } + else + { + GTA.UI.Notification.Show($"~r~{AnimationsPath} not found"); + } + }; Menu.Add(enableItem); - Menu.Add(boneIndexItem); - Menu.Add(enableSecondaryItem); - Menu.Add(secondaryBoneIndexItem); - Menu.Add(dirItem); - Menu.Add(clipboardItem); + Menu.Add(dumpItem); + Menu.Add(dumpVWHashItem); + Menu.Add(dumpWHashItem); + Menu.Add(dumpFixItem); + Menu.Add(getAnimItem); } - private static void EnableSecondaryItem_Changed(object sender, EventArgs e) + private static void DumpItem_Activated(object sender, EventArgs e) { - if (enableSecondaryItem.Checked) + dumpItem.Enabled = false; + Directory.CreateDirectory(@"RageCoop\Data\tmp"); + var input = @"RageCoop\Data\tmp\vehicles.json"; + var dumpLocation = @"RageCoop\Data\VehicleWeapons.json"; + try { - DevTool.UseSecondary = true; - secondaryBoneIndexItem.Enabled = true; + + VehicleWeaponInfo.Dump(input, dumpLocation); + Console.Info($"Weapon info dumped to " + dumpLocation); } - else + catch (Exception ex) { - DevTool.UseSecondary = false; - secondaryBoneIndexItem.Enabled = false; + Console.Error($"~r~" + ex.ToString()); + } + finally + { + dumpItem.Enabled = true; } - } - - private static void DirItem_ItemChanged(object sender, ItemChangedEventArgs e) - { - DevTool.Direction = dirItem.SelectedItem; - } - - private static void ClipboardItem_Activated(object sender, EventArgs e) - { - DevTool.CopyToClipboard(dirItem.SelectedItem); } private static void enableItem_Activated(object sender, EventArgs e) { if (enableItem.Checked) { - DevTool.Instance.Resume(); DevTool.ToMark = Game.Player.Character.CurrentVehicle; + DevTool.Instance.Resume(); } else { diff --git a/Client/Scripts/Networking/Receive.cs b/Client/Scripts/Networking/Receive.cs index 0ff84c9..21343a3 100644 --- a/Client/Scripts/Networking/Receive.cs +++ b/Client/Scripts/Networking/Receive.cs @@ -42,11 +42,10 @@ namespace RageCoop.Client } }; private static readonly AutoResetEvent _publicKeyReceived = new AutoResetEvent(false); - private static bool _recycle; public static void ProcessMessage(NetIncomingMessage message) { if (message == null) { return; } - _recycle = true; + var _recycle = true; switch (message.MessageType) { case NetIncomingMessageType.StatusChanged: @@ -293,7 +292,7 @@ namespace RageCoop.Client { recycle = false; // Dispatch to script thread - API.QueueAction(() => { SyncEvents.HandleEvent(packetType, msg); Peer.Recycle(msg); return true; }); + API.QueueAction(() => { SyncEvents.HandleEvent(packetType, msg); return true; }); } break; } diff --git a/Client/Scripts/Properties/AssemblyInfo.cs b/Client/Scripts/Properties/AssemblyInfo.cs index c803f2e..83ad61a 100644 --- a/Client/Scripts/Properties/AssemblyInfo.cs +++ b/Client/Scripts/Properties/AssemblyInfo.cs @@ -16,7 +16,7 @@ using System.Resources; // Version informationr( -[assembly: AssemblyVersion("1.5.6.1")] -[assembly: AssemblyFileVersion("1.5.6.1")] +[assembly: AssemblyVersion("1.5.6.98")] +[assembly: AssemblyFileVersion("1.5.6.98")] [assembly: NeutralResourcesLanguageAttribute( "en-US" )] diff --git a/Client/Scripts/RageCoop.Client.csproj b/Client/Scripts/RageCoop.Client.csproj index 4ae9576..c4bed45 100644 --- a/Client/Scripts/RageCoop.Client.csproj +++ b/Client/Scripts/RageCoop.Client.csproj @@ -128,6 +128,9 @@ + + .editorconfig + diff --git a/Client/Scripts/Sync/Entities/Ped/SyncedPed.cs b/Client/Scripts/Sync/Entities/Ped/SyncedPed.cs index aaad583..f0cac0a 100644 --- a/Client/Scripts/Sync/Entities/Ped/SyncedPed.cs +++ b/Client/Scripts/Sync/Entities/Ped/SyncedPed.cs @@ -175,7 +175,7 @@ namespace RageCoop.Client return; } - Vector3 targetPos = MainPed.Bones[Bone.IKHead].Position; + Vector3 targetPos = MainPed.Bones[Bone.IKHead].Position + Vector3.WorldUp * 0.5f; Point toDraw = default; if (Util.WorldToScreen(targetPos, ref toDraw)) { @@ -688,7 +688,6 @@ namespace RageCoop.Client } if (MainPed.IsOnTurretSeat()) { - // Function.Call(Hash.SET_VEHICLE_TURRET_SPEED_THIS_FRAME, MainPed.CurrentVehicle, 100); Function.Call(Hash.TASK_VEHICLE_AIM_AT_COORD, MainPed.Handle, AimCoords.X, AimCoords.Y, AimCoords.Z); } if (MainPed.VehicleWeapon == VehicleWeaponHash.Invalid) diff --git a/Client/Scripts/Sync/EntityPool.cs b/Client/Scripts/Sync/EntityPool.cs index 6bc2022..4d03a1d 100644 --- a/Client/Scripts/Sync/EntityPool.cs +++ b/Client/Scripts/Sync/EntityPool.cs @@ -43,7 +43,7 @@ namespace RageCoop.Client #endregion public static void Cleanup(bool keepPlayer = true, bool keepMine = true) { - foreach (var ped in PedsByID.Values) + foreach (var ped in PedsByID.Values.ToArray()) { if ((keepPlayer && (ped.ID == Main.LocalPlayerID)) || (keepMine && (ped.OwnerID == Main.LocalPlayerID))) { continue; } RemovePed(ped.ID); @@ -51,7 +51,7 @@ namespace RageCoop.Client PedsByID.Clear(); PedsByHandle.Clear(); - foreach (int id in new List(VehiclesByID.Keys)) + foreach (int id in VehiclesByID.Keys.ToArray()) { if (keepMine && (VehiclesByID[id].OwnerID == Main.LocalPlayerID)) { continue; } RemoveVehicle(id); @@ -59,7 +59,7 @@ namespace RageCoop.Client VehiclesByID.Clear(); VehiclesByHandle.Clear(); - foreach (var p in ProjectilesByID.Values) + foreach (var p in ProjectilesByID.Values.ToArray()) { if (p.Shooter.ID != Main.LocalPlayerID && p.MainProjectile != null && p.MainProjectile.Exists()) { diff --git a/Client/Scripts/Sync/SyncEvents.cs b/Client/Scripts/Sync/SyncEvents.cs index 125c748..d40aa6b 100644 --- a/Client/Scripts/Sync/SyncEvents.cs +++ b/Client/Scripts/Sync/SyncEvents.cs @@ -3,6 +3,7 @@ using GTA.Math; using Lidgren.Network; using RageCoop.Core; using System; +using System.Runtime.InteropServices; namespace RageCoop.Client { @@ -30,9 +31,7 @@ namespace RageCoop.Client { // Main.Logger.Trace($"bullet shot:{(WeaponHash)hash}"); - var start = owner.MainPed.GetMuzzlePosition(); - if (owner.MainPed.IsOnTurretSeat()) { start = owner.MainPed.Bones[Bone.SkelHead].Position; } if (start.DistanceTo(impactPosition) > 10) { // Reduce latency @@ -43,17 +42,8 @@ namespace RageCoop.Client public static void TriggerVehBulletShot(uint hash, Vehicle veh, SyncedPed owner) { - int i; - // ANNIHL - if (veh.Model.Hash == 837858166) - { - Networking.SendVehicleBullet(hash, owner, veh.Bones[35]); - Networking.SendVehicleBullet(hash, owner, veh.Bones[36]); - Networking.SendVehicleBullet(hash, owner, veh.Bones[37]); - Networking.SendVehicleBullet(hash, owner, veh.Bones[38]); - } - else if ((i = veh.GetMuzzleIndex()) != -1) + if ((i = veh.GetMuzzleIndex(owner.MainPed.VehicleWeapon)) != -1) { Networking.SendVehicleBullet(hash, owner, veh.Bones[i]); } @@ -72,8 +62,6 @@ namespace RageCoop.Client #region HANDLE public static ParticleEffectAsset CorePFXAsset = new ParticleEffectAsset("core"); - private static WeaponAsset _weaponAsset = default; - private static uint _lastWeaponHash; private static void HandlePedKilled(Packets.PedKilled p) { @@ -94,60 +82,21 @@ namespace RageCoop.Client } private static void HandleBulletShot(Vector3 start, Vector3 end, uint weaponHash, int ownerID) { - switch (weaponHash) - { - // Minigun, not working for some reason - case (uint)WeaponHash.Minigun: - weaponHash = 1176362416; - break; - - // Valkyire, not working for some reason - case 2756787765: - weaponHash = 1176362416; - break; - - // Tampa3, not working for some reason - case 3670375085: - weaponHash = 1176362416; - break; - - // Ruiner2, not working for some reason - case 50118905: - weaponHash = 1176362416; - break; - - // SAVAGE - case 1638077257: - weaponHash = (uint)VehicleWeaponHash.PlayerLazer; - break; - - case (uint)VehicleWeaponHash.PlayerBuzzard: - weaponHash = 1176362416; - break; - } - var p = EntityPool.GetPedByID(ownerID)?.MainPed; if (p == null) { p = Game.Player.Character; Main.Logger.Warning("Failed to find owner for bullet"); } + + var damage = (int)p.GetWeaponDamage(weaponHash); + weaponHash = WeaponUtil.GetWeaponFix(weaponHash); + if (!CorePFXAsset.IsLoaded) { CorePFXAsset.Request(); } - if (_lastWeaponHash != weaponHash) - { - _weaponAsset.MarkAsNoLongerNeeded(); - _weaponAsset = new WeaponAsset(weaponHash); - _lastWeaponHash = weaponHash; - } - if (!_weaponAsset.IsLoaded) { _weaponAsset.Request(); } - World.ShootBullet(start, end, p, _weaponAsset, (int)p.GetWeaponDamage(weaponHash)); + var asset = new WeaponAsset(weaponHash); + if (!asset.IsLoaded) { asset.Request(); } + World.ShootBullet(start, end, p, asset, damage); Prop w; - if (((w = p.Weapons.CurrentWeaponObject) != null) && (p.VehicleWeapon == VehicleWeaponHash.Invalid)) + var turret = false; + if ((((w = p.Weapons.CurrentWeaponObject) != null) && (p.VehicleWeapon == VehicleWeaponHash.Invalid)) || (turret = p.IsOnTurretSeat())) { - if (p.Weapons.Current.Components.GetSuppressorComponent().Active) - { - World.CreateParticleEffectNonLooped(CorePFXAsset, "muz_pistol_silencer", p.GetMuzzlePosition(), w.Rotation, 1); - } - else - { - World.CreateParticleEffectNonLooped(CorePFXAsset, WeaponUtil.GetFlashFX((WeaponHash)weaponHash), p.GetMuzzlePosition(), w.Rotation, 1); - } + World.CreateParticleEffectNonLooped(CorePFXAsset, p.Weapons.Current.Components.GetSuppressorComponent().Active ? "muz_pistol_silencer" : WeaponUtil.GetFlashFX((WeaponHash)weaponHash, turret), p.GetMuzzlePosition(), turret ? p.CurrentVehicle.GetMuzzleBone(p.VehicleWeapon).GetRotation() : w.Rotation, 1); } } public static void HandleVehicleBulletShot(Packets.VehicleBulletShot p) @@ -157,8 +106,8 @@ namespace RageCoop.Client if (v == null) { return; } var b = v.Bones[p.Bone]; World.CreateParticleEffectNonLooped(CorePFXAsset, - WeaponUtil.GetFlashFX((WeaponHash)p.WeaponHash), - b.Position, b.ForwardVector.ToEulerRotation(v.Bones[35].UpVector), 1); + WeaponUtil.GetFlashFX((WeaponHash)p.WeaponHash, true), + b.Position, b.GetRotation(), 1); } public static void HandleEvent(PacketType type, NetIncomingMessage msg) { @@ -166,8 +115,7 @@ namespace RageCoop.Client { case PacketType.BulletShot: { - Packets.BulletShot p = new Packets.BulletShot(); - p.Deserialize(msg); + var p = msg.GetPacket(); HandleBulletShot(p.StartPosition, p.EndPosition, p.WeaponHash, p.OwnerID); break; } diff --git a/Client/Scripts/Util/PedExtensions.cs b/Client/Scripts/Util/PedExtensions.cs index fdf5f00..56ad5fa 100644 --- a/Client/Scripts/Util/PedExtensions.cs +++ b/Client/Scripts/Util/PedExtensions.cs @@ -335,7 +335,11 @@ namespace RageCoop.Client { return v.Bones[35].Position + v.Bones[35].ForwardVector * 100; } - if (p.IsOnTurretSeat()) { return p.GetLookingCoord(); } + if (p.IsOnTurretSeat()) + { + var b = p.CurrentVehicle.GetMuzzleBone(p.VehicleWeapon); + return b.Position + b.ForwardVector * 50; + } if (weapon != null) { // Not very accurate, but doesn't matter @@ -459,6 +463,7 @@ namespace RageCoop.Client public static bool IsTurretSeat(this Vehicle veh, int seat) { + if (Function.Call(Hash.IS_TURRET_SEAT, veh, seat)) { return true; } if (!Function.Call(Hash.DOES_VEHICLE_HAVE_WEAPONS, veh.Handle)) { return false; diff --git a/Client/Scripts/Util/Util.cs b/Client/Scripts/Util/Util.cs index 550497b..088c0b8 100644 --- a/Client/Scripts/Util/Util.cs +++ b/Client/Scripts/Util/Util.cs @@ -1,6 +1,7 @@ using GTA; using GTA.Math; using GTA.Native; +using LemonUI.Elements; using Newtonsoft.Json; using RageCoop.Core; using System; @@ -14,6 +15,10 @@ namespace RageCoop.Client { internal static class Util { + public static Vector3 GetRotation(this EntityBone b) + { + return b.ForwardVector.ToEulerRotation(b.UpVector); + } public static void StartUpCheck() { if (AppDomain.CurrentDomain.GetData("RageCoop.Client.LoaderContext") == null) @@ -42,6 +47,21 @@ namespace RageCoop.Client return new SizeF(width, 1080f); } } + public static void DrawTextFromCoord(Vector3 coord, string text, float scale = 0.5f, Point offset = default) + { + Point toDraw = default; + if (WorldToScreen(coord, ref toDraw)) + { + toDraw.X += offset.X; + toDraw.Y += offset.Y; + new ScaledText(toDraw, text, scale, GTA.UI.Font.ChaletLondon) + { + Outline = true, + Alignment = GTA.UI.Alignment.Center, + Color = Color.White, + }.Draw(); + } + } public static bool WorldToScreen(Vector3 pos, ref Point screenPos) { float x, y; diff --git a/Client/Scripts/Util/WeaponUtil.cs b/Client/Scripts/Util/WeaponUtil.cs index ca403e5..cb1c5db 100644 --- a/Client/Scripts/Util/WeaponUtil.cs +++ b/Client/Scripts/Util/WeaponUtil.cs @@ -1,22 +1,239 @@ using GTA; using GTA.Math; using GTA.Native; +using Newtonsoft.Json; +using RageCoop.Core; using System.Collections.Generic; +using System.Linq; +using System.IO; +using System; +using Console = GTA.Console; +using System.Drawing; +using System.Runtime.InteropServices; namespace RageCoop.Client { - internal class MuzzleInfo + #region DUMP + + class VehicleInfo { - public MuzzleInfo(Vector3 pos, Vector3 forward) - { - Position = pos; - ForawardVector = forward; - } - public Vector3 Position; - public Vector3 ForawardVector; + public string Name; + public string[] Weapons; + public uint Hash; + public VehicleBone[] Bones; } + class VehicleBone + { + public uint BoneID; + public uint BoneIndex; + public string BoneName; + } + class WeaponBones + { + public string Name; + public VehicleBone[] Bones; + } + class VehicleWeaponInfo + { + public static void Dump(string input, string output) + { + Console.Info("Generating " + output); + if (!File.Exists(input)) + { + Console.Info("Downloading"); + HttpHelper.DownloadFile("https://raw.githubusercontent.com/DurtyFree/gta-v-data-dumps/master/vehicles.json", input); + } + Console.Info("Deserialising"); + var infos = JsonConvert.DeserializeObject(File.ReadAllText(input)); + Console.Info("Serialising"); + File.WriteAllText(output, + JsonConvert.SerializeObject( + infos.Select(x => FromVehicle(x)).Where(x => x != null), + Formatting.Indented)); + } + public static VehicleWeaponInfo FromVehicle(VehicleInfo info) + { + if (info.Weapons.Length == 0) + { + return null; + } + var result = new VehicleWeaponInfo() { Hash = info.Hash, Name = info.Name }; + for (int i = 0; i < info.Weapons.Length; i++) + { + result.Weapons.Add((uint)Game.GenerateHash(info.Weapons[i]) + , new WeaponBones + { + Name = info.Weapons[i], + Bones = info.Bones.Where(x => x.BoneName.StartsWith($"weapon_{i + 1}") && !x.BoneName.EndsWith("rot")).ToArray() + }); + + } + return result; + } + public uint Hash; + public string Name; + public Dictionary Weapons = new Dictionary(); + } + class WeaponInfo + { + public string Name; + public uint Hash; + } + + [StructLayout(LayoutKind.Explicit, Size = 312)] + public struct DlcWeaponData + { + } + class WeaponFix + { + public Dictionary Bullet=new Dictionary(); + public Dictionary Lazer = new Dictionary(); + } + #endregion + internal static class WeaponUtil { + public static Dictionary VehicleWeapons = new Dictionary(); + public static WeaponFix WeaponFix; + public const string VehicleWeaponLocation= @"RageCoop\Data\VehicleWeapons.json"; + public const string WeaponFixLocation = @"RageCoop\Data\WeaponFixes.json"; + static WeaponUtil() + { + if (!File.Exists(VehicleWeaponLocation)) + { + Directory.CreateDirectory(@"RageCoop\Data\tmp"); + var input = @"RageCoop\Data\tmp\vehicles.json"; + VehicleWeaponInfo.Dump(input, VehicleWeaponLocation); + } + + // Parse and load to memory + foreach (var w in JsonConvert.DeserializeObject(File.ReadAllText(VehicleWeaponLocation))) + { + VehicleWeapons.Add(w.Hash, w); + } + WeaponFix = JsonConvert.DeserializeObject(File.ReadAllText(WeaponFixLocation)); + } + public static void DumpWeaponFix(string path = WeaponFixLocation) + { + var P = Game.Player.Character; + var pos = P.Position + Vector3.WorldUp * 3; + var types = new HashSet() { 3 }; + P.IsInvincible = true; + var fix = new WeaponFix(); + foreach (VehicleWeaponHash v in Enum.GetValues(typeof(VehicleWeaponHash))) + { + Console.Info("Testing: " + v); + if (types.Contains(v.GetWeaponDamageType())) + { + var asset = new WeaponAsset((int)v); + asset.Request(1000); + World.ShootBullet(pos, pos + Vector3.WorldUp, P, asset, 0, 1000); + if (!Function.Call(Hash.IS_BULLET_IN_AREA, pos.X, pos.Y, pos.Z, 10f, true) && + !Function.Call(Hash.IS_PROJECTILE_IN_AREA, pos.X - 10, pos.Y - 10, pos.Z - 10, pos.X + 10, pos.Y + 10, pos.Z + 10, true)) + { + fix.Bullet.Add((uint)v,$"{nameof(VehicleWeaponHash)}.{v}"); + } + foreach (var p in World.GetAllProjectiles()) + { + p.Delete(); + } + Script.Wait(50); + } + } + foreach (WeaponHash w in Enum.GetValues(typeof(WeaponHash))) + { + if (types.Contains(w.GetWeaponDamageType())) + { + Console.Info("Testing: " + w); + var asset = new WeaponAsset((int)w); + asset.Request(1000); + World.ShootBullet(pos, pos + Vector3.WorldUp, P, asset, 0, 1000); + if (!Function.Call(Hash.IS_BULLET_IN_AREA, pos.X, pos.Y, pos.Z, 10f, true) && + !Function.Call(Hash.IS_PROJECTILE_IN_AREA, pos.X - 10, pos.Y - 10, pos.Z - 10, pos.X + 10, pos.Y + 10, pos.Z + 10, true)) + { + fix.Bullet.Add((uint)w, $"{nameof(WeaponHash)}.{w}"); + } + foreach (var p in World.GetAllProjectiles()) + { + p.Delete(); + } + Script.Wait(50); + } + } + AddLazer(VehicleWeaponHash.PlayerSavage); + AddLazer(VehicleWeaponHash.StrikeforceCannon); + void AddLazer(dynamic hash) + { + fix.Lazer.Add((uint)hash, $"{hash.GetType().Name}.{hash.ToString()}"); + } + File.WriteAllText(path, JsonConvert.SerializeObject(fix, Formatting.Indented)); + + P.IsInvincible = false; + } + public static void DumpWeaponHashes(string path = VehicleWeaponLocation) + { + Dictionary hashes = new Dictionary(); + foreach (var wep in JsonConvert.DeserializeObject(HttpHelper.DownloadString("https://raw.githubusercontent.com/DurtyFree/gta-v-data-dumps/master/weapons.json"))) + { + if (!wep.Name.StartsWith("WEAPON")) { continue; } + hashes.Add(wep.Hash, wep.Name); + } + var output = "public enum WeaponHash : uint\r\n{"; + List lines = new List(); + foreach (var hash in hashes) + { + lines.Add($"{CoreUtils.FormatToSharpStyle(hash.Value, 7)} = {hash.Key.ToHex()}"); + } + lines.Sort(); + foreach (var l in lines) + { + output += $"\r\n\t{l},"; + } + output += "\r\n}"; + File.WriteAllText(path, output); + + } + + public static void DumpVehicleWeaponHashes(string path = @"RageCoop\Data\VehicleWeaponHash.cs") + { + Dictionary hashes = new Dictionary(); + foreach (var veh in VehicleWeapons.Values) + { + foreach (var hash in veh.Weapons) + { + if (!hashes.ContainsKey(hash.Key)) + { + hashes.Add(hash.Key, hash.Value.Name); + } + } + } + var output = "public enum VehicleWeaponHash : uint\r\n{\r\n\tInvalid = 0xFFFFFFFF,"; + List lines = new List(); + foreach (var hash in hashes) + { + lines.Add($"{CoreUtils.FormatToSharpStyle(hash.Value)} = {hash.Key.ToHex()}"); + } + lines.Sort(); + foreach (var l in lines) + { + output += $"\r\n\t{l},"; + } + output += "\r\n}"; + File.WriteAllText(path, output); + + } + public static uint GetWeaponFix(uint hash) + { + if(WeaponFix.Bullet.TryGetValue(hash,out var _)) + { + return (uint)VehicleWeaponHash.SubcarMg; + } + if (WeaponFix.Lazer.TryGetValue(hash, out var _)) + { + return (uint)VehicleWeaponHash.PlayerLazer; + } + return hash; + } public static Dictionary GetWeaponComponents(this Weapon weapon) { Dictionary result = null; @@ -36,334 +253,37 @@ namespace RageCoop.Client public static Vector3 GetMuzzlePosition(this Ped p) { - var w = p.Weapons.CurrentWeaponObject; - if (w != null) + if (p.IsOnTurretSeat()) { - var hash = p.Weapons.Current.Hash; - if (MuzzleBoneIndexes.ContainsKey(hash)) { return w.Bones[MuzzleBoneIndexes[hash]].Position; } - return w.Position; + return p.CurrentVehicle.GetMuzzleBone(p.VehicleWeapon).Position; + } + var wb = p.Weapons?.CurrentWeaponObject?.Bones["gun_muzzle"]; + if (wb?.IsValid == true) + { + return wb.Position; } return p.Bones[Bone.SkelRightHand].Position; } - private static long BulletsShot = 0; - public static float GetWeaponDamage(this Ped P, uint hash) { var comp = P.Weapons.Current.Components.GetSuppressorComponent(); return Function.Call(Hash.GET_WEAPON_DAMAGE, hash, comp.Active ? comp.ComponentHash : WeaponComponentHash.Invalid); - - /* - if (P.IsInVehicle() && (hash!=(uint)P.Weapons.Current.Hash)) - { - // This is a vehicle weapon - P.VehicleWeapon=(VehicleWeaponHash)hash; - return 100; - } - switch (P.Weapons.Current.Group) - { - case WeaponGroup.Pistol: return 30; - case WeaponGroup.AssaultRifle: return 30; - case WeaponGroup.SMG: return 20; - case WeaponGroup.MG: return 40; - case WeaponGroup.Shotgun: return 30; - case WeaponGroup.Sniper: return 200; - case WeaponGroup.Heavy: return 30; - } - return 0; - */ } - public static int GetMuzzleIndex(this Vehicle v) + public static int GetMuzzleIndex(this Vehicle v, VehicleWeaponHash hash) { - BulletsShot++; - switch (v.Model.Hash) + if (VehicleWeapons.TryGetValue((uint)v.Model.Hash, out var veh) && veh.Weapons.TryGetValue((uint)hash, out var wp)) { - // cerberus3 - case 1909700336: - return 53; - - // cerberus2 - case 679453769: - return 54; - - // cerberus - case -801550069: - return 90; - /* - // cerberus (flame) - case -801550069: - i=BulletsShot%2==0 ? 89 : 88; - return new MuzzleInfo(v.Bones[i].Position, v.Bones[i].ForwardVector); - // cerberus (passenger flame) - case -801550069: - i=BulletsShot%2==0 ? 76 : 75; - return new MuzzleInfo(v.Bones[i].Position, v.Bones[i].ForwardVector); - */ - - // ISSI6 - case 1239571361: - return BulletsShot % 2 == 0 ? 12 : 14; - - - // ISSI5 - case 1537277726: - return BulletsShot % 2 == 0 ? 30 : 32; - - - // ISSI4 - case 628003514: - return BulletsShot % 2 == 0 ? 14 : 12; - - - // DOMINATOR6 - case -1293924613: - return BulletsShot % 2 == 0 ? 51 : 55; - - - // IMPALER4 - case -1744505657: - return BulletsShot % 2 == 0 ? 64 : 63; - - - - // IMPERATOR3 - case -755532233: - return BulletsShot % 2 == 0 ? 86 : 88; - - - - // SLAMVAN6 - case 1742022738: - return BulletsShot % 2 == 0 ? 78 : 76; - - - // CHAMPION - case -915234475: - return BulletsShot % 2 == 0 ? 60 : 61; - - - // MONSTER4 - case 840387324: - return BulletsShot % 2 == 0 ? 63 : 65; - - - // BRUTUS2 - case -1890996696: - return 67; - - // BRUISER2 - case -1694081890: - return BulletsShot % 2 == 0 ? 45 : 51; - - - // TECHNICAL3 - case 1356124575: - return 67; - - // TECHNICAL2 - case 1180875963: - return 54; - - // TECHNICAL - case -2096818938: - return 63; - - // PATRIOT3 - case -670086588: - return BulletsShot % 2 == 0 ? 87 : 89; - - // NIGHTSHARK - case 433954513: - return BulletsShot % 2 == 0 ? 1 : 2; - - /* - // NIGHTSHARK (second) - case 433954513: - return BulletsShot%2==0 ? 3 : 4; - */ - - // MENACER - case 2044532910: - return BulletsShot % 2 == 0 ? 91 : 90; - /* - // MENACER - case 2044532910: - return new MuzzleInfo(v.Bones[75].Position, v.Bones[75].ForwardVector); - // MENACER - case 2044532910: - return new MuzzleInfo(v.Bones[78].Position, v.Bones[78].ForwardVector); - - */ - - // CARACARA - case 1254014755: - return 83; - - /* - // CARACARA - case 1254014755: - return BulletsShot%2==0 ? 93 : 94; - */ - - // INSURGENT - case -1860900134: - return 49; - - // INSURGENT3 - case -1924433270: - return 81; - - /* - // INSURGENT3 - case -1924433270: - return BulletsShot%2==0 ? 86 : 91; - */ - - // BLAZER5 - case -1590337689: - return BulletsShot % 2 == 0 ? 17 : 18; - - // BRUISER - case 668439077: - return BulletsShot % 2 == 0 ? 66 : 68; - - - // BRUTUS - case 2139203625: - return 84; - - - // MONSTER3 - case 1721676810: - return BulletsShot % 2 == 0 ? 53 : 55; - - - // BRUISER3 - case -2042350822: - return BulletsShot % 2 == 0 ? 52 : 50; - - // BRUTUS3 - case 2038858402: - return 84; - - // MONSTER5 - case -715746948: - return BulletsShot % 2 == 0 ? 63 : 65; - - // JB7002 - case 394110044: - return BulletsShot % 2 == 0 ? 54 : 53; - - // DOMINATOR5 - case -1375060657: - return BulletsShot % 2 == 0 ? 35 : 36; - - // IMPALER3 - case -1924800695: - return BulletsShot % 2 == 0 ? 75 : 76; - - - // IMPERATOR2 - case 1637620610: - return BulletsShot % 2 == 0 ? 97 : 99; - - - // SLAMVAN5 - case 373261600: - return BulletsShot % 2 == 0 ? 51 : 53; - - - // RUINER2 - case 941494461: - return BulletsShot % 2 == 0 ? 65 : 66; - - - // TAMPA3 - case -1210451983: - return 87; - - // SCRAMJET - case -638562243: - return BulletsShot % 2 == 0 ? 44 : 45; - - - // VIGILANTE - case -1242608589: - return BulletsShot % 2 == 0 ? 42 : 43; - - - // ZR380 - case 540101442: - return BulletsShot % 2 == 0 ? 57 : 63; - - - // ZR3802 - case -1106120762: - return BulletsShot % 2 == 0 ? 57 : 63; - - - // ZR3803 - case -1478704292: - return BulletsShot % 2 == 0 ? 53 : 59; - - - // STROMBERG - case 886810209: - return BulletsShot % 2 == 0 ? 85 : 84; - - - // SLAMVAN4 - case -2061049099: - return BulletsShot % 2 == 0 ? 76 : 78; - - - // IMPERATOR - case 444994115: - return BulletsShot % 2 == 0 ? 88 : 86; - - - // IMPALER2 - case 1009171724: - return BulletsShot % 2 == 0 ? 63 : 64; - - - // DOMINATOR4 - case -688189648: - return BulletsShot % 2 == 0 ? 59 : 60; - - - // SAVAGE - case -82626025: - return 30; - - // BUZZARD - case 788747387: - return BulletsShot % 2 == 0 ? 28 : 23; - - - // ANNIHL - case 837858166: - return (int)BulletsShot % 4 + 35; - - - // HYDRA - case 970385471: - return BulletsShot % 2 == 0 ? 29 : 28; - - - // STARLING - case -1700874274: - return BulletsShot % 2 == 0 ? 24 : 12; - - - // RHINO - case 782665360: - return 30; - - default: - return AddOnDataProvider.GetMuzzleIndex(v.Model.Hash); + return (int)wp.Bones[CoreUtils.RandInt(0, wp.Bones.Length)].BoneIndex; } + return -1; + } + public static EntityBone GetMuzzleBone(this Vehicle v, VehicleWeaponHash hash) + { + var i = v.GetMuzzleIndex(hash); + if (i == -1) { return null; } + return v.Bones[i]; } public static bool IsUsingProjectileWeapon(this Ped p) { @@ -377,83 +297,16 @@ namespace RageCoop.Client var w = p.Weapons.Current; return w.Group == WeaponGroup.Thrown || ProjectileWeapons.Contains(w.Hash); } - + public static int GetWeaponDamageType(this T hash) where T : Enum + { + return Function.Call(Hash.GET_WEAPON_DAMAGE_TYPE, hash); + } public static readonly HashSet ExplosiveBullets = new HashSet { (uint)VehicleWeaponHash.PlayerLazer, (uint)WeaponHash.Railgun, 1638077257 }; - - public static readonly Dictionary MuzzleBoneIndexes = new Dictionary - { - {WeaponHash.HeavySniper,6}, - {WeaponHash.MarksmanRifle,9}, - {WeaponHash.SniperRifle,9}, - {WeaponHash.AdvancedRifle,5}, - {WeaponHash.SpecialCarbine,9}, - {WeaponHash.BullpupRifle,7}, - {WeaponHash.AssaultRifle,9}, - {WeaponHash.CarbineRifle,6}, - {WeaponHash.MachinePistol,5}, - {WeaponHash.SMG,5}, - {WeaponHash.AssaultSMG,6}, - {WeaponHash.CombatPDW,5}, - {WeaponHash.MG,6}, - {WeaponHash.CombatMG,7}, - {WeaponHash.Gusenberg,7}, - {WeaponHash.MicroSMG,10}, - {WeaponHash.APPistol,8}, - {WeaponHash.StunGun,4}, - {WeaponHash.Pistol,8}, - {WeaponHash.CombatPistol,8}, - {WeaponHash.Pistol50,7}, - {WeaponHash.SNSPistol,8}, - {WeaponHash.HeavyPistol,8}, - {WeaponHash.VintagePistol,8}, - {WeaponHash.Railgun,9}, - {WeaponHash.Minigun,5}, - {WeaponHash.Musket,3}, - {WeaponHash.HeavyShotgun,10}, - {WeaponHash.PumpShotgun,11}, - {WeaponHash.SawnOffShotgun,8}, - {WeaponHash.BullpupShotgun,8}, - {WeaponHash.AssaultShotgun,9}, - {WeaponHash.HeavySniperMk2,11}, - {WeaponHash.MarksmanRifleMk2,9}, - {WeaponHash.CarbineRifleMk2,13}, - {WeaponHash.SpecialCarbineMk2,16}, - {WeaponHash.BullpupRifleMk2,8}, - {WeaponHash.CompactRifle,7}, - {WeaponHash.MilitaryRifle,11}, - {WeaponHash.AssaultrifleMk2,17}, - {WeaponHash.MiniSMG,5}, - {WeaponHash.SMGMk2,6}, - {WeaponHash.CombatMGMk2,16}, - {WeaponHash.UnholyHellbringer,4}, - {WeaponHash.PistolMk2,12}, - {WeaponHash.SNSPistolMk2,15}, - {WeaponHash.CeramicPistol,10}, - {WeaponHash.MarksmanPistol,4}, - {WeaponHash.Revolver,7}, - {WeaponHash.RevolverMk2,7}, - {WeaponHash.DoubleActionRevolver,7}, - {WeaponHash.NavyRevolver,7}, - {WeaponHash.PericoPistol,4}, - {WeaponHash.FlareGun,4}, - {WeaponHash.UpNAtomizer,4}, - {WeaponHash.HomingLauncher,5}, - {WeaponHash.CompactGrenadeLauncher,8}, - {WeaponHash.Widowmaker,6}, - {WeaponHash.GrenadeLauncher,3}, - {WeaponHash.RPG,9}, - {WeaponHash.DoubleBarrelShotgun,8}, - {WeaponHash.SweeperShotgun,7}, - {WeaponHash.CombatShotgun,7}, - {WeaponHash.PumpShotgunMk2,7}, - - }; - public static readonly HashSet ProjectileWeapons = new HashSet { WeaponHash.HomingLauncher, WeaponHash.RPG, @@ -471,8 +324,18 @@ namespace RageCoop.Client (VehicleWeaponHash)3565779982, // STROMBERG missiles (VehicleWeaponHash)3169388763, // SCRAMJET missiles }; - public static string GetFlashFX(this WeaponHash w) + public static string GetFlashFX(this WeaponHash w,bool veh) { + if (veh) + { + + switch ((VehicleWeaponHash)w) + { + case VehicleWeaponHash.Tank: + return "muz_tank"; + default: return "muz_buzzard"; + } + } switch (w.GetWeaponGroup()) { case WeaponGroup.SMG: @@ -510,16 +373,9 @@ namespace RageCoop.Client case WeaponGroup.FireExtinguisher: return "weap_extinguisher"; + default: + return "muz_assault_rifle"; } - switch ((VehicleWeaponHash)w) - { - case VehicleWeaponHash.Tank: - return "muz_tank"; - - case VehicleWeaponHash.PlayerBuzzard: - return "muz_buzzard"; - } - return "muz_assault_rifle"; } public static WeaponGroup GetWeaponGroup(this WeaponHash hash) { diff --git a/Client/Scripts/WorldThread.cs b/Client/Scripts/WorldThread.cs index 2d44487..ffcb4e3 100644 --- a/Client/Scripts/WorldThread.cs +++ b/Client/Scripts/WorldThread.cs @@ -2,6 +2,7 @@ using GTA.Native; using System; using System.Collections.Generic; +using System.Drawing; using System.Threading; using System.Threading.Tasks; diff --git a/Core/CoreUtils.cs b/Core/CoreUtils.cs index 62431eb..2eafd62 100644 --- a/Core/CoreUtils.cs +++ b/Core/CoreUtils.cs @@ -19,11 +19,33 @@ using System.Text; [assembly: InternalsVisibleTo("RageCoop.Server")] [assembly: InternalsVisibleTo("RageCoop.Client")] [assembly: InternalsVisibleTo("RageCoop.Client.Installer")] +[assembly: InternalsVisibleTo("RageCoop.Client.DataDumper")] [assembly: InternalsVisibleTo("RageCoop.ResourceBuilder")] namespace RageCoop.Core { internal static class CoreUtils { + private static Random random = new Random(); + public static string FormatToSharpStyle(string input,int offset=14) + { + var ss = input.Substring(offset).Split("_".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); + // Replace first character with upper case + for (int i = 0; i < ss.Length; i++) + { + var sec = ss[i].ToLower(); + var head = sec[0]; + ss[i] = head.ToString().ToUpper() + sec.Remove(0, 1); + } + return string.Join("", ss); + } + public static string ToHex(this int value) + { + return String.Format("0x{0:X}", value); + } + public static string ToHex(this uint value) + { + return String.Format("0x{0:X}", value); + } private static readonly HashSet ToIgnore = new HashSet() { "RageCoop.Client", @@ -35,16 +57,37 @@ namespace RageCoop.Core "ScriptHookVDotNet3", "ScriptHookVDotNet" }; + public static int RandInt(int start,int end) + { + return random.Next(start, end); + } + public static string GetTempDirectory(string dir = null) + { + dir = dir ?? Path.GetTempPath(); + string path; + do + { + path = Path.Combine(dir, RandomString(10)); + } while (Directory.Exists(path) || File.Exists(path)); + + return path; + } + public static string RandomString(int length) + { + const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + return new string(Enumerable.Repeat(chars, length) + .Select(s => s[random.Next(s.Length)]).ToArray()); + } public static void GetDependencies(Assembly assembly, ref HashSet existing) { if (assembly.FullName.StartsWith("System")) { return; } - foreach(var name in assembly.GetReferencedAssemblies()) + foreach (var name in assembly.GetReferencedAssemblies()) { if (name.FullName.StartsWith("System")) { continue; } try { var asm = Assembly.Load(name); - GetDependencies(asm,ref existing); + GetDependencies(asm, ref existing); } catch { } } diff --git a/Core/Networking/HttpHelper.cs b/Core/Networking/HttpHelper.cs index 3c7a75e..2b2dd02 100644 --- a/Core/Networking/HttpHelper.cs +++ b/Core/Networking/HttpHelper.cs @@ -7,7 +7,7 @@ namespace RageCoop.Core { internal static class HttpHelper { - public static void DownloadFile(string url, string destination, Action progressCallback) + public static void DownloadFile(string url, string destination, Action progressCallback = null) { if (File.Exists(destination)) { File.Delete(destination); } AutoResetEvent ae = new AutoResetEvent(false); diff --git a/RageCoop-V.sln b/RageCoop-V.sln index 714563f..ad4a479 100644 --- a/RageCoop-V.sln +++ b/RageCoop-V.sln @@ -15,6 +15,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RageCoop.Client.Loader", "C EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Client", "Client", "{531656CF-7269-488D-B042-741BC96C3941}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{12E29AB7-74C4-4250-8975-C02D7FFC2D7B}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/Server/Properties/AssemblyInfo.cs b/Server/Properties/AssemblyInfo.cs index d970dca..c3c597b 100644 --- a/Server/Properties/AssemblyInfo.cs +++ b/Server/Properties/AssemblyInfo.cs @@ -15,7 +15,7 @@ using System.Resources; [assembly: AssemblyCulture("")] // Version information -[assembly: AssemblyVersion("1.5.6.1")] -[assembly: AssemblyFileVersion("1.5.6.1")] +[assembly: AssemblyVersion("1.5.6.12")] +[assembly: AssemblyFileVersion("1.5.6.12")] [assembly: NeutralResourcesLanguageAttribute( "en-US" )] diff --git a/libs/ScriptHookVDotNet.dll b/libs/ScriptHookVDotNet.dll index 99c840c..a03030f 100644 Binary files a/libs/ScriptHookVDotNet.dll and b/libs/ScriptHookVDotNet.dll differ diff --git a/libs/ScriptHookVDotNet2.dll b/libs/ScriptHookVDotNet2.dll index cde7303..554a2fc 100644 Binary files a/libs/ScriptHookVDotNet2.dll and b/libs/ScriptHookVDotNet2.dll differ diff --git a/libs/ScriptHookVDotNet3.dll b/libs/ScriptHookVDotNet3.dll index eb132a2..0cf01b8 100644 Binary files a/libs/ScriptHookVDotNet3.dll and b/libs/ScriptHookVDotNet3.dll differ