Initial CEF and DirectX overlay implementation (PoC, unfinished)

Still pretty unstable, game might crash at times.
Revamp build system and other small fixes
This commit is contained in:
sardelka9515
2022-11-05 18:35:39 +08:00
parent 2828b9b74f
commit 8961eb102b
97 changed files with 179796 additions and 204 deletions

View File

@ -0,0 +1,112 @@
using System;
using System.Drawing;
using DXHook.Hook.Common;
using GTA;
using RageCoop.Client.CefHost;
using RageCoop.Client.Scripting;
namespace RageCoop.Client.GUI
{
public class CefClient
{
public readonly int Id;
internal CefAdapter Adapter;
internal CefController Controller;
internal ImageElement MainFrame;
internal CefClient(int id, Size size)
{
Id = id;
Controller = CefController.Create(id, size, out Adapter, BufferMode.Full);
MainFrame = new ImageElement(size.Width, size.Height, 4, Adapter.PtrBuffer);
Adapter.OnPaint += (len, dirty) =>
{
try
{
// Image is using same shared buffer, so just need to make it re-copied to GPU
MainFrame.Invalidate();
}
catch (Exception ex)
{
API.Logger.Error(ex);
}
};
}
internal void Destroy()
{
Controller.Dispose();
Adapter.Dispose();
MainFrame.Dispose();
}
public Point GetLocationInFrame(Point screenPos)
{
screenPos.X -= MainFrame.Location.X;
screenPos.Y -= MainFrame.Location.Y;
return screenPos;
}
public Point GetLocationInCef(Point screenPos)
{
var p = GetLocationInFrame(screenPos);
p.X = (int)(p.X / Scale);
p.Y = (int)(p.Y / Scale);
return p;
}
internal bool PointInArea(Point screen)
{
screen = GetLocationInFrame(screen);
return screen.X.IsBetween(0, Width) && screen.Y.IsBetween(0, Height);
}
internal void Tick()
{
var mousePos = Util.CursorPosition;
if (!PointInArea(mousePos)) return;
var pos = GetLocationInCef(mousePos);
if (Game.IsControlJustPressed(Control.CursorAccept))
Controller.SendMouseClick(pos.X, pos.Y, 0, MouseButton.Left, false, 1);
else if (Game.IsControlJustReleased(Control.CursorAccept))
Controller.SendMouseClick(pos.X, pos.Y, 0, MouseButton.Left, true, 1);
}
#region FRAME-APPERANCE
public float Scale
{
get => MainFrame.Scale;
set => MainFrame.Scale = value;
}
public Color Tint
{
get => MainFrame.Tint;
set => MainFrame.Tint = value;
}
public byte Opacity
{
get => MainFrame.Opacity;
set => MainFrame.Opacity = value;
}
public Point Location
{
get => MainFrame.Location;
set => MainFrame.Location = value;
}
public int Width => MainFrame.Width;
public int Height => MainFrame.Height;
public bool Hidden
{
get => MainFrame.Hidden;
set => MainFrame.Hidden = value;
}
#endregion
}
}

View File

@ -0,0 +1,121 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using DXHook.Hook.Common;
using GTA;
using GTA.Native;
using RageCoop.Client.CefHost;
using RageCoop.Client.Scripting;
using RageCoop.Core;
namespace RageCoop.Client.GUI
{
internal static class CefManager
{
private static readonly ConcurrentDictionary<int, CefClient> Clients =
new ConcurrentDictionary<int, CefClient>();
private static readonly Overlay CefOverlay = new Overlay
{
Elements = new List<IOverlayElement>(),
Hidden = false
};
static CefManager()
{
Main.CefRunning = true;
HookManager.Initialize();
CefController.Initialize(@"RageCoop\SubProcess\RageCoop.Client.CefHost.exe");
CefController.OnCefMessage = m => API.Logger.Debug(m);
HookManager.AddOverLay(CefOverlay);
}
public static CefClient ActiveClient { get; set; }
public static void Test()
{
var c = CreateClient(new Size(640, 480));
c.Scale = 0.8f;
c.Opacity = 128;
Script.Wait(2000);
c.Controller.LoadUrl("https://ragecoop.online/");
ActiveClient = c;
}
public static void Tick()
{
if (ActiveClient != null)
{
Game.DisableAllControlsThisFrame();
Function.Call(Hash._SET_MOUSE_CURSOR_ACTIVE_THIS_FRAME);
ActiveClient.Tick();
}
}
public static void KeyDown(Keys key)
{
}
public static void KeyUp(Keys key)
{
}
public static bool DestroyClient(CefClient client)
{
lock (Clients)
{
if (Clients.TryRemove(client.Id, out var c) && client == c)
{
client.Destroy();
CefOverlay.Elements.Remove(client.MainFrame);
if (ActiveClient == client) ActiveClient = null;
return true;
}
}
return false;
}
public static CefClient CreateClient(Size size)
{
lock (Clients)
{
var id = 0;
while (id == 0 || Clients.ContainsKey(id)) id = CoreUtils.RandInt(0, int.MaxValue);
var client = new CefClient(id, size);
if (Clients.TryAdd(id, client))
{
CefOverlay.Elements.Add(client.MainFrame);
return client;
}
API.Logger.Warning("Failed to create CefClient");
client.Destroy();
return null;
}
}
public static void CleanUp()
{
Main.CefRunning = false;
ActiveClient = null;
try
{
lock (Clients)
{
foreach (var c in Clients.Values) DestroyClient(c);
Clients.Clear();
}
CefController.ShutDown();
}
catch (Exception ex)
{
API.Logger.Error(ex);
}
}
}
}

View File

@ -0,0 +1,61 @@
using System.Collections.Generic;
using DXHook.Hook;
using DXHook.Hook.Common;
using DXHook.Interface;
using RageCoop.Client.Scripting;
namespace RageCoop.Client.GUI
{
internal static class HookManager
{
public static readonly CaptureInterface Interface = new CaptureInterface();
private static DXHookD3D11 _hook;
public static Overlay DefaultOverlay = new Overlay();
public static bool Hooked => _hook != null;
public static void GetOverlays()
{
new List<IOverlay>(_hook.Overlays);
}
public static void AddOverLay(IOverlay ol)
{
_hook.Overlays.Add(ol);
_hook.IsOverlayUpdatePending = true;
}
public static void RemoveOverlay(IOverlay ol)
{
_hook.Overlays.Remove(ol);
_hook.IsOverlayUpdatePending = true;
}
public static void Initialize()
{
if (_hook != null) return;
_hook = new DXHookD3D11(Interface);
_hook.Config = new CaptureConfig
{
Direct3DVersion = Direct3DVersion.Direct3D11,
ShowOverlay = true
};
_hook.Overlays = new List<IOverlay>();
_hook.Hook();
_hook.OnPresent += Present;
DefaultOverlay.Elements = new List<IOverlayElement>();
AddOverLay(DefaultOverlay);
Interface.RemoteMessage += m => { API.Logger.Debug("DXHook: " + m.Message); };
API.Logger.Debug("Hooked DX3D11");
}
private static void Present()
{
}
public static void CleanUp()
{
_hook?.Cleanup();
_hook?.Dispose();
_hook = null;
}
}
}

View File

@ -12,6 +12,7 @@ using GTA.UI;
using LemonUI.Elements;
using LemonUI.Menus;
using Lidgren.Network;
using RageCoop.Client.GUI;
using RageCoop.Client.Menus;
using RageCoop.Client.Scripting;
using RageCoop.Core;
@ -49,6 +50,7 @@ namespace RageCoop.Client
public static Ped P;
public static float FPS;
private static bool _lastDead;
public static bool CefRunning;
/// <summary>
/// Don't use it!
@ -145,11 +147,13 @@ namespace RageCoop.Client
Aborted += OnAborted;
Tick += OnTick;
KeyDown += OnKeyDown;
KeyUp += OnKeyUp;
Util.NativeMemory();
Counter.Restart();
}
public static string LogPath => $"{Settings.DataDirectory}\\RageCoop.Client.log";
private static void OnAborted(object sender, EventArgs e)
@ -159,7 +163,7 @@ namespace RageCoop.Client
WorldThread.Instance?.Abort();
DevTool.Instance?.Abort();
ScriptDomain.CurrentDomain.Tick -= DomainTick;
Disconnected("Abort");
CleanUp("Abort");
WorldThread.DoQueuedActions();
}
catch (Exception ex)
@ -241,6 +245,10 @@ namespace RageCoop.Client
CoopMenu.MenuPool.Process();
#endif
if (CefRunning)
{
CefManager.Tick();
}
if (!Networking.IsOnServer)
{
@ -255,7 +263,8 @@ namespace RageCoop.Client
if (Networking.ShowNetworkInfo)
{
new ScaledText(new PointF(Screen.PrimaryScreen.Bounds.Width / 2, 0),
$"L: {Networking.Latency * 1000:N0}ms", 0.5f) { Alignment = Alignment.Center }.Draw();
$"L: {Networking.Latency * 1000:N0}ms", 0.5f)
{ Alignment = Alignment.Center }.Draw();
new ScaledText(new PointF(Screen.PrimaryScreen.Bounds.Width / 2, 30),
$"R: {NetUtility.ToHumanReadable(Statistics.BytesDownPerSecond)}/s", 0.5f)
{ Alignment = Alignment.Center }.Draw();
@ -300,6 +309,14 @@ namespace RageCoop.Client
Ticked++;
}
private void OnKeyUp(object sender, KeyEventArgs e)
{
if (CefRunning)
{
CefManager.KeyUp(e.KeyCode);
}
}
private static void OnKeyDown(object sender, KeyEventArgs e)
{
if (MainChat.Focused)
@ -308,6 +325,11 @@ namespace RageCoop.Client
return;
}
if (CefRunning)
{
CefManager.KeyDown(e.KeyCode);
}
if (Networking.IsOnServer)
{
if (Voice.WasInitialized())
@ -317,7 +339,8 @@ namespace RageCoop.Client
Voice.StartRecording();
return;
}
else if (Voice.IsRecording())
if (Voice.IsRecording())
{
Voice.StopRecording();
return;
@ -380,37 +403,37 @@ namespace RageCoop.Client
}
else if (e.KeyCode == Settings.PassengerKey)
{
var P = Game.Player.Character;
if (!P.IsInVehicle())
if (P == null || P.IsInVehicle())
{
if (P.IsTaskActive(TaskType.CTaskEnterVehicle))
{
P.Task.ClearAll();
}
else
{
var V = World.GetClosestVehicle(P.ReadPosition(), 50);
return;
}
if (V != null)
if (P.IsTaskActive(TaskType.CTaskEnterVehicle))
{
P.Task.ClearAll();
}
else
{
var V = World.GetClosestVehicle(P.ReadPosition(), 15);
if (V != null)
{
var seat = P.GetNearestSeat(V);
var p = V.GetPedOnSeat(seat);
if (p != null && !p.IsDead)
{
var seat = P.GetNearestSeat(V);
var p = V.GetPedOnSeat(seat);
if (p != null && !p.IsDead)
for (int i = -1; i < V.PassengerCapacity; i++)
{
for (int i = -1; i < V.PassengerCapacity; i++)
seat = (VehicleSeat)i;
p = V.GetPedOnSeat(seat);
if (p == null || p.IsDead)
{
seat = (VehicleSeat)i;
p = V.GetPedOnSeat(seat);
if (p == null || p.IsDead)
{
break;
}
break;
}
}
P.Task.EnterVehicle(V, seat, -1, 5, EnterVehicleFlags.None);
}
P.Task.EnterVehicle(V, seat, -1, 5, EnterVehicleFlags.None);
}
}
}
@ -436,9 +459,14 @@ namespace RageCoop.Client
Logger.Info(">> Connected <<");
}
public static void Disconnected(string reason)
public static void CleanUp(string reason)
{
Logger.Info($">> Disconnected << reason: {reason}");
if (reason != "Abort")
{
Logger.Info($">> Disconnected << reason: {reason}");
API.QueueAction(() => { Notification.Show("~r~Disconnected: " + reason); });
}
API.QueueAction(() =>
{
if (MainChat.Focused)
@ -452,11 +480,12 @@ namespace RageCoop.Client
WorldThread.Traffic(true);
Function.Call(Hash.SET_ENABLE_VEHICLE_SLIPSTREAMING, false);
CoopMenu.DisconnectedMenuSetting();
Notification.Show("~r~Disconnected: " + reason);
LocalPlayerID = default;
Resources.Unload();
});
Memory.RestorePatches();
CefManager.CleanUp();
HookManager.CleanUp();
DownloadManager.Cleanup();
Voice.ClearAll();
}

View File

@ -3,6 +3,7 @@ using System.Drawing;
using GTA;
using GTA.UI;
using LemonUI.Menus;
using RageCoop.Client.GUI;
using RageCoop.Client.Loader;
namespace RageCoop.Client
@ -32,6 +33,14 @@ namespace RageCoop.Client
private static readonly NativeCheckboxItem ShowNetworkInfoItem =
new NativeCheckboxItem("Show Network Info", Networking.ShowNetworkInfo);
private static readonly NativeCheckboxItem DxHookTest =
new NativeCheckboxItem("Enable D3D11 hook", false);
private static readonly NativeCheckboxItem CefTest =
new NativeCheckboxItem("Test CEF overlay", false);
private static CefClient _testCef;
static DebugMenu()
{
Menu.Banner.Color = Color.FromArgb(225, 0, 0, 0);
@ -68,12 +77,43 @@ namespace RageCoop.Client
Main.Settings.ShowEntityOwnerName = ShowOwnerItem.Checked;
Util.SaveSettings();
};
DxHookTest.CheckboxChanged += Hook;
CefTest.CheckboxChanged += CefTestChange;
;
ReloadItem.Activated += ReloadDomain;
Menu.Add(SimulatedLatencyItem);
Menu.Add(ShowNetworkInfoItem);
Menu.Add(ShowOwnerItem);
Menu.Add(ReloadItem);
Menu.AddSubMenu(DiagnosticMenu);
Menu.Add(DxHookTest);
Menu.Add(CefTest);
}
private static void CefTestChange(object sender, EventArgs e)
{
if (CefTest.Checked)
{
_testCef = CefManager.CreateClient(new Size(640, 480));
_testCef.Scale = 0.8f;
_testCef.Opacity = 128;
Script.Wait(2000);
_testCef.Controller.LoadUrl("https://ragecoop.online/");
CefManager.ActiveClient = _testCef;
}
else
{
CefManager.DestroyClient(_testCef);
}
DxHookTest.Checked = HookManager.Hooked;
}
private static void Hook(object sender, EventArgs e)
{
if (DxHookTest.Checked)
HookManager.Initialize();
else
HookManager.CleanUp();
}
private static void ReloadDomain(object sender, EventArgs e)

View File

@ -80,7 +80,7 @@ namespace RageCoop.Client
break;
case NetConnectionStatus.Disconnected:
if (message.SenderConnection == ServerConnection) Main.Disconnected(reason);
if (message.SenderConnection == ServerConnection) Main.CleanUp(reason);
break;
}

View File

@ -1,4 +1,7 @@
using System.Reflection;

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Resources;
// General Information
@ -13,6 +16,7 @@ using System.Resources;
// Version informationr(
[assembly: AssemblyVersion("1.5.7.118")]
[assembly: AssemblyFileVersion("1.5.7.118")]
[assembly: NeutralResourcesLanguageAttribute("en-US")]
[assembly: AssemblyVersion("1.5.7.351")]
[assembly: AssemblyFileVersion("1.5.7.351")]
[assembly: NeutralResourcesLanguageAttribute( "en-US" )]

View File

@ -2,6 +2,7 @@
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@ -18,6 +19,14 @@
</NuGetPackageImportStamp>
<OutPutPath>..\..\bin\$(Configuration)\Client\Scripts</OutPutPath>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
<AllowedReferenceRelatedFileExtensions>
.dll
.pdb
</AllowedReferenceRelatedFileExtensions>
<DocumentationFile>..\..\bin\API\RageCoop.Client.xml</DocumentationFile>
<DebugType>full</DebugType>
<NoWarn>CS1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<DefineConstants>DEBUG</DefineConstants>
@ -27,6 +36,9 @@
<ItemGroup>
<Compile Include="Debug.cs" />
<Compile Include="DevTools\DevTool.cs" />
<Compile Include="GUI\CefClient.cs" />
<Compile Include="GUI\CefManager.cs" />
<Compile Include="GUI\HookManager.cs" />
<Compile Include="Main.cs" />
<Compile Include="Menus\CoopMenu.cs" />
<Compile Include="Menus\Sub\DebugMenu.cs" />
@ -42,11 +54,6 @@
<Compile Include="Networking\Send.cs" />
<Compile Include="Networking\Statistics.cs" />
<Compile Include="PlayerList.cs" />
<Compile Include="Properties\AssemblyInfo.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>AssemblyInfo.tt</DependentUpon>
</Compile>
<Compile Include="Scripting\API.cs" />
<Compile Include="Scripting\BaseScript.cs" />
<Compile Include="Scripting\ClientScript.cs" />
@ -73,9 +80,17 @@
<Compile Include="Util\Util.cs" />
<Compile Include="Util\VehicleExtensions.cs" />
<Compile Include="Util\WeaponUtil.cs" />
<Compile Include="Util\Win32.cs" />
<Compile Include="WorldThread.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="BitmapUtil, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\libs\BitmapUtil.dll</HintPath>
</Reference>
<Reference Include="DXHook">
<HintPath>..\..\libs\DXHook\DXHook.dll</HintPath>
</Reference>
<Reference Include="ICSharpCode.SharpZipLib, Version=1.4.0.12, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<HintPath>..\..\packages\SharpZipLib.1.4.0\lib\netstandard2.0\ICSharpCode.SharpZipLib.dll</HintPath>
</Reference>
@ -86,9 +101,6 @@
<HintPath>..\..\libs\Lidgren.Network.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.Extensions.ObjectPool, Version=6.0.8.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.ObjectPool.6.0.8\lib\net461\Microsoft.Extensions.ObjectPool.dll</HintPath>
</Reference>
<Reference Include="NAudio, Version=2.1.0.0, Culture=neutral, PublicKeyToken=e279aa5131008a41, processorArchitecture=MSIL">
<HintPath>..\..\packages\NAudio.2.1.0\lib\net472\NAudio.dll</HintPath>
</Reference>
@ -113,6 +125,10 @@
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="RageCoop.Client.CefHost, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\bin\$(Configuration)\Client\SubProcess\ref\RageCoop.Client.CefHost.dll</HintPath>
</Reference>
<Reference Include="ScriptHookVDotNet">
<HintPath>..\..\libs\ScriptHookVDotNet.dll</HintPath>
</Reference>
@ -121,6 +137,12 @@
</Reference>
<Reference Include="System" />
<Reference Include="System.Drawing" />
<Reference Include="System.Drawing.Common, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Drawing.Common.4.5.0\lib\net461\System.Drawing.Common.dll</HintPath>
</Reference>
<Reference Include="System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Windows.Forms" />
</ItemGroup>
<ItemGroup>
@ -131,10 +153,16 @@
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Content Include="icon.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Properties\AssemblyInfo.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>AssemblyInfo.cs</LastGenOutput>
</Content>
<Content Include="sharpdx_direct3d11_1_effects_x64.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
@ -149,8 +177,14 @@
<Name>RageCoop.Client.Loader</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup Condition=" '$(DevEnvDir)' != '*Undefined*'">
<PostBuildEvent>"$(DevEnvDir)TextTransform.exe" -a !!BuildConfiguration!$(Configuration) "$(ProjectDir)Properties\AssemblyInfo.tt"</PostBuildEvent>
<PropertyGroup>
<PostBuildEvent Condition=" '$(DevEnvDir)' != '*Undefined*'">
"$(DevEnvDir)TextTransform.exe" -a !!BuildConfiguration!$(Configuration) "$(ProjectDir)Properties\AssemblyInfo.tt"
</PostBuildEvent>
<PreBuildEvent Condition=" '$(SolutionDir)' != '*Undefined*'">
dotnet build -c $(Configuration) "$(SolutionDir)Client\CefHost\RageCoop.Client.CefHost.csproj"
</PreBuildEvent>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=util/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@ -41,48 +41,6 @@ namespace RageCoop.Client.Scripting
#endregion
/// <summary>
/// Queue an action to be executed on next tick.
/// </summary>
/// <param name="a"></param>
public static void QueueAction(Action a)
{
WorldThread.QueueAction(a);
}
public static void QueueActionAndWait(Action a, int timeout = 15000)
{
var done = new AutoResetEvent(false);
Exception e = null;
QueueAction(() =>
{
try
{
a();
done.Set();
}
catch (Exception ex)
{
e = ex;
}
});
if (e != null)
throw e;
if (!done.WaitOne(timeout)) throw new TimeoutException();
}
/// <summary>
/// Queue an action to be executed on next tick, allowing you to call scripting API from another thread.
/// </summary>
/// <param name="a">
/// An <see cref="Func{T, TResult}" /> to be executed with a return value indicating whether it can be
/// removed after execution.
/// </param>
public static void QueueAction(Func<bool> a)
{
WorldThread.QueueAction(a);
}
/// <summary>
/// Client configuration, this will conflict with server-side config.
/// </summary>
@ -304,6 +262,49 @@ namespace RageCoop.Client.Scripting
#region FUNCTIONS
/// <summary>
/// Queue an action to be executed on next tick.
/// </summary>
/// <param name="a"></param>
public static void QueueAction(Action a)
{
WorldThread.QueueAction(a);
}
public static void QueueActionAndWait(Action a, int timeout = 15000)
{
var done = new AutoResetEvent(false);
Exception e = null;
QueueAction(() =>
{
try
{
a();
done.Set();
}
catch (Exception ex)
{
e = ex;
}
});
if (e != null)
throw e;
if (!done.WaitOne(timeout)) throw new TimeoutException();
}
/// <summary>
/// Queue an action to be executed on next tick, allowing you to call scripting API from another thread.
/// </summary>
/// <param name="a">
/// An <see cref="Func{T, TResult}" /> to be executed with a return value indicating whether it can be
/// removed after execution.
/// </param>
public static void QueueAction(Func<bool> a)
{
WorldThread.QueueAction(a);
}
/// <summary>
/// Connect to a server
/// </summary>

View File

@ -42,10 +42,10 @@ namespace RageCoop.Client
static Memory()
{
// Weapon/radio wheel slow-mo patch
// Thanks @CamxxCore, https://github.com/CamxxCore/GTAVWeaponWheelMod
// Thanks to @CamxxCore, https://github.com/CamxxCore/GTAVWeaponWheelMod
var result = NativeMemory.FindPattern("\x38\x51\x64\x74\x19", "xxxxx");
if (result == null)
throw new NotSupportedException("Can't find memory pattern to patch weapon/radio slow-mo");
throw new NotSupportedException("Can't find memory pattern to patch weapon/radio slowdown");
var address = result + 26;
address = address + *(int*)address + 4u;
VignettingPatch = new MemPatch(address, new byte[] { RET, 0x90, 0x90, 0x90, 0x90 });

View File

@ -20,6 +20,33 @@ namespace RageCoop.Client
{
public static string SettingsPath = "RageCoop\\Settings.json";
/// <summary>
/// The location of the cursor on screen between 0 and 1.
/// </summary>
public static PointF CursorPositionRelative
{
get
{
var cursorX = Game.IsControlEnabled(Control.CursorX)
? Game.GetControlValueNormalized(Control.CursorX)
: Game.GetDisabledControlValueNormalized(Control.CursorX);
var cursorY = Game.IsControlEnabled(Control.CursorY)
? Game.GetControlValueNormalized(Control.CursorY)
: Game.GetDisabledControlValueNormalized(Control.CursorY);
return new PointF(cursorX, cursorY);
}
}
public static Point CursorPosition
{
get
{
var p = CursorPositionRelative;
var res = Screen.Resolution;
return new Point((int)(p.X * res.Width), (int)(p.Y * res.Height));
}
}
public static SizeF ResolutionMaintainRatio
{
get

View File

@ -0,0 +1,469 @@
using System;
using System.Drawing;
using System.Runtime.InteropServices;
// ReSharper disable InconsistentNaming
// ReSharper disable IdentifierTypo
// ReSharper disable UnusedMember.Local
namespace RageCoop.Client
{
internal class Win32
{
#region ENUM
/// <summary>
/// Enumerates the valid hook types passed as the idHook parameter into a call to SetWindowsHookEx.
/// </summary>
public enum HookType
{
/// <summary>
/// Installs a hook procedure that monitors messages generated as a result of an input event in a dialog box,
/// message box, menu, or scroll bar. For more information, see the MessageProc hook procedure.
/// </summary>
WH_MSGFILTER = -1,
/// <summary>
/// Installs a hook procedure that records input messages posted to the system message queue. This hook is
/// useful for recording macros. For more information, see the JournalRecordProc hook procedure.
/// </summary>
WH_JOURNALRECORD = 0,
/// <summary>
/// Installs a hook procedure that posts messages previously recorded by a WH_JOURNALRECORD hook procedure.
/// For more information, see the JournalPlaybackProc hook procedure.
/// </summary>
WH_JOURNALPLAYBACK = 1,
/// <summary>
/// Installs a hook procedure that monitors keystroke messages. For more information, see the KeyboardProc
/// hook procedure.
/// </summary>
WH_KEYBOARD = 2,
/// <summary>
/// Installs a hook procedure that monitors messages posted to a message queue. For more information, see the
/// GetMsgProc hook procedure.
/// </summary>
WH_GETMESSAGE = 3,
/// <summary>
/// Installs a hook procedure that monitors messages before the system sends them to the destination window
/// procedure. For more information, see the CallWndProc hook procedure.
/// </summary>
WH_CALLWNDPROC = 4,
/// <summary>
/// Installs a hook procedure that receives notifications useful to a CBT application. For more information,
/// see the CBTProc hook procedure.
/// </summary>
WH_CBT = 5,
/// <summary>
/// Installs a hook procedure that monitors messages generated as a result of an input event in a dialog box,
/// message box, menu, or scroll bar. The hook procedure monitors these messages for all applications in the
/// same desktop as the calling thread. For more information, see the SysMsgProc hook procedure.
/// </summary>
WH_SYSMSGFILTER = 6,
/// <summary>
/// Installs a hook procedure that monitors mouse messages. For more information, see the MouseProc hook
/// procedure.
/// </summary>
WH_MOUSE = 7,
/// <summary>
/// </summary>
WH_HARDWARE = 8,
/// <summary>
/// Installs a hook procedure useful for debugging other hook procedures. For more information, see the
/// DebugProc hook procedure.
/// </summary>
WH_DEBUG = 9,
/// <summary>
/// Installs a hook procedure that receives notifications useful to shell applications. For more information,
/// see the ShellProc hook procedure.
/// </summary>
WH_SHELL = 10,
/// <summary>
/// Installs a hook procedure that will be called when the application's foreground thread is about to become
/// idle. This hook is useful for performing low priority tasks during idle time. For more information, see the
/// ForegroundIdleProc hook procedure.
/// </summary>
WH_FOREGROUNDIDLE = 11,
/// <summary>
/// Installs a hook procedure that monitors messages after they have been processed by the destination window
/// procedure. For more information, see the CallWndRetProc hook procedure.
/// </summary>
WH_CALLWNDPROCRET = 12,
/// <summary>
/// Installs a hook procedure that monitors low-level keyboard input events. For more information, see the
/// LowLevelKeyboardProc hook procedure.
/// </summary>
WH_KEYBOARD_LL = 13,
/// <summary>
/// Installs a hook procedure that monitors low-level mouse input events. For more information, see the
/// LowLevelMouseProc hook procedure.
/// </summary>
WH_MOUSE_LL = 14
}
#endregion
public static Image CaptureWindow(IntPtr handle)
{
var windowDC = User32.GetWindowDC(handle);
var rECT = new RECT();
User32.GetWindowRect(handle, ref rECT);
var num = rECT.right - rECT.left;
var num1 = rECT.bottom - rECT.top;
var intPtr = GDI32.CreateCompatibleDC(windowDC);
var intPtr1 = GDI32.CreateCompatibleBitmap(windowDC, num, num1);
var intPtr2 = GDI32.SelectObject(intPtr, intPtr1);
GDI32.BitBlt(intPtr, 0, 0, num, num1, windowDC, 0, 0, 13369376);
GDI32.SelectObject(intPtr, intPtr2);
Image image = Image.FromHbitmap(intPtr1);
GDI32.DeleteObject(intPtr1);
GDI32.DeleteDC(intPtr);
User32.ReleaseDC(handle, windowDC);
return image;
}
public static void ClearLastError()
{
SetLastErrorEx(0, 0);
}
public static class GDI32
{
public const int SRCCOPY = 13369376;
[DllImport("gdi32.dll", CharSet = CharSet.None, ExactSpelling = false)]
public static extern bool BitBlt(IntPtr hObject, int nXDest, int nYDest, int nWidth, int nHeight,
IntPtr hObjectSource, int nXSrc, int nYSrc, int dwRop);
[DllImport("gdi32.dll", CharSet = CharSet.None, ExactSpelling = false)]
public static extern IntPtr CreateCompatibleBitmap(IntPtr hDC, int nWidth, int nHeight);
[DllImport("gdi32.dll", CharSet = CharSet.None, ExactSpelling = false)]
public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
[DllImport("gdi32.dll", CharSet = CharSet.None, ExactSpelling = false)]
public static extern bool DeleteDC(IntPtr hDC);
[DllImport("gdi32.dll", CharSet = CharSet.None, ExactSpelling = false)]
public static extern IntPtr DeleteObject(IntPtr hObject);
[DllImport("gdi32.dll", CharSet = CharSet.None, ExactSpelling = false)]
public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
}
public static class User32
{
[DllImport("user32.dll", CharSet = CharSet.None, ExactSpelling = false)]
public static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll", CharSet = CharSet.None, ExactSpelling = false)]
public static extern IntPtr GetWindowDC(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.None, ExactSpelling = false)]
public static extern IntPtr GetWindowRect(IntPtr hWnd, ref RECT rect);
[DllImport("user32.dll", CharSet = CharSet.None, ExactSpelling = false)]
public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
}
#region INPUT-HOOK
[DllImport("user32.dll", SetLastError = true)]
internal static extern void SetLastErrorEx(uint dwErrCode, uint dwType);
[DllImport("user32", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall,
SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(HookType idHook, MouseProc lpfn, int hInstance, int threadId);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall,
SetLastError = true)]
public static extern int CallNextHookEx(IntPtr idHook, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall,
SetLastError = true)]
public static extern int GetCurrentThreadId();
[DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall,
SetLastError = true)]
public static extern int GetModuleHandle(string lpModuleName);
public delegate int MouseProc(int nCode, IntPtr wParam, IntPtr lParam);
#endregion
#region WM-CONST
public const uint WM_ACTIVATE = 0x0006;
public const uint WM_ACTIVATEAPP = 0x001C;
public const uint WM_AFXFIRST = 0x0360;
public const uint WM_AFXLAST = 0x037F;
public const uint WM_APP = 0x8000;
public const uint WM_ASKCBFORMATNAME = 0x030C;
public const uint WM_CANCELJOURNAL = 0x004B;
public const uint WM_CANCELMODE = 0x001F;
public const uint WM_CAPTURECHANGED = 0x0215;
public const uint WM_CHANGECBCHAIN = 0x030D;
public const uint WM_CHANGEUISTATE = 0x0127;
public const uint WM_CHAR = 0x0102;
public const uint WM_CHARTOITEM = 0x002F;
public const uint WM_CHILDACTIVATE = 0x0022;
public const uint WM_CLEAR = 0x0303;
public const uint WM_CLOSE = 0x0010;
public const uint WM_CLIPBOARDUPDATE = 0x031D;
public const uint WM_COMMAND = 0x0111;
public const uint WM_COMPACTING = 0x0041;
public const uint WM_COMPAREITEM = 0x0039;
public const uint WM_CONTEXTMENU = 0x007B;
public const uint WM_COPY = 0x0301;
public const uint WM_COPYDATA = 0x004A;
public const uint WM_CREATE = 0x0001;
public const uint WM_CTLCOLORBTN = 0x0135;
public const uint WM_CTLCOLORDLG = 0x0136;
public const uint WM_CTLCOLOREDIT = 0x0133;
public const uint WM_CTLCOLORLISTBOX = 0x0134;
public const uint WM_CTLCOLORMSGBOX = 0x0132;
public const uint WM_CTLCOLORSCROLLBAR = 0x0137;
public const uint WM_CTLCOLORSTATIC = 0x0138;
public const uint WM_CUT = 0x0300;
public const uint WM_DEADCHAR = 0x0103;
public const uint WM_DELETEITEM = 0x002D;
public const uint WM_DESTROY = 0x0002;
public const uint WM_DESTROYCLIPBOARD = 0x0307;
public const uint WM_DEVICECHANGE = 0x0219;
public const uint WM_DEVMODECHANGE = 0x001B;
public const uint WM_DISPLAYCHANGE = 0x007E;
public const uint WM_DRAWCLIPBOARD = 0x0308;
public const uint WM_DRAWITEM = 0x002B;
public const uint WM_DROPFILES = 0x0233;
public const uint WM_ENABLE = 0x000A;
public const uint WM_ENDSESSION = 0x0016;
public const uint WM_ENTERIDLE = 0x0121;
public const uint WM_ENTERMENULOOP = 0x0211;
public const uint WM_ENTERSIZEMOVE = 0x0231;
public const uint WM_ERASEBKGND = 0x0014;
public const uint WM_EXITMENULOOP = 0x0212;
public const uint WM_EXITSIZEMOVE = 0x0232;
public const uint WM_FONTCHANGE = 0x001D;
public const uint WM_GETDLGCODE = 0x0087;
public const uint WM_GETFONT = 0x0031;
public const uint WM_GETHOTKEY = 0x0033;
public const uint WM_GETICON = 0x007F;
public const uint WM_GETMINMAXINFO = 0x0024;
public const uint WM_GETOBJECT = 0x003D;
public const uint WM_GETTEXT = 0x000D;
public const uint WM_GETTEXTLENGTH = 0x000E;
public const uint WM_HANDHELDFIRST = 0x0358;
public const uint WM_HANDHELDLAST = 0x035F;
public const uint WM_HELP = 0x0053;
public const uint WM_HOTKEY = 0x0312;
public const uint WM_HSCROLL = 0x0114;
public const uint WM_HSCROLLCLIPBOARD = 0x030E;
public const uint WM_ICONERASEBKGND = 0x0027;
public const uint WM_IME_CHAR = 0x0286;
public const uint WM_IME_COMPOSITION = 0x010F;
public const uint WM_IME_COMPOSITIONFULL = 0x0284;
public const uint WM_IME_CONTROL = 0x0283;
public const uint WM_IME_ENDCOMPOSITION = 0x010E;
public const uint WM_IME_KEYDOWN = 0x0290;
public const uint WM_IME_KEYLAST = 0x010F;
public const uint WM_IME_KEYUP = 0x0291;
public const uint WM_IME_NOTIFY = 0x0282;
public const uint WM_IME_REQUEST = 0x0288;
public const uint WM_IME_SELECT = 0x0285;
public const uint WM_IME_SETCONTEXT = 0x0281;
public const uint WM_IME_STARTCOMPOSITION = 0x010D;
public const uint WM_INITDIALOG = 0x0110;
public const uint WM_INITMENU = 0x0116;
public const uint WM_INITMENUPOPUP = 0x0117;
public const uint WM_INPUTLANGCHANGE = 0x0051;
public const uint WM_INPUTLANGCHANGEREQUEST = 0x0050;
public const uint WM_KEYDOWN = 0x0100;
public const uint WM_KEYFIRST = 0x0100;
public const uint WM_KEYLAST = 0x0108;
public const uint WM_KEYUP = 0x0101;
public const uint WM_KILLFOCUS = 0x0008;
public const uint WM_LBUTTONDBLCLK = 0x0203;
public const uint WM_LBUTTONDOWN = 0x0201;
public const uint WM_LBUTTONUP = 0x0202;
public const uint WM_MBUTTONDBLCLK = 0x0209;
public const uint WM_MBUTTONDOWN = 0x0207;
public const uint WM_MBUTTONUP = 0x0208;
public const uint WM_MDIACTIVATE = 0x0222;
public const uint WM_MDICASCADE = 0x0227;
public const uint WM_MDICREATE = 0x0220;
public const uint WM_MDIDESTROY = 0x0221;
public const uint WM_MDIGETACTIVE = 0x0229;
public const uint WM_MDIICONARRANGE = 0x0228;
public const uint WM_MDIMAXIMIZE = 0x0225;
public const uint WM_MDINEXT = 0x0224;
public const uint WM_MDIREFRESHMENU = 0x0234;
public const uint WM_MDIRESTORE = 0x0223;
public const uint WM_MDISETMENU = 0x0230;
public const uint WM_MDITILE = 0x0226;
public const uint WM_MEASUREITEM = 0x002C;
public const uint WM_MENUCHAR = 0x0120;
public const uint WM_MENUCOMMAND = 0x0126;
public const uint WM_MENUDRAG = 0x0123;
public const uint WM_MENUGETOBJECT = 0x0124;
public const uint WM_MENURBUTTONUP = 0x0122;
public const uint WM_MENUSELECT = 0x011F;
public const uint WM_MOUSEACTIVATE = 0x0021;
public const uint WM_MOUSEFIRST = 0x0200;
public const uint WM_MOUSEHOVER = 0x02A1;
public const uint WM_MOUSELAST = 0x020D;
public const uint WM_MOUSELEAVE = 0x02A3;
public const uint WM_MOUSEMOVE = 0x0200;
public const uint WM_MOUSEWHEEL = 0x020A;
public const uint WM_MOUSEHWHEEL = 0x020E;
public const uint WM_MOVE = 0x0003;
public const uint WM_MOVING = 0x0216;
public const uint WM_NCACTIVATE = 0x0086;
public const uint WM_NCCALCSIZE = 0x0083;
public const uint WM_NCCREATE = 0x0081;
public const uint WM_NCDESTROY = 0x0082;
public const uint WM_NCHITTEST = 0x0084;
public const uint WM_NCLBUTTONDBLCLK = 0x00A3;
public const uint WM_NCLBUTTONDOWN = 0x00A1;
public const uint WM_NCLBUTTONUP = 0x00A2;
public const uint WM_NCMBUTTONDBLCLK = 0x00A9;
public const uint WM_NCMBUTTONDOWN = 0x00A7;
public const uint WM_NCMBUTTONUP = 0x00A8;
public const uint WM_NCMOUSEHOVER = 0x02A0;
public const uint WM_NCMOUSELEAVE = 0x02A2;
public const uint WM_NCMOUSEMOVE = 0x00A0;
public const uint WM_NCPAINT = 0x0085;
public const uint WM_NCRBUTTONDBLCLK = 0x00A6;
public const uint WM_NCRBUTTONDOWN = 0x00A4;
public const uint WM_NCRBUTTONUP = 0x00A5;
public const uint WM_NCXBUTTONDBLCLK = 0x00AD;
public const uint WM_NCXBUTTONDOWN = 0x00AB;
public const uint WM_NCXBUTTONUP = 0x00AC;
public const uint WM_NCUAHDRAWCAPTION = 0x00AE;
public const uint WM_NCUAHDRAWFRAME = 0x00AF;
public const uint WM_NEXTDLGCTL = 0x0028;
public const uint WM_NEXTMENU = 0x0213;
public const uint WM_NOTIFY = 0x004E;
public const uint WM_NOTIFYFORMAT = 0x0055;
public const uint WM_NULL = 0x0000;
public const uint WM_PAINT = 0x000F;
public const uint WM_PAINTCLIPBOARD = 0x0309;
public const uint WM_PAINTICON = 0x0026;
public const uint WM_PALETTECHANGED = 0x0311;
public const uint WM_PALETTEISCHANGING = 0x0310;
public const uint WM_PARENTNOTIFY = 0x0210;
public const uint WM_PASTE = 0x0302;
public const uint WM_PENWINFIRST = 0x0380;
public const uint WM_PENWINLAST = 0x038F;
public const uint WM_POWER = 0x0048;
public const uint WM_POWERBROADCAST = 0x0218;
public const uint WM_PRINT = 0x0317;
public const uint WM_PRINTCLIENT = 0x0318;
public const uint WM_QUERYDRAGICON = 0x0037;
public const uint WM_QUERYENDSESSION = 0x0011;
public const uint WM_QUERYNEWPALETTE = 0x030F;
public const uint WM_QUERYOPEN = 0x0013;
public const uint WM_QUEUESYNC = 0x0023;
public const uint WM_QUIT = 0x0012;
public const uint WM_RBUTTONDBLCLK = 0x0206;
public const uint WM_RBUTTONDOWN = 0x0204;
public const uint WM_RBUTTONUP = 0x0205;
public const uint WM_RENDERALLFORMATS = 0x0306;
public const uint WM_RENDERFORMAT = 0x0305;
public const uint WM_SETCURSOR = 0x0020;
public const uint WM_SETFOCUS = 0x0007;
public const uint WM_SETFONT = 0x0030;
public const uint WM_SETHOTKEY = 0x0032;
public const uint WM_SETICON = 0x0080;
public const uint WM_SETREDRAW = 0x000B;
public const uint WM_SETTEXT = 0x000C;
public const uint WM_SETTINGCHANGE = 0x001A;
public const uint WM_SHOWWINDOW = 0x0018;
public const uint WM_SIZE = 0x0005;
public const uint WM_SIZECLIPBOARD = 0x030B;
public const uint WM_SIZING = 0x0214;
public const uint WM_SPOOLERSTATUS = 0x002A;
public const uint WM_STYLECHANGED = 0x007D;
public const uint WM_STYLECHANGING = 0x007C;
public const uint WM_SYNCPAINT = 0x0088;
public const uint WM_SYSCHAR = 0x0106;
public const uint WM_SYSCOLORCHANGE = 0x0015;
public const uint WM_SYSCOMMAND = 0x0112;
public const uint WM_SYSDEADCHAR = 0x0107;
public const uint WM_SYSKEYDOWN = 0x0104;
public const uint WM_SYSKEYUP = 0x0105;
public const uint WM_TCARD = 0x0052;
public const uint WM_TIMECHANGE = 0x001E;
public const uint WM_TIMER = 0x0113;
public const uint WM_UNDO = 0x0304;
public const uint WM_UNINITMENUPOPUP = 0x0125;
public const uint WM_USER = 0x0400;
public const uint WM_USERCHANGED = 0x0054;
public const uint WM_VKEYTOITEM = 0x002E;
public const uint WM_VSCROLL = 0x0115;
public const uint WM_VSCROLLCLIPBOARD = 0x030A;
public const uint WM_WINDOWPOSCHANGED = 0x0047;
public const uint WM_WINDOWPOSCHANGING = 0x0046;
public const uint WM_WININICHANGE = 0x001A;
public const uint WM_XBUTTONDBLCLK = 0x020D;
public const uint WM_XBUTTONDOWN = 0x020B;
public const uint WM_XBUTTONUP = 0x020C;
#endregion
#region STRUCT
[StructLayout(LayoutKind.Sequential)]
private struct MouseHookStructEx
{
public readonly MOUSEHOOKSTRUCT mouseHookStruct;
public readonly int MouseData;
}
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
[StructLayout(LayoutKind.Sequential)]
public struct Point
{
public int X;
public int Y;
}
[StructLayout(LayoutKind.Sequential)]
public struct MOUSEHOOKSTRUCT
{
public Point pt;
public IntPtr hwnd;
public uint wHitTestCode;
public IntPtr dwExtraInfo;
}
#endregion
}
}

View File

@ -7,6 +7,10 @@
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

BIN
Client/Scripts/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -24,6 +24,7 @@
<package id="System.Diagnostics.DiagnosticSource" version="4.3.0" targetFramework="net48" />
<package id="System.Diagnostics.Tools" version="4.3.0" targetFramework="net48" />
<package id="System.Diagnostics.Tracing" version="4.3.0" targetFramework="net48" />
<package id="System.Drawing.Common" version="4.5.0" targetFramework="net48" />
<package id="System.Globalization" version="4.3.0" targetFramework="net48" />
<package id="System.Globalization.Calendars" version="4.3.0" targetFramework="net48" />
<package id="System.IO" version="4.3.0" targetFramework="net48" />
@ -33,7 +34,7 @@
<package id="System.IO.FileSystem.Primitives" version="4.3.0" targetFramework="net48" />
<package id="System.Linq" version="4.3.0" targetFramework="net48" />
<package id="System.Linq.Expressions" version="4.3.0" targetFramework="net48" />
<package id="System.Memory" version="4.5.4" targetFramework="net48" />
<package id="System.Memory" version="4.5.5" targetFramework="net48" />
<package id="System.Net.Http" version="4.3.0" targetFramework="net48" />
<package id="System.Net.Primitives" version="4.3.0" targetFramework="net48" />
<package id="System.Net.Sockets" version="4.3.0" targetFramework="net48" />

Binary file not shown.