Queue action in WorldThread
This commit is contained in:
@ -42,7 +42,6 @@ namespace RageCoop.Client
|
||||
internal static Vector3 PlayerPosition;
|
||||
internal static 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;
|
||||
internal static SHVDN.Console Console => AppDomain.CurrentDomain.GetData("Console") as SHVDN.Console;
|
||||
/// <summary>
|
||||
@ -179,7 +178,6 @@ namespace RageCoop.Client
|
||||
#endif
|
||||
|
||||
|
||||
DoQueuedActions();
|
||||
if (!Networking.IsOnServer)
|
||||
{
|
||||
return;
|
||||
@ -349,7 +347,7 @@ namespace RageCoop.Client
|
||||
{
|
||||
Voice.Init();
|
||||
}
|
||||
QueueAction(() =>
|
||||
API.QueueAction(() =>
|
||||
{
|
||||
WorldThread.Traffic(!Settings.DisableTraffic);
|
||||
Function.Call(Hash.SET_ENABLE_VEHICLE_SLIPSTREAMING, true);
|
||||
@ -365,7 +363,7 @@ namespace RageCoop.Client
|
||||
|
||||
|
||||
Logger.Info($">> Disconnected << reason: {reason}");
|
||||
QueueAction(() =>
|
||||
API.QueueAction(() =>
|
||||
{
|
||||
if (MainChat.Focused)
|
||||
{
|
||||
@ -385,62 +383,7 @@ namespace RageCoop.Client
|
||||
Voice.ClearAll();
|
||||
Resources.Unload();
|
||||
}
|
||||
private static void DoQueuedActions()
|
||||
{
|
||||
lock (QueuedActions)
|
||||
{
|
||||
foreach (var action in QueuedActions.ToArray())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (action())
|
||||
{
|
||||
QueuedActions.Remove(action);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
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(); }
|
||||
}
|
||||
|
||||
public static void Delay(Action a, int time)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
Thread.Sleep(time);
|
||||
QueueAction(a);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
using GTA.UI;
|
||||
using LemonUI.Menus;
|
||||
using Newtonsoft.Json;
|
||||
using RageCoop.Client.Scripting;
|
||||
using RageCoop.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -16,6 +17,7 @@ namespace RageCoop.Client.Menus
|
||||
/// </summary>
|
||||
internal static class ServersMenu
|
||||
{
|
||||
static API API = Main.API;
|
||||
private static Thread GetServersThread;
|
||||
internal static NativeMenu Menu = new NativeMenu("RAGECOOP", "Servers", "Go to the server list")
|
||||
{
|
||||
@ -60,7 +62,7 @@ namespace RageCoop.Client.Menus
|
||||
serverList = JsonConvert.DeserializeObject<List<ServerInfo>>(DownloadString(realUrl));
|
||||
|
||||
// Need to be processed in main thread
|
||||
Main.QueueAction(() =>
|
||||
API.QueueAction(() =>
|
||||
{
|
||||
if (serverList == null)
|
||||
{
|
||||
@ -127,7 +129,7 @@ namespace RageCoop.Client.Menus
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Main.QueueAction(() =>
|
||||
API.QueueAction(() =>
|
||||
{
|
||||
ResultItem.Title = "Download failed!";
|
||||
ResultItem.Description = ex.Message;
|
||||
|
@ -1,5 +1,6 @@
|
||||
using ICSharpCode.SharpZipLib.Zip;
|
||||
using LemonUI.Menus;
|
||||
using RageCoop.Client.Scripting;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
@ -10,6 +11,7 @@ namespace RageCoop.Client.Menus
|
||||
{
|
||||
internal class UpdateMenu
|
||||
{
|
||||
static readonly API API = Main.API;
|
||||
public static bool IsUpdating { get; private set; } = false;
|
||||
private static readonly NativeItem _updatingItem = new NativeItem("Updating...");
|
||||
private static readonly NativeItem _downloadItem = new NativeItem("Download", "Download and update to latest nightly");
|
||||
@ -45,7 +47,7 @@ namespace RageCoop.Client.Menus
|
||||
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls13 | SecurityProtocolType.Tls12;
|
||||
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
|
||||
|
||||
client.DownloadProgressChanged += (s, e1) => { Main.QueueAction(() => { _updatingItem.AltTitle = $"{e1.ProgressPercentage}%"; }); };
|
||||
client.DownloadProgressChanged += (s, e1) => { API.QueueAction(() => { _updatingItem.AltTitle = $"{e1.ProgressPercentage}%"; }); };
|
||||
client.DownloadFileCompleted += (s, e2) => { Install(); };
|
||||
client.DownloadFileAsync(new Uri("https://github.com/RAGECOOP/RAGECOOP-V/releases/download/nightly/RageCoop.Client.zip"), _downloadPath);
|
||||
}
|
||||
@ -60,7 +62,7 @@ namespace RageCoop.Client.Menus
|
||||
{
|
||||
try
|
||||
{
|
||||
Main.QueueAction(() =>
|
||||
API.QueueAction(() =>
|
||||
{
|
||||
_updatingItem.AltTitle = "Installing...";
|
||||
});
|
||||
@ -73,7 +75,7 @@ namespace RageCoop.Client.Menus
|
||||
new FastZip().ExtractZip(_downloadPath, "Scripts", FastZip.Overwrite.Always, null, null, null, true);
|
||||
try { File.Delete(_downloadPath); } catch { }
|
||||
try { File.Delete(Path.Combine("Scripts", "RageCoop.Client.Installer.exe")); } catch { }
|
||||
Main.QueueAction(() =>
|
||||
API.QueueAction(() =>
|
||||
{
|
||||
Util.Reload();
|
||||
IsUpdating = false;
|
||||
|
@ -101,7 +101,7 @@ namespace RageCoop.Client
|
||||
try { ProcessMessage(m); }
|
||||
catch (Exception ex) { Main.Logger.Error(ex); }
|
||||
};
|
||||
Main.QueueAction(() => { Notification.Show($"~y~Trying to connect..."); });
|
||||
API.QueueAction(() => { Notification.Show($"~y~Trying to connect..."); });
|
||||
Menus.CoopMenu._serverConnectItem.Enabled = false;
|
||||
Security.Regen();
|
||||
if (publicKey == null)
|
||||
@ -136,7 +136,7 @@ namespace RageCoop.Client
|
||||
catch (Exception ex)
|
||||
{
|
||||
Main.Logger.Error("Cannot connect to server: ", ex);
|
||||
Main.QueueAction(() => Notification.Show("Cannot connect to server: " + ex.Message));
|
||||
API.QueueAction(() => Notification.Show("Cannot connect to server: " + ex.Message));
|
||||
}
|
||||
IsConnecting = false;
|
||||
});
|
||||
@ -155,7 +155,7 @@ namespace RageCoop.Client
|
||||
PlayerList.SetPlayer(packet.PedID, packet.Username);
|
||||
|
||||
Main.Logger.Debug($"player connected:{p.Username}");
|
||||
Main.QueueAction(() =>
|
||||
API.QueueAction(() =>
|
||||
GTA.UI.Notification.Show($"~h~{p.Username}~h~ connected."));
|
||||
}
|
||||
private static void PlayerDisconnect(Packets.PlayerDisconnect packet)
|
||||
@ -163,7 +163,7 @@ namespace RageCoop.Client
|
||||
var player = PlayerList.GetPlayer(packet.PedID);
|
||||
if (player == null) { return; }
|
||||
PlayerList.RemovePlayer(packet.PedID);
|
||||
Main.QueueAction(() =>
|
||||
API.QueueAction(() =>
|
||||
{
|
||||
EntityPool.RemoveAllFromPlayer(packet.PedID);
|
||||
GTA.UI.Notification.Show($"~h~{player.Username}~h~ left.");
|
||||
|
@ -149,7 +149,7 @@ namespace RageCoop.Client
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Main.QueueAction(() =>
|
||||
API.QueueAction(() =>
|
||||
{
|
||||
GTA.UI.Notification.Show($"~r~~h~Packet Error {ex.Message}");
|
||||
return true;
|
||||
@ -236,7 +236,7 @@ namespace RageCoop.Client
|
||||
Packets.ChatMessage packet = new Packets.ChatMessage((b) => Security.Decrypt(b));
|
||||
packet.Deserialize(msg);
|
||||
|
||||
Main.QueueAction(() => { Main.MainChat.AddMessage(packet.Username, packet.Message); return true; });
|
||||
API.QueueAction(() => { Main.MainChat.AddMessage(packet.Username, packet.Message); return true; });
|
||||
}
|
||||
break;
|
||||
|
||||
@ -264,7 +264,7 @@ namespace RageCoop.Client
|
||||
if (packet.Flags.HasEventFlag(Core.Scripting.CustomEventFlags.Queued))
|
||||
{
|
||||
recycle = false;
|
||||
Main.QueueAction(() =>
|
||||
API.QueueAction(() =>
|
||||
{
|
||||
API.Events.InvokeCustomEventReceived(packet);
|
||||
Peer.Recycle(msg);
|
||||
@ -290,7 +290,7 @@ namespace RageCoop.Client
|
||||
{
|
||||
recycle = false;
|
||||
// Dispatch to script thread
|
||||
Main.QueueAction(() => { SyncEvents.HandleEvent(packetType, msg); Peer.Recycle(msg); return true; });
|
||||
API.QueueAction(() => { SyncEvents.HandleEvent(packetType, msg); Peer.Recycle(msg); return true; });
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ namespace RageCoop.Client
|
||||
p._latencyToServer = packet.Latency;
|
||||
p.Position = packet.Position;
|
||||
p.IsHost = packet.IsHost;
|
||||
Main.QueueAction(() =>
|
||||
API.QueueAction(() =>
|
||||
{
|
||||
if (p.FakeBlip?.Exists() != true)
|
||||
{
|
||||
@ -126,7 +126,7 @@ namespace RageCoop.Client
|
||||
if (Players.TryGetValue(id, out var player))
|
||||
{
|
||||
Players.Remove(id);
|
||||
Main.QueueAction(() => player.FakeBlip?.Delete());
|
||||
API.QueueAction(() => player.FakeBlip?.Delete());
|
||||
}
|
||||
}
|
||||
public static void Cleanup()
|
||||
|
@ -16,7 +16,7 @@ using System.Resources;
|
||||
|
||||
|
||||
// Version informationr(
|
||||
[assembly: AssemblyVersion("1.5.4.141")]
|
||||
[assembly: AssemblyFileVersion("1.5.4.141")]
|
||||
[assembly: AssemblyVersion("1.5.4.146")]
|
||||
[assembly: AssemblyFileVersion("1.5.4.146")]
|
||||
[assembly: NeutralResourcesLanguageAttribute( "en-US" )]
|
||||
|
||||
|
@ -292,7 +292,7 @@ namespace RageCoop.Client.Scripting
|
||||
/// <param name="a"></param>
|
||||
public void QueueAction(Action a)
|
||||
{
|
||||
Main.QueueAction(a);
|
||||
WorldThread.QueueAction(a);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -301,7 +301,7 @@ namespace RageCoop.Client.Scripting
|
||||
/// <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 void QueueAction(Func<bool> a)
|
||||
{
|
||||
Main.QueueAction(a);
|
||||
WorldThread.QueueAction(a);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -27,6 +27,7 @@ namespace RageCoop.Client
|
||||
{
|
||||
|
||||
if (!NeedUpdate) { return; }
|
||||
if (!Model.IsLoaded) { Model.Request(); return; }
|
||||
if (MainProp == null || !MainProp.Exists())
|
||||
{
|
||||
MainProp = World.CreateProp(Model, Position, Rotation, false, false);
|
||||
|
@ -113,7 +113,7 @@ namespace RageCoop.Client
|
||||
{
|
||||
if (MainVehicle.IsDead)
|
||||
{
|
||||
Main.Delay(() =>
|
||||
WorldThread.Delay(() =>
|
||||
{
|
||||
if (MainVehicle.IsDead && !IsDead)
|
||||
{
|
||||
|
@ -8,6 +8,9 @@ namespace RageCoop.Client
|
||||
{
|
||||
internal static class SyncEvents
|
||||
{
|
||||
|
||||
static readonly Scripting.API API = Main.API;
|
||||
|
||||
#region TRIGGER
|
||||
public static void TriggerPedKilled(SyncedPed victim)
|
||||
{
|
||||
@ -256,7 +259,7 @@ namespace RageCoop.Client
|
||||
|
||||
if (!getBulletImpact())
|
||||
{
|
||||
Main.QueueAction(getBulletImpact);
|
||||
API.QueueAction(getBulletImpact);
|
||||
}
|
||||
}
|
||||
else if (subject.VehicleWeapon == VehicleWeaponHash.Tank && subject.LastWeaponImpactPosition != default)
|
||||
|
@ -1,7 +1,11 @@
|
||||
using GTA;
|
||||
using GTA.Native;
|
||||
using RageCoop.Client.Scripting;
|
||||
using RageCoop.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
|
||||
namespace RageCoop.Client
|
||||
{
|
||||
@ -10,7 +14,63 @@ namespace RageCoop.Client
|
||||
/// </summary>
|
||||
internal class WorldThread : Script
|
||||
{
|
||||
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>
|
||||
@ -27,6 +87,7 @@ namespace RageCoop.Client
|
||||
private static bool _trafficEnabled;
|
||||
private void OnTick(object sender, EventArgs e)
|
||||
{
|
||||
DoQueuedActions();
|
||||
if (Game.IsLoading || !Networking.IsOnServer)
|
||||
{
|
||||
return;
|
||||
|
Reference in New Issue
Block a user