ResourceDomain

This commit is contained in:
sardelka9515
2022-10-08 12:43:24 +08:00
parent a062322dda
commit 54c7f4ce92
17 changed files with 291 additions and 49 deletions

View File

@ -73,8 +73,9 @@ namespace RageCoop.Client
}
DevToolMenu.secondaryBoneIndexItem.AltTitle = Secondary.ToString();
}
private static void OnTick(object sender, EventArgs e)
private void OnTick(object sender, EventArgs e)
{
if (!Util.ShouldBeRunning) { Abort(); }
if (ToMark == null || !ToMark.Exists()) { return; }
Update();
Draw(Current);

View File

@ -2,8 +2,10 @@
using GTA.Math;
using GTA.Native;
using RageCoop.Client.Menus;
using RageCoop.Client.Scripting;
using RageCoop.Core;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
@ -19,7 +21,7 @@ namespace RageCoop.Client
/// </summary>
internal class Main : Script
{
private bool _gameLoaded = false;
private static bool _gameLoaded = false;
internal static Version Version = typeof(Main).Assembly.GetName().Version;
internal static int LocalPlayerID = 0;
@ -34,26 +36,27 @@ namespace RageCoop.Client
internal static Chat MainChat = null;
internal static Stopwatch Counter = new Stopwatch();
internal static Logger Logger = null;
internal static ulong Ticked = 0;
internal static Vector3 PlayerPosition;
internal static Scripting.Resources Resources = null;
private static readonly ConcurrentQueue<Action> TaskQueue = new ConcurrentQueue<Action>();
private static readonly List<Func<bool>> QueuedActions = new List<Func<bool>>();
public static Worker Worker;
public static string ScriptPath;
/// <summary>
/// Don't use it!
/// </summary>
public Main()
{
Worker = new Worker("RageCoop.Client.Main.Worker", Logger);
ScriptPath = Filename;
if (!Util.ShouldBeRunning) { return; }
try
{
Settings = Util.ReadSettings();
}
catch
{
GTA.UI.Notification.Show("Malformed configuration, overwriting with default values...");
// GTA.UI.Notification.Show("Malformed configuration, overwriting with default values...");
Settings = new Settings();
Util.SaveSettings();
}
@ -68,7 +71,9 @@ namespace RageCoop.Client
LogLevel=Settings.LogLevel,
#endif
};
Resources = new Scripting.Resources();
Worker = new Worker("RageCoop.Client.Main.Worker", Logger);
SHVDN.ScriptDomain.CurrentDomain.Tick += DomainTick;
Resources = new Resources();
if (Game.Version < GameVersion.v1_0_1290_1_Steam)
{
Tick += (object sender, EventArgs e) =>
@ -91,21 +96,66 @@ namespace RageCoop.Client
#if !NON_INTERACTIVE
#endif
MainChat = new Chat();
Aborted += OnAborted;
Tick += OnTick;
Tick += (s, e) => { Scripting.API.Events.InvokeTick(); };
Tick += (s, e) => { API.Events.InvokeTick(); };
KeyDown += OnKeyDown;
KeyDown += (s, e) => { Scripting.API.Events.InvokeKeyDown(s, e); };
KeyUp += (s, e) => { Scripting.API.Events.InvokeKeyUp(s, e); };
KeyDown += (s, e) => { API.Events.InvokeKeyDown(s, e); };
KeyUp += (s, e) => { API.Events.InvokeKeyUp(s, e); };
Aborted += (object sender, EventArgs e) => Disconnected("Abort");
Util.NativeMemory();
Counter.Restart();
}
private static void OnAborted(object sender, EventArgs e)
{
try
{
ResourceDomain.Unload();
SHVDN.ScriptDomain.CurrentDomain.Tick -= DomainTick;
}
catch(Exception ex)
{
Logger.Error(ex);
}
}
private static void DomainTick(object sender, EventArgs e)
{
while(TaskQueue.TryDequeue(out var task))
{
try
{
task.Invoke();
}
catch(Exception ex)
{
Logger.Error(ex);
}
}
if (Networking.IsOnServer)
{
try
{
EntityPool.DoSync();
}
catch (Exception ex)
{
Logger.Error(ex);
}
}
}
internal static void QueueToMainThread(Action task)
{
TaskQueue.Enqueue(task);
}
public static Ped P;
public static float FPS;
private bool _lastDead;
private void OnTick(object sender, EventArgs e)
private static bool _lastDead;
private static void OnTick(object sender, EventArgs e)
{
P = Game.Player.Character;
PlayerPosition = P.ReadPosition();
@ -135,14 +185,6 @@ namespace RageCoop.Client
{
Game.TimeScale = 1;
}
try
{
EntityPool.DoSync();
}
catch (Exception ex)
{
Main.Logger.Error(ex);
}
if (Networking.ShowNetworkInfo)
{
@ -153,7 +195,7 @@ namespace RageCoop.Client
MainChat.Tick();
PlayerList.Tick();
if (!Scripting.API.Config.EnableAutoRespawn)
if (!API.Config.EnableAutoRespawn)
{
Function.Call(Hash.PAUSE_DEATH_ARREST_RESTART, true);
Function.Call(Hash.IGNORE_NEXT_RESTART, true);
@ -167,8 +209,8 @@ namespace RageCoop.Client
{
P.Health = 1;
Game.Player.WantedLevel = 0;
Main.Logger.Debug("Player died.");
Scripting.API.Events.InvokePlayerDied();
Logger.Debug("Player died.");
API.Events.InvokePlayerDied();
}
GTA.UI.Screen.StopEffects();
}
@ -185,8 +227,16 @@ namespace RageCoop.Client
_lastDead = P.IsDead;
Ticked++;
}
private void OnKeyDown(object sender, KeyEventArgs e)
private static void OnKeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.U)
{
ResourceDomain.Unload();
}
if (e.KeyCode == Keys.L)
{
ResourceDomain.Load();
}
if (MainChat.Focused)
{
MainChat.OnKeyDown(e.KeyCode);

View File

@ -16,7 +16,7 @@ using System.Resources;
// Version informationr(
[assembly: AssemblyVersion("1.5.4.9")]
[assembly: AssemblyFileVersion("1.5.4.9")]
[assembly: AssemblyVersion("1.5.4.105")]
[assembly: AssemblyFileVersion("1.5.4.105")]
[assembly: NeutralResourcesLanguageAttribute( "en-US" )]

View File

@ -55,6 +55,7 @@
<Compile Include="Scripting\API.cs" />
<Compile Include="Scripting\BaseScript.cs" />
<Compile Include="Scripting\ClientScript.cs" />
<Compile Include="Scripting\ResourceDomain.cs" />
<Compile Include="Scripting\Resources.cs" />
<Compile Include="Security.cs" />
<Compile Include="Settings.cs" />
@ -296,6 +297,17 @@
<ItemGroup>
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
</ItemGroup>
<ItemGroup>
<COMReference Include="mscoree">
<Guid>{5477469E-83B1-11D2-8B49-00A0C9B7C9C4}</Guid>
<VersionMajor>2</VersionMajor>
<VersionMinor>4</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>tlbimp</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\Fody.6.6.3\build\Fody.targets" Condition="Exists('..\packages\Fody.6.6.3\build\Fody.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">

View File

@ -93,10 +93,9 @@ namespace RageCoop.Client.Scripting
{
var vehicleModel = (Model)e.Args[1];
vehicleModel.Request(1000);
Vehicle veh = World.CreateVehicle(vehicleModel, (Vector3)e.Args[2], (float)e.Args[3]);
while (veh == null)
Vehicle veh;
while ((veh = World.CreateVehicle(vehicleModel, (Vector3)e.Args[2], (float)e.Args[3])) == null)
{
veh = World.CreateVehicle(vehicleModel, (Vector3)e.Args[2], (float)e.Args[3]);
Thread.Sleep(10);
}
veh.CanPretendOccupants = false;

View File

@ -0,0 +1,109 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using SHVDN;
using RageCoop.Core;
using GTA.Native;
using System.Reflection;
using System.Windows.Forms;
namespace RageCoop.Client.Scripting
{
public class ResourceDomain : MarshalByRefObject, IDisposable
{
public static ResourceDomain Instance;
readonly ScriptDomain RootDomain;
ScriptDomain CurrentDomain => ScriptDomain.CurrentDomain;
internal ResourceDomain(ScriptDomain root)
{
RootDomain = root;
// Bridge to current ScriptDomain
root.Tick += Tick;
root.KeyEvent += KeyEvent;
}
public static void Load()
{
if (Instance != null)
{
throw new Exception("Already loaded");
}
ScriptDomain domain = null;
try
{
var dir = Path.GetFullPath(@"RageCoop\Scripts");
if (Directory.Exists(dir))
{
Directory.Delete(dir, true);
}
Directory.CreateDirectory(dir);
// Copy API assemblies
var api = typeof(ResourceDomain).Assembly;
File.Copy(api.Location, Path.Combine(dir, Path.GetFileName(api.Location)), true);
foreach (var a in api.GetReferencedAssemblies())
{
var asm = Assembly.Load(a.FullName);
if (string.IsNullOrEmpty(asm.Location))
{
continue;
}
File.Copy(asm.Location, Path.Combine(dir, Path.GetFileName(asm.Location)), true);
}
// Copy test script
// File.Copy(@"M:\SandBox-Shared\repos\RAGECOOP\RAGECOOP-V\bin\Debug\TestScript.dll", Path.Combine(dir, Path.GetFileName("TestScript.dll")), true);
// Load domain in main thread
Main.QueueToMainThread(() =>
{
domain = ScriptDomain.Load(Directory.GetParent(typeof(ScriptDomain).Assembly.Location).FullName, dir);
domain.AppDomain.SetData("Console",ScriptDomain.CurrentDomain.AppDomain.GetData("Console"));
Instance = (ResourceDomain)domain.AppDomain.CreateInstanceFromAndUnwrap(typeof(ResourceDomain).Assembly.Location, typeof(ResourceDomain).FullName, false, BindingFlags.NonPublic | BindingFlags.Instance, null, new object[] { ScriptDomain.CurrentDomain }, null, null);
domain.Start();
});
// Wait till next tick
GTA.Script.Yield();
}
catch (Exception ex)
{
GTA.UI.Notification.Show(ex.ToString());
Main.Logger.Error(ex);
if (domain != null)
{
ScriptDomain.Unload(domain);
}
}
}
public static void Unload()
{
if (Instance == null)
{
return;
}
Instance.Dispose();
ScriptDomain.Unload(Instance.CurrentDomain);
Instance = null;
}
void Tick(object sender, EventArgs args)
{
CurrentDomain.DoTick();
}
void KeyEvent(Keys keys, bool status)
{
CurrentDomain.DoKeyEvent(keys, status);
}
public void Dispose()
{
RootDomain.Tick -= Tick;
RootDomain.KeyEvent -= KeyEvent;
}
}
}

View File

@ -40,8 +40,10 @@ namespace RageCoop.Client
var flag = AnimationFlags.Loop;
if (!Function.Call<bool>(Hash.IS_ENTITY_PLAYING_ANIM, MainPed, animDict, ourAnim, 3))
{
if (LoadAnim(animDict) == null) { return; }
MainPed.Task.ClearAll();
Function.Call(Hash.TASK_PLAY_ANIM, MainPed, LoadAnim(animDict), ourAnim, 8f, 10f, -1, flag, -8f, 1, 1, 1);
Function.Call(Hash.TASK_PLAY_ANIM, MainPed, animDict, ourAnim, 8f, 10f, -1, flag, -8f, 1, 1, 1);
}
}
}
@ -143,18 +145,11 @@ namespace RageCoop.Client
private string LoadAnim(string anim)
{
ulong startTime = Util.GetTickCount64();
while (!Function.Call<bool>(Hash.HAS_ANIM_DICT_LOADED, anim))
if(!Function.Call<bool>(Hash.HAS_ANIM_DICT_LOADED, anim))
{
Script.Yield();
Function.Call(Hash.REQUEST_ANIM_DICT, anim);
if (Util.GetTickCount64() - startTime >= 1000)
{
break;
}
return null;
}
return anim;
}
}

View File

@ -283,7 +283,10 @@ namespace RageCoop.Client
if (!Function.Call<bool>(Hash.IS_ENTITY_PLAYING_ANIM, MainPed.Handle, "skydive@base", "free_idle", 3))
{
Function.Call(Hash.TASK_PLAY_ANIM, MainPed.Handle, LoadAnim("skydive@base"), "free_idle", 8f, 10f, -1, 0, -8f, 1, 1, 1);
// Skip update if animation is not loaded
var dict = LoadAnim("skydive@base");
if (dict == null) { return; }
Function.Call(Hash.TASK_PLAY_ANIM, MainPed.Handle, dict, "free_idle", 8f, 10f, -1, 0, -8f, 1, 1, 1);
}
return;
}
@ -312,7 +315,9 @@ namespace RageCoop.Client
if (!Function.Call<bool>(Hash.IS_ENTITY_PLAYING_ANIM, MainPed.Handle, "skydive@parachute@first_person", "chute_idle_right", 3))
{
Function.Call(Hash.TASK_PLAY_ANIM, MainPed, LoadAnim("skydive@parachute@first_person"), "chute_idle_right", 8f, 10f, -1, 0, -8f, 1, 1, 1);
var dict = LoadAnim("skydive@parachute@first_person");
if (dict == null) { return; }
Function.Call(Hash.TASK_PLAY_ANIM, MainPed, dict, "chute_idle_right", 8f, 10f, -1, 0, -8f, 1, 1, 1);
}
return;

View File

@ -3,6 +3,7 @@ using GTA.Math;
using GTA.Native;
using RageCoop.Core;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
@ -10,12 +11,44 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Xml.Serialization;
using mscoree;
using System.Runtime.InteropServices.ComTypes;
[assembly: InternalsVisibleTo("RageCoop.Client.Installer")]
namespace RageCoop.Client
{
internal static class Util
{
public static bool ShouldBeRunning => Main.ScriptPath == null || Main.ScriptPath.ToLower() == Path.Combine(Directory.GetCurrentDirectory(), @"Scripts\RageCoop\RageCoop.Client.dll").ToLower();
public static IList<AppDomain> GetAppDomains()
{
IList<AppDomain> _IList = new List<AppDomain>();
IntPtr enumHandle = IntPtr.Zero;
ICorRuntimeHost host = new CorRuntimeHost();
try
{
host.EnumDomains(out enumHandle);
object domain = null;
while (true)
{
host.NextDomain(enumHandle, out domain);
if (domain == null) break;
AppDomain appDomain = (AppDomain)domain;
_IList.Add(appDomain);
}
return _IList;
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
return null;
}
finally
{
host.CloseEnum(enumHandle);
Marshal.ReleaseComObject(host);
}
}
public static SizeF ResolutionMaintainRatio
{
get

View File

@ -25,6 +25,7 @@ namespace RageCoop.Client
private static bool _trafficEnabled;
private void OnTick(object sender, EventArgs e)
{
if (!Util.ShouldBeRunning) { Abort(); }
if (Game.IsLoading || !Networking.IsOnServer)
{
return;

View File

@ -26,15 +26,16 @@ namespace RageCoop.Core
{
private static readonly HashSet<string> ToIgnore = new HashSet<string>()
{
"RageCoop.Client.dll",
"RageCoop.Core.dll",
"RageCoop.Server.dll",
"ScriptHookVDotNet3.dll",
"ScriptHookVDotNet.dll"
"RageCoop.Client",
"RageCoop.Core",
"RageCoop.Server",
"ScriptHookVDotNet2",
"ScriptHookVDotNet3",
"ScriptHookVDotNet"
};
public static bool CanBeIgnored(this string name)
{
return ToIgnore.Contains(name);
return ToIgnore.Contains(Path.GetFileNameWithoutExtension(name));
}
public static void GetBytesFromObject(object obj, NetOutgoingMessage m)
{

View File

@ -15,7 +15,7 @@ using System.Resources;
[assembly: AssemblyCulture("")]
// Version information
[assembly: AssemblyVersion("1.5.4.10")]
[assembly: AssemblyFileVersion("1.5.4.10")]
[assembly: AssemblyVersion("1.5.4.40")]
[assembly: AssemblyFileVersion("1.5.4.40")]
[assembly: NeutralResourcesLanguageAttribute( "en-US" )]

19
TestScript/Test.cs Normal file
View File

@ -0,0 +1,19 @@
using System;
using GTA;
using GTA.UI;
namespace TestScript
{
public class Test : Script
{
public Test()
{
Tick += OnTick;
}
private void OnTick(object sender, EventArgs e)
{
Screen.ShowHelpTextThisFrame("bruh");
}
}
}

View File

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<OutDir>..\bin\Debug</OutDir>
</PropertyGroup>
<ItemGroup>
<Reference Include="ScriptHookVDotNet">
<HintPath>..\libs\ScriptHookVDotNet.dll</HintPath>
</Reference>
<Reference Include="ScriptHookVDotNet3">
<HintPath>..\libs\ScriptHookVDotNet3.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

Binary file not shown.

Binary file not shown.

Binary file not shown.