Change settings and data directory
This commit is contained in:
parent
1606d25fed
commit
617dbc9812
@ -8,6 +8,7 @@ using System.Windows.Forms;
|
||||
|
||||
namespace RageCoop.Client
|
||||
{
|
||||
[ScriptAttributes(Author = "RageCoop", NoDefaultInstance = false, SupportURL = "https://github.com/RAGECOOP/RAGECOOP-V")]
|
||||
internal class DevTool : Script
|
||||
{
|
||||
public static Vehicle ToMark;
|
||||
@ -15,11 +16,14 @@ namespace RageCoop.Client
|
||||
public static int Current = 0;
|
||||
public static int Secondary = 0;
|
||||
public static MuzzleDir Direction = MuzzleDir.Forward;
|
||||
public static Script Instance;
|
||||
public DevTool()
|
||||
{
|
||||
if (!Main.IsPrimaryDomain) { return; }
|
||||
Instance = this;
|
||||
if (!Util.IsPrimaryDomain) { Abort(); return; }
|
||||
Tick += OnTick;
|
||||
KeyDown += OnKeyDown;
|
||||
Pause();
|
||||
}
|
||||
|
||||
private void OnKeyDown(object sender, KeyEventArgs e)
|
||||
|
@ -4,6 +4,8 @@ using GTA.Native;
|
||||
using RageCoop.Client.Menus;
|
||||
using RageCoop.Client.Scripting;
|
||||
using RageCoop.Core;
|
||||
using SHVDN;
|
||||
using Script = GTA.Script;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
@ -13,15 +15,16 @@ using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Console = GTA.Console;
|
||||
|
||||
namespace RageCoop.Client
|
||||
{
|
||||
/// <summary>
|
||||
/// Don't use it!
|
||||
/// </summary>
|
||||
[ScriptAttributes(Author = "RageCoop", NoDefaultInstance = false, SupportURL = "https://github.com/RAGECOOP/RAGECOOP-V")]
|
||||
internal class Main : Script
|
||||
{
|
||||
public static bool IsPrimaryDomain => (AppDomain.CurrentDomain.GetData("Primary") as bool?) != false;
|
||||
public static API API = API.GetInstance();
|
||||
private static bool _gameLoaded = false;
|
||||
internal static Version Version = typeof(Main).Assembly.GetName().Version;
|
||||
@ -43,17 +46,28 @@ namespace RageCoop.Client
|
||||
internal static Resources Resources = null;
|
||||
private static readonly ConcurrentQueue<Action> TaskQueue = new ConcurrentQueue<Action>();
|
||||
public static Worker Worker;
|
||||
internal static SHVDN.Console Console => AppDomain.CurrentDomain.GetData("Console") as SHVDN.Console;
|
||||
/// <summary>
|
||||
/// Don't use it!
|
||||
/// </summary>
|
||||
public Main()
|
||||
{
|
||||
Console.PrintInfo($"Starting {typeof(Main).FullName}, domain: {AppDomain.CurrentDomain.Id}, {IsPrimaryDomain}");
|
||||
if (!IsPrimaryDomain) { Console.PrintInfo("Ignored loading in scondary domain"); return; }
|
||||
Console.WriteLine($"Starting {typeof(Main).FullName}, domain: {AppDomain.CurrentDomain.Id}, {Util.IsPrimaryDomain}");
|
||||
if (!Util.IsPrimaryDomain) { Console.WriteLine("Ignored loading in scondary domain"); Abort(); return; }
|
||||
try
|
||||
{
|
||||
Settings = Util.ReadSettings();
|
||||
if (Settings.DataDirectory.StartsWith("Scripts"))
|
||||
{
|
||||
var defaultDir = new Settings().DataDirectory;
|
||||
Console.Warning.WriteLine("Data directory must be outside scripts folder, migrating to default direcoty: "+defaultDir);
|
||||
if (Directory.Exists(Settings.DataDirectory))
|
||||
{
|
||||
CoreUtils.CopyFilesRecursively(new DirectoryInfo(Settings.DataDirectory), new DirectoryInfo(defaultDir));
|
||||
Directory.Delete(Settings.DataDirectory, true);
|
||||
}
|
||||
Settings.DataDirectory = defaultDir;
|
||||
Util.SaveSettings();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
@ -73,7 +87,7 @@ namespace RageCoop.Client
|
||||
#endif
|
||||
};
|
||||
Worker = new Worker("RageCoop.Client.Main.Worker", Logger);
|
||||
SHVDN.ScriptDomain.CurrentDomain.Tick += DomainTick;
|
||||
ScriptDomain.CurrentDomain.Tick += DomainTick;
|
||||
Resources = new Resources();
|
||||
if (Game.Version < GameVersion.v1_0_1290_1_Steam)
|
||||
{
|
||||
@ -99,10 +113,7 @@ namespace RageCoop.Client
|
||||
MainChat = new Chat();
|
||||
Aborted += OnAborted;
|
||||
Tick += OnTick;
|
||||
Tick += (s, e) => { API.Events.InvokeTick(); };
|
||||
KeyDown += OnKeyDown;
|
||||
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();
|
||||
@ -114,8 +125,11 @@ namespace RageCoop.Client
|
||||
{
|
||||
try
|
||||
{
|
||||
ResourceDomain.Unload();
|
||||
SHVDN.ScriptDomain.CurrentDomain.Tick -= DomainTick;
|
||||
WorldThread.DoQueuedActions();
|
||||
WorldThread.Instance?.Abort();
|
||||
DevTool.Instance?.Abort();
|
||||
ResourceDomain.UnloadAll();
|
||||
ScriptDomain.CurrentDomain.Tick -= DomainTick;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -230,14 +244,6 @@ namespace RageCoop.Client
|
||||
}
|
||||
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);
|
||||
|
@ -1,12 +1,15 @@
|
||||
using GTA;
|
||||
using LemonUI.Menus;
|
||||
using RageCoop.Client.Scripting;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
|
||||
namespace RageCoop.Client
|
||||
{
|
||||
internal static class DebugMenu
|
||||
{
|
||||
public static string DebugLocation => Path.Combine(Main.Settings.DataDirectory, @"Debug");
|
||||
public static NativeMenu Menu = new NativeMenu("RAGECOOP", "Debug", "Debug settings")
|
||||
{
|
||||
UseMouse = false,
|
||||
@ -17,6 +20,7 @@ namespace RageCoop.Client
|
||||
UseMouse = false,
|
||||
Alignment = Main.Settings.FlipMenu ? GTA.UI.Alignment.Right : GTA.UI.Alignment.Left
|
||||
};
|
||||
public static NativeItem DebugScriptsItem = new NativeItem("Load debug scripts", $"Load scripts from {DebugLocation}");
|
||||
public static NativeItem SimulatedLatencyItem = new NativeItem("Simulated network latency", "Simulated network latency in ms (one way)", "0");
|
||||
public static NativeCheckboxItem ShowOwnerItem = new NativeCheckboxItem("Show entity owner", "Show the owner name of the entity you're aiming at", false);
|
||||
private static readonly NativeCheckboxItem ShowNetworkInfoItem = new NativeCheckboxItem("Show Network Info", Networking.ShowNetworkInfo);
|
||||
@ -46,13 +50,29 @@ namespace RageCoop.Client
|
||||
};
|
||||
ShowNetworkInfoItem.CheckboxChanged += (s, e) => { Networking.ShowNetworkInfo = ShowNetworkInfoItem.Checked; };
|
||||
ShowOwnerItem.CheckboxChanged += (s, e) => { Main.Settings.ShowEntityOwnerName = ShowOwnerItem.Checked; Util.SaveSettings(); };
|
||||
DebugScriptsItem.Activated += ToggleScripts;
|
||||
Menu.Add(SimulatedLatencyItem);
|
||||
Menu.Add(ShowNetworkInfoItem);
|
||||
Menu.Add(ShowOwnerItem);
|
||||
Menu.Add(DebugScriptsItem);
|
||||
Menu.AddSubMenu(DiagnosticMenu);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static void ToggleScripts(object sender, EventArgs e)
|
||||
{
|
||||
if (ResourceDomain.IsLoaded(DebugLocation))
|
||||
{
|
||||
ResourceDomain.Unload(DebugLocation);
|
||||
DebugScriptsItem.Title = "Load debug scripts";
|
||||
DebugScriptsItem.Description = $"Load scripts from {DebugLocation}";
|
||||
}
|
||||
else
|
||||
{
|
||||
ResourceDomain.Load(DebugLocation);
|
||||
DebugScriptsItem.Title = "Unload debug scripts";
|
||||
DebugScriptsItem.Description = $"Unload scripts from {DebugLocation}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -73,10 +73,12 @@ namespace RageCoop.Client
|
||||
{
|
||||
if (enableItem.Checked)
|
||||
{
|
||||
DevTool.Instance.Resume();
|
||||
DevTool.ToMark = Game.Player.Character.CurrentVehicle;
|
||||
}
|
||||
else
|
||||
{
|
||||
DevTool.Instance.Pause();
|
||||
DevTool.ToMark = null;
|
||||
}
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ namespace RageCoop.Client
|
||||
});
|
||||
}
|
||||
}
|
||||
public static bool IsOnServer { get => ServerConnection?.Status == NetConnectionStatus.Connected; }
|
||||
public static bool IsOnServer => ServerConnection?.Status == NetConnectionStatus.Connected;
|
||||
|
||||
#region -- PLAYER --
|
||||
private static void PlayerConnect(Packets.PlayerConnect packet)
|
||||
|
@ -16,7 +16,7 @@ using System.Resources;
|
||||
|
||||
|
||||
// Version informationr(
|
||||
[assembly: AssemblyVersion("1.5.4.146")]
|
||||
[assembly: AssemblyFileVersion("1.5.4.146")]
|
||||
[assembly: AssemblyVersion("1.5.4.184")]
|
||||
[assembly: AssemblyFileVersion("1.5.4.184")]
|
||||
[assembly: NeutralResourcesLanguageAttribute( "en-US" )]
|
||||
|
||||
|
@ -297,17 +297,6 @@
|
||||
<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">
|
||||
|
@ -112,32 +112,12 @@ namespace RageCoop.Client.Scripting
|
||||
/// </summary>
|
||||
public event EventHandler<SyncedPed> OnPedDeleted;
|
||||
|
||||
/// <summary>
|
||||
/// This is equivalent of <see cref="GTA.Script.Tick"/>.
|
||||
/// </summary>
|
||||
public event EmptyEvent OnTick;
|
||||
|
||||
/// <summary>
|
||||
/// This is equivalent of <see cref="Script.KeyDown"/>
|
||||
/// </summary>
|
||||
public KeyEventHandler OnKeyDown;
|
||||
|
||||
/// <summary>
|
||||
/// This is equivalent of <see cref="Script.KeyUp"/>
|
||||
/// </summary>
|
||||
public KeyEventHandler OnKeyUp;
|
||||
|
||||
#region INVOKE
|
||||
internal void InvokeVehicleSpawned(SyncedVehicle v) { OnVehicleSpawned?.Invoke(null, v); }
|
||||
internal void InvokeVehicleDeleted(SyncedVehicle v) { OnVehicleDeleted?.Invoke(null, v); }
|
||||
internal void InvokePedSpawned(SyncedPed p) { OnPedSpawned?.Invoke(null, p); }
|
||||
internal void InvokePedDeleted(SyncedPed p) { OnPedDeleted?.Invoke(null, p); }
|
||||
internal void InvokePlayerDied() { OnPlayerDied?.Invoke(); }
|
||||
internal void InvokeTick() { OnTick?.Invoke(); }
|
||||
|
||||
internal void InvokeKeyDown(object s, KeyEventArgs e) { OnKeyDown?.Invoke(s, e); }
|
||||
|
||||
internal void InvokeKeyUp(object s, KeyEventArgs e) { OnKeyUp?.Invoke(s, e); }
|
||||
|
||||
internal void InvokeCustomEventReceived(Packets.CustomEvent p)
|
||||
{
|
||||
@ -169,7 +149,7 @@ namespace RageCoop.Client.Scripting
|
||||
public static API GetInstance()
|
||||
{
|
||||
if (Instance != null) { return Instance; }
|
||||
if (Main.IsPrimaryDomain)
|
||||
if (Util.IsPrimaryDomain)
|
||||
{
|
||||
Instance = new API();
|
||||
}
|
||||
|
@ -9,9 +9,9 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace RageCoop.Client.Scripting
|
||||
{
|
||||
[ScriptAttributes(Author = "RageCoop", NoDefaultInstance = true, SupportURL = "https://github.com/RAGECOOP/RAGECOOP-V")]
|
||||
internal class BaseScript : ClientScript
|
||||
{
|
||||
readonly API API = Main.API;
|
||||
private bool _isHost = false;
|
||||
public override void OnStart()
|
||||
{
|
||||
@ -185,6 +185,7 @@ namespace RageCoop.Client.Scripting
|
||||
prop.Model = (Model)e.Args[1];
|
||||
prop.Position = (Vector3)e.Args[2];
|
||||
prop.Rotation = (Vector3)e.Args[3];
|
||||
Main.Logger.Debug("Prop: "+ prop.Model.Request(1000));
|
||||
prop.Update();
|
||||
}
|
||||
private void NativeCall(CustomEventReceivedArgs e)
|
||||
|
@ -5,8 +5,14 @@ namespace RageCoop.Client.Scripting
|
||||
/// <summary>
|
||||
/// Inherit from this class, constructor will be called automatically, but other scripts might have yet been loaded, you should use <see cref="OnStart"/>. to initiate your script.
|
||||
/// </summary>
|
||||
public abstract class ClientScript
|
||||
[GTA.ScriptAttributes(Author = "RageCoop", NoDefaultInstance = true, SupportURL = "https://github.com/RAGECOOP/RAGECOOP-V")]
|
||||
public abstract class ClientScript : GTA.Script
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="Scripting.API"/> instance to communicate with RageCoop
|
||||
/// </summary>
|
||||
protected static API API => Main.API;
|
||||
|
||||
/// <summary>
|
||||
/// This method would be called from background thread, call <see cref="API.QueueAction(System.Action)"/> to dispatch it to main thread.
|
||||
/// </summary>
|
||||
|
@ -1,99 +1,138 @@
|
||||
using SHVDN;
|
||||
using RageCoop.Core;
|
||||
using Console = GTA.Console;
|
||||
using SHVDN;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Windows.Forms;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace RageCoop.Client.Scripting
|
||||
{
|
||||
internal class ResourceDomain : MarshalByRefObject, IDisposable
|
||||
{
|
||||
public static ResourceDomain Instance;
|
||||
public static ConcurrentDictionary<string, ResourceDomain> LoadedDomains => new ConcurrentDictionary<string, ResourceDomain>(_loadedDomains);
|
||||
static readonly ConcurrentDictionary<string, ResourceDomain> _loadedDomains = new ConcurrentDictionary<string, ResourceDomain>();
|
||||
public static ScriptDomain PrimaryDomain;
|
||||
public static string blah = "blah";
|
||||
public string BaseDirectory => AppDomain.CurrentDomain.BaseDirectory;
|
||||
private ScriptDomain CurrentDomain => ScriptDomain.CurrentDomain;
|
||||
private ResourceDomain(ScriptDomain primary)
|
||||
private ResourceDomain(ScriptDomain primary, string[] apiPaths)
|
||||
{
|
||||
foreach (var apiPath in apiPaths)
|
||||
{
|
||||
try
|
||||
{
|
||||
Assembly.LoadFrom(apiPath);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
PrimaryDomain = primary;
|
||||
|
||||
// Bridge to current ScriptDomain
|
||||
primary.Tick += Tick;
|
||||
primary.KeyEvent += KeyEvent;
|
||||
AppDomain.CurrentDomain.SetData("Primary",false);
|
||||
Main.Console.PrintInfo("Loaded scondary domain: " + AppDomain.CurrentDomain.Id + " " + Main.IsPrimaryDomain);
|
||||
AppDomain.CurrentDomain.SetData("Primary", false);
|
||||
Console.WriteLine("Loaded scondary domain: " + AppDomain.CurrentDomain.Id + " " + Util.IsPrimaryDomain);
|
||||
}
|
||||
public static void Load(string dir = @"RageCoop\Scripts")
|
||||
public static bool IsLoaded(string dir)
|
||||
{
|
||||
if (Instance != null)
|
||||
return _loadedDomains.ContainsKey(Path.GetFullPath(dir).ToLower());
|
||||
}
|
||||
public void SetupScripts()
|
||||
{
|
||||
foreach(var s in ScriptDomain.CurrentDomain.RunningScripts)
|
||||
{
|
||||
throw new Exception("Already loaded");
|
||||
}
|
||||
else if (!Main.IsPrimaryDomain)
|
||||
}
|
||||
public static ResourceDomain Load(string dir = @"RageCoop\Scripts\Debug")
|
||||
{
|
||||
lock (_loadedDomains)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot load in another domain");
|
||||
}
|
||||
ScriptDomain domain = null;
|
||||
try
|
||||
{
|
||||
dir = Path.GetFullPath(dir);
|
||||
|
||||
if (Directory.Exists(dir))
|
||||
dir = Path.GetFullPath(dir).ToLower();
|
||||
if (!Util.IsPrimaryDomain)
|
||||
{
|
||||
Directory.Delete(dir, true);
|
||||
throw new InvalidOperationException("Cannot load in another domain");
|
||||
}
|
||||
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())
|
||||
if (IsLoaded(dir))
|
||||
{
|
||||
var asm = Assembly.Load(a.FullName);
|
||||
if (string.IsNullOrEmpty(asm.Location))
|
||||
throw new Exception("Already loaded");
|
||||
}
|
||||
ScriptDomain domain = null;
|
||||
try
|
||||
{
|
||||
dir = Path.GetFullPath(dir);
|
||||
Directory.CreateDirectory(dir);
|
||||
|
||||
// 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(() =>
|
||||
{
|
||||
continue;
|
||||
}
|
||||
File.Copy(asm.Location, Path.Combine(dir, Path.GetFileName(asm.Location)), true);
|
||||
|
||||
var api = new List<string>();
|
||||
api.Add(typeof(ResourceDomain).Assembly.Location);
|
||||
api.AddRange(typeof(ResourceDomain).Assembly.GetReferencedAssemblies()
|
||||
.Select(x => Assembly.Load(x.FullName).Location)
|
||||
.Where(x => !string.IsNullOrEmpty(x)));
|
||||
|
||||
domain = ScriptDomain.Load(Directory.GetParent(typeof(ScriptDomain).Assembly.Location).FullName, dir);
|
||||
domain.AppDomain.SetData("Console", ScriptDomain.CurrentDomain.AppDomain.GetData("Console"));
|
||||
domain.AppDomain.SetData("RageCoop.Client.API", API.GetInstance());
|
||||
_loadedDomains.TryAdd(dir, (ResourceDomain)domain.AppDomain.CreateInstanceFromAndUnwrap(typeof(ResourceDomain).Assembly.Location, typeof(ResourceDomain).FullName, false, BindingFlags.NonPublic | BindingFlags.Instance, null, new object[] { ScriptDomain.CurrentDomain, api.ToArray() }, null, null));
|
||||
domain.Start();
|
||||
});
|
||||
|
||||
// Wait till next tick
|
||||
GTA.Script.Yield();
|
||||
return _loadedDomains[dir];
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
GTA.UI.Notification.Show(ex.ToString());
|
||||
Main.Logger.Error(ex);
|
||||
if (domain != null)
|
||||
{
|
||||
ScriptDomain.Unload(domain);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
public static void Unload(ResourceDomain domain)
|
||||
{
|
||||
lock (_loadedDomains)
|
||||
{
|
||||
Main.QueueToMainThread(() =>
|
||||
{
|
||||
domain = ScriptDomain.Load(Directory.GetParent(typeof(ScriptDomain).Assembly.Location).FullName, dir);
|
||||
domain.AppDomain.SetData("Console", ScriptDomain.CurrentDomain.AppDomain.GetData("Console"));
|
||||
domain.AppDomain.SetData("RageCoop.Client.API", API.GetInstance());
|
||||
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();
|
||||
domain.Dispose();
|
||||
ScriptDomain.Unload(domain.CurrentDomain);
|
||||
_loadedDomains.TryRemove(domain.BaseDirectory, out _);
|
||||
});
|
||||
|
||||
// Wait till next tick
|
||||
GTA.Script.Yield();
|
||||
}
|
||||
catch (Exception ex)
|
||||
}
|
||||
public static void Unload(string dir)
|
||||
{
|
||||
Unload(_loadedDomains[Path.GetFullPath(dir).ToLower()]);
|
||||
}
|
||||
public static void UnloadAll()
|
||||
{
|
||||
lock (_loadedDomains)
|
||||
{
|
||||
GTA.UI.Notification.Show(ex.ToString());
|
||||
Main.Logger.Error(ex);
|
||||
if (domain != null)
|
||||
foreach (var d in _loadedDomains.Values.ToArray())
|
||||
{
|
||||
ScriptDomain.Unload(domain);
|
||||
Unload(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Unload()
|
||||
{
|
||||
if (Instance == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Instance.Dispose();
|
||||
ScriptDomain.Unload(Instance.CurrentDomain);
|
||||
Instance = null;
|
||||
}
|
||||
|
||||
private void Tick(object sender, EventArgs args)
|
||||
{
|
||||
CurrentDomain.DoTick();
|
||||
|
@ -103,11 +103,7 @@ namespace RageCoop.Client.Scripting
|
||||
public void Unload()
|
||||
{
|
||||
StopAll();
|
||||
if (LoadedResources.Count > 0)
|
||||
{
|
||||
API.QueueAction(() => Util.Reload());
|
||||
}
|
||||
LoadedResources.Clear();
|
||||
ResourceDomain.UnloadAll();
|
||||
}
|
||||
|
||||
private void LoadResource(ZipFile file, string dataFolderRoot)
|
||||
|
@ -70,7 +70,7 @@ namespace RageCoop.Client
|
||||
/// <summary>
|
||||
/// The directory where log and resources downloaded from server will be placed.
|
||||
/// </summary>
|
||||
public string DataDirectory { get; set; } = "Scripts\\RageCoop\\Data";
|
||||
public string DataDirectory { get; set; } = "RageCoop\\Data";
|
||||
|
||||
/// <summary>
|
||||
/// Show the owner name of the entity you're aiming at
|
||||
|
@ -8,7 +8,6 @@ namespace RageCoop.Client
|
||||
{
|
||||
internal static class SyncEvents
|
||||
{
|
||||
|
||||
static readonly Scripting.API API = Main.API;
|
||||
|
||||
#region TRIGGER
|
||||
|
@ -1,7 +1,7 @@
|
||||
using GTA;
|
||||
using Console = GTA.Console;
|
||||
using GTA.Math;
|
||||
using GTA.Native;
|
||||
using mscoree;
|
||||
using RageCoop.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -12,41 +12,14 @@ using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
using System.Xml.Serialization;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
[assembly: InternalsVisibleTo("RageCoop.Client.Installer")]
|
||||
namespace RageCoop.Client
|
||||
{
|
||||
internal static class Util
|
||||
{
|
||||
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 bool IsPrimaryDomain => (AppDomain.CurrentDomain?.GetData("Primary") as bool?) != false;
|
||||
public static SizeF ResolutionMaintainRatio
|
||||
{
|
||||
get
|
||||
@ -141,28 +114,21 @@ namespace RageCoop.Client
|
||||
|
||||
|
||||
#endregion
|
||||
public static string SettingsPath = "Scripts\\RageCoop\\Data\\RageCoop.Client.Settings.xml";
|
||||
public static string SettingsPath = "RageCoop\\Settings.json";
|
||||
public static Settings ReadSettings(string path = null)
|
||||
{
|
||||
path = path ?? SettingsPath;
|
||||
XmlSerializer ser = new XmlSerializer(typeof(Settings));
|
||||
|
||||
Directory.CreateDirectory(Directory.GetParent(path).FullName);
|
||||
Settings settings = null;
|
||||
|
||||
if (File.Exists(path))
|
||||
Settings settings;
|
||||
try
|
||||
{
|
||||
using (FileStream stream = File.OpenRead(path))
|
||||
{
|
||||
settings = (Settings)ser.Deserialize(stream);
|
||||
}
|
||||
settings = JsonConvert.DeserializeObject<Settings>(File.ReadAllText(path));
|
||||
}
|
||||
else
|
||||
catch (Exception ex)
|
||||
{
|
||||
using (FileStream stream = File.OpenWrite(path))
|
||||
{
|
||||
ser.Serialize(stream, settings = new Settings());
|
||||
}
|
||||
Main.Logger?.Error(ex);
|
||||
File.WriteAllText(path, JsonConvert.SerializeObject(settings = new Settings(), Formatting.Indented));
|
||||
}
|
||||
|
||||
return settings;
|
||||
@ -175,11 +141,7 @@ namespace RageCoop.Client
|
||||
settings = settings ?? Main.Settings;
|
||||
Directory.CreateDirectory(Directory.GetParent(path).FullName);
|
||||
|
||||
using (FileStream stream = new FileStream(path, File.Exists(path) ? FileMode.Truncate : FileMode.Create, FileAccess.ReadWrite))
|
||||
{
|
||||
XmlSerializer ser = new XmlSerializer(typeof(Settings));
|
||||
ser.Serialize(stream, settings);
|
||||
}
|
||||
File.WriteAllText(path, JsonConvert.SerializeObject(settings,Formatting.Indented));
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -266,7 +228,6 @@ namespace RageCoop.Client
|
||||
foreach (var l in lines)
|
||||
{
|
||||
var ss = l.Split('=');
|
||||
ss.ForEach(s => s.Replace(" ", ""));
|
||||
if (ss.Length > 0 && ss[0] == "ReloadKey")
|
||||
{
|
||||
reloadKey = ss[1];
|
||||
|
@ -12,71 +12,18 @@ namespace RageCoop.Client
|
||||
/// <summary>
|
||||
/// Don't use it!
|
||||
/// </summary>
|
||||
[ScriptAttributes(Author = "RageCoop", NoDefaultInstance = false, SupportURL = "https://github.com/RAGECOOP/RAGECOOP-V")]
|
||||
internal class WorldThread : Script
|
||||
{
|
||||
public static Script Instance;
|
||||
private static readonly List<Func<bool>> QueuedActions = new List<Func<bool>>();
|
||||
|
||||
public static void Delay(Action a, int time)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
Thread.Sleep(time);
|
||||
QueueAction(a);
|
||||
});
|
||||
}
|
||||
private static void DoQueuedActions()
|
||||
{
|
||||
lock (QueuedActions)
|
||||
{
|
||||
foreach (var action in QueuedActions.ToArray())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (action())
|
||||
{
|
||||
QueuedActions.Remove(action);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Main.Logger.Error(ex);
|
||||
QueuedActions.Remove(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queue an action to be executed on next tick, allowing you to call scripting API from another thread.
|
||||
/// </summary>
|
||||
/// <param name="a"> An action to be executed with a return value indicating whether the action can be removed after execution.</param>
|
||||
internal static void QueueAction(Func<bool> a)
|
||||
{
|
||||
lock (QueuedActions)
|
||||
{
|
||||
QueuedActions.Add(a);
|
||||
}
|
||||
}
|
||||
internal static void QueueAction(Action a)
|
||||
{
|
||||
lock (QueuedActions)
|
||||
{
|
||||
QueuedActions.Add(() => { a(); return true; });
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Clears all queued actions
|
||||
/// </summary>
|
||||
internal static void ClearQueuedActions()
|
||||
{
|
||||
lock (QueuedActions) { QueuedActions.Clear(); }
|
||||
}
|
||||
/// <summary>
|
||||
/// Don't use it!
|
||||
/// </summary>
|
||||
public WorldThread()
|
||||
{
|
||||
if (!Main.IsPrimaryDomain) { return; }
|
||||
Instance = this;
|
||||
if (!Util.IsPrimaryDomain) { Abort(); return; }
|
||||
Tick += OnTick;
|
||||
Aborted += (sender, e) =>
|
||||
{
|
||||
@ -207,5 +154,61 @@ namespace RageCoop.Client
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Delay(Action a, int time)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
Thread.Sleep(time);
|
||||
QueueAction(a);
|
||||
});
|
||||
}
|
||||
internal static void DoQueuedActions()
|
||||
{
|
||||
lock (QueuedActions)
|
||||
{
|
||||
foreach (var action in QueuedActions.ToArray())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (action())
|
||||
{
|
||||
QueuedActions.Remove(action);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Main.Logger.Error(ex);
|
||||
QueuedActions.Remove(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queue an action to be executed on next tick, allowing you to call scripting API from another thread.
|
||||
/// </summary>
|
||||
/// <param name="a"> An action to be executed with a return value indicating whether the action can be removed after execution.</param>
|
||||
internal static void QueueAction(Func<bool> a)
|
||||
{
|
||||
lock (QueuedActions)
|
||||
{
|
||||
QueuedActions.Add(a);
|
||||
}
|
||||
}
|
||||
internal static void QueueAction(Action a)
|
||||
{
|
||||
lock (QueuedActions)
|
||||
{
|
||||
QueuedActions.Add(() => { a(); return true; });
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Clears all queued actions
|
||||
/// </summary>
|
||||
internal static void ClearQueuedActions()
|
||||
{
|
||||
lock (QueuedActions) { QueuedActions.Clear(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Resources;
|
||||
|
||||
// General Information
|
||||
@ -13,7 +15,7 @@ using System.Resources;
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Version information
|
||||
[assembly: AssemblyVersion("1.5.4.41")]
|
||||
[assembly: AssemblyFileVersion("1.5.4.41")]
|
||||
[assembly: NeutralResourcesLanguageAttribute("en-US")]
|
||||
[assembly: AssemblyVersion("1.5.4.42")]
|
||||
[assembly: AssemblyFileVersion("1.5.4.42")]
|
||||
[assembly: NeutralResourcesLanguageAttribute( "en-US" )]
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user