Change settings and data directory

This commit is contained in:
sardelka9515 2022-10-09 22:07:52 +08:00
parent 1606d25fed
commit 617dbc9812
20 changed files with 239 additions and 231 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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}";
}
}
}
}

View File

@ -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;
}
}

View File

@ -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)

View File

@ -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" )]

View File

@ -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">

View File

@ -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();
}

View File

@ -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)

View File

@ -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>

View File

@ -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();

View File

@ -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)

View File

@ -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

View File

@ -8,7 +8,6 @@ namespace RageCoop.Client
{
internal static class SyncEvents
{
static readonly Scripting.API API = Main.API;
#region TRIGGER

View File

@ -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];

View File

@ -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(); }
}
}
}

View File

@ -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.