Preparing for PluginLoader
This commit is contained in:
parent
f9b9d78b79
commit
58362c2613
@ -1,6 +1,7 @@
|
||||
using System.IO;
|
||||
using RageCoop.Core.Scripting;
|
||||
using ICSharpCode.SharpZipLib.Zip;
|
||||
using System;
|
||||
|
||||
namespace RageCoop.Client.Scripting
|
||||
{
|
||||
@ -15,7 +16,15 @@ namespace RageCoop.Client.Scripting
|
||||
{
|
||||
foreach (var s in d.Scripts)
|
||||
{
|
||||
Main.QueueAction(() => s.OnStart());
|
||||
try
|
||||
{
|
||||
s.OnStart();
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Logger.Error("Error occurred when starting script:"+s.GetType().FullName);
|
||||
Logger?.Error(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -28,7 +37,15 @@ namespace RageCoop.Client.Scripting
|
||||
{
|
||||
foreach (var s in d.Scripts)
|
||||
{
|
||||
Main.QueueAction(() => s.OnStop());
|
||||
try
|
||||
{
|
||||
s.OnStop();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error("Error occurred when stopping script:"+s.GetType().FullName);
|
||||
Logger?.Error(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,10 +13,10 @@ namespace RageCoop.Core
|
||||
private bool _stopping=false;
|
||||
public string Name { get; set; }
|
||||
public bool IsBusy { get;private set; }
|
||||
internal Worker(int maxJobs = Int32.MaxValue,string name="Worker")
|
||||
internal Worker(string name,Logger logger,int maxJobs = Int32.MaxValue)
|
||||
{
|
||||
Name = name;
|
||||
_semaphoreSlim = new SemaphoreSlim(maxJobs);
|
||||
_semaphoreSlim = new SemaphoreSlim(0,maxJobs);
|
||||
_workerThread=new Thread(() =>
|
||||
{
|
||||
while (!_stopping)
|
||||
@ -26,7 +26,15 @@ namespace RageCoop.Core
|
||||
if(Jobs.TryDequeue(out var job))
|
||||
{
|
||||
IsBusy=true;
|
||||
job.Invoke();
|
||||
try
|
||||
{
|
||||
job.Invoke();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error("Error occurred when executing queued job:");
|
||||
logger.Error(ex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -37,7 +45,7 @@ namespace RageCoop.Core
|
||||
});
|
||||
_workerThread.Start();
|
||||
}
|
||||
public void QueueWork(Action work)
|
||||
public void QueueJob(Action work)
|
||||
{
|
||||
Jobs.Enqueue(work);
|
||||
_semaphoreSlim.Release();
|
||||
@ -45,6 +53,7 @@ namespace RageCoop.Core
|
||||
public void Stop()
|
||||
{
|
||||
_stopping=true;
|
||||
QueueJob(() => { });
|
||||
if (_workerThread.IsAlive)
|
||||
{
|
||||
_workerThread.Join();
|
||||
|
@ -46,6 +46,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="McMaster.NETCore.Plugins">
|
||||
<HintPath>..\libs\McMaster.NETCore.Plugins.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>..\libs\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
|
@ -17,6 +17,13 @@ namespace RageCoop.Server.Scripting
|
||||
internal Dictionary<int, List<Action<CustomEventReceivedArgs>>> CustomEventHandlers = new();
|
||||
#endregion
|
||||
public event EventHandler<ChatEventArgs> OnChatMessage;
|
||||
/// <summary>
|
||||
/// Will be invoked from main thread before registered handlers
|
||||
/// </summary>
|
||||
public event EventHandler<OnCommandEventArgs> OnCommandReceived;
|
||||
/// <summary>
|
||||
/// Will be invoked from main thread when a client is attempting to connect, use <see cref="HandshakeEventArgs.Deny(string)"/> to deny the connection request.
|
||||
/// </summary>
|
||||
public event EventHandler<HandshakeEventArgs> OnPlayerHandshake;
|
||||
/// <summary>
|
||||
/// Will be invoked when a player is connected, but this player might not be ready yet(client resources not loaded), using <see cref="OnPlayerReady"/> is recommended.
|
||||
@ -28,10 +35,6 @@ namespace RageCoop.Server.Scripting
|
||||
public event EventHandler<Client> OnPlayerReady;
|
||||
public event EventHandler<Client> OnPlayerDisconnected;
|
||||
/// <summary>
|
||||
/// Will be invoked before registered handlers
|
||||
/// </summary>
|
||||
public event EventHandler<OnCommandEventArgs> OnCommandReceived;
|
||||
/// <summary>
|
||||
/// Invoked everytime a player's main ped has been updated
|
||||
/// </summary>
|
||||
public event EventHandler<Client> OnPlayerUpdate;
|
||||
@ -47,6 +50,41 @@ namespace RageCoop.Server.Scripting
|
||||
OnPlayerUpdate=null;
|
||||
}
|
||||
#region INVOKE
|
||||
internal void InvokePlayerHandshake(HandshakeEventArgs args)
|
||||
{ OnPlayerHandshake?.Invoke(this, args); }
|
||||
internal void InvokeOnCommandReceived(string cname, string[] cargs, Client sender)
|
||||
{
|
||||
var args = new OnCommandEventArgs()
|
||||
{
|
||||
Name=cname,
|
||||
Args=cargs,
|
||||
Sender=sender
|
||||
};
|
||||
OnCommandReceived?.Invoke(this, args);
|
||||
if (args.Cancel)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (Commands.Any(x => x.Key.Name == cmdName))
|
||||
{
|
||||
string[] argsWithoutCmd = cmdArgs.Skip(1).ToArray();
|
||||
|
||||
CommandContext ctx = new()
|
||||
{
|
||||
Client = sender,
|
||||
Args = argsWithoutCmd
|
||||
};
|
||||
|
||||
KeyValuePair<Command, Action<CommandContext>> command = Commands.First(x => x.Key.Name == cmdName);
|
||||
command.Value.Invoke(ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
SendChatMessage("Server", "Command not found!", sender.Connection);
|
||||
}
|
||||
}
|
||||
|
||||
internal void InvokeOnChatMessage(Packets.ChatMessage p, Client sender)
|
||||
{
|
||||
OnChatMessage?.Invoke(this, new ChatEventArgs()
|
||||
@ -61,8 +99,6 @@ namespace RageCoop.Server.Scripting
|
||||
{ OnPlayerReady?.Invoke(this, client); }
|
||||
internal void InvokePlayerDisconnected(Client client)
|
||||
{ OnPlayerDisconnected?.Invoke(this,client); }
|
||||
internal void InvokePlayerHandshake(HandshakeEventArgs args)
|
||||
{ OnPlayerHandshake?.Invoke(this, args); }
|
||||
|
||||
internal void InvokeCustomEventReceived(Packets.CustomEvent p, Client sender)
|
||||
{
|
||||
@ -73,17 +109,6 @@ namespace RageCoop.Server.Scripting
|
||||
handlers.ForEach((x) => { x.Invoke(args); });
|
||||
}
|
||||
}
|
||||
internal bool InvokeOnCommandReceived(string cname, string[] cargs, Client sender)
|
||||
{
|
||||
var args = new OnCommandEventArgs()
|
||||
{
|
||||
Name=cname,
|
||||
Args=cargs,
|
||||
Sender=sender
|
||||
};
|
||||
OnCommandReceived?.Invoke(this, args);
|
||||
return args.Cancel;
|
||||
}
|
||||
internal void InvokePlayerUpdate(Client client)
|
||||
{
|
||||
OnPlayerUpdate?.Invoke(this, client);
|
||||
|
@ -116,7 +116,6 @@ namespace RageCoop.Server.Scripting
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
s.OnStop();
|
||||
}
|
||||
catch(Exception ex)
|
||||
|
@ -26,23 +26,24 @@ namespace RageCoop.Server
|
||||
|
||||
public class Server
|
||||
{
|
||||
private readonly string _compatibleVersion = "V0_5";
|
||||
public API API { get; private set; }
|
||||
internal BaseScript BaseScript { get; set; }=new BaseScript();
|
||||
internal readonly ServerSettings Settings;
|
||||
internal NetServer MainNetServer;
|
||||
private bool _stopping=false;
|
||||
|
||||
internal readonly Dictionary<Command, Action<CommandContext>> Commands = new();
|
||||
internal readonly Dictionary<long,Client> Clients = new();
|
||||
private System.Timers.Timer SendPlayerTimer = new System.Timers.Timer(5000);
|
||||
|
||||
private Dictionary<int,FileTransfer> InProgressFileTransfers=new();
|
||||
private Resources Resources;
|
||||
public API API { get; private set; }
|
||||
internal Logger Logger;
|
||||
private Security Security;
|
||||
private System.Timers.Timer _sendInfoTimer = new System.Timers.Timer(5000);
|
||||
private bool _stopping = false;
|
||||
private Thread _listenerThread;
|
||||
private Thread _announceThread;
|
||||
private Worker _worker;
|
||||
private readonly string _compatibleVersion = "V0_5";
|
||||
public Server(ServerSettings settings,Logger logger=null)
|
||||
{
|
||||
Settings = settings;
|
||||
@ -77,9 +78,10 @@ namespace RageCoop.Server
|
||||
|
||||
MainNetServer = new NetServer(config);
|
||||
MainNetServer.Start();
|
||||
SendPlayerTimer.Elapsed+=(s, e) => { SendPlayerInfos(); };
|
||||
SendPlayerTimer.AutoReset=true;
|
||||
SendPlayerTimer.Enabled=true;
|
||||
_worker=new Worker("ServerWorker");
|
||||
_sendInfoTimer.Elapsed+=(s, e) => { SendPlayerInfos(); };
|
||||
_sendInfoTimer.AutoReset=true;
|
||||
_sendInfoTimer.Enabled=true;
|
||||
Logger?.Info(string.Format("Server listening on {0}:{1}", config.LocalAddress.ToString(), config.Port));
|
||||
if (Settings.AnnounceSelf)
|
||||
{
|
||||
@ -193,12 +195,13 @@ namespace RageCoop.Server
|
||||
public void Stop()
|
||||
{
|
||||
_stopping = true;
|
||||
SendPlayerTimer.Stop();
|
||||
SendPlayerTimer.Enabled=false;
|
||||
SendPlayerTimer.Dispose();
|
||||
_sendInfoTimer.Stop();
|
||||
_sendInfoTimer.Enabled=false;
|
||||
_sendInfoTimer.Dispose();
|
||||
Logger?.Flush();
|
||||
_listenerThread?.Join();
|
||||
_announceThread?.Join();
|
||||
_worker.Dispose();
|
||||
}
|
||||
private void Listen()
|
||||
{
|
||||
@ -273,10 +276,10 @@ namespace RageCoop.Server
|
||||
{
|
||||
SendPlayerConnectPacket(sender);
|
||||
Resources.SendTo(sender);
|
||||
API.Events.InvokePlayerConnected(sender);
|
||||
_worker.QueueJob(()=> API.Events.InvokePlayerConnected(sender));
|
||||
if (sender.IsReady)
|
||||
{
|
||||
API.Events.InvokePlayerReady(sender);
|
||||
_worker.QueueJob(()=>API.Events.InvokePlayerReady(sender));
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -356,7 +359,7 @@ namespace RageCoop.Server
|
||||
Packets.ChatMessage packet = new();
|
||||
packet.Unpack(data);
|
||||
|
||||
API.Events.InvokeOnChatMessage(packet, sender);
|
||||
_worker.QueueJob(()=>API.Events.InvokeOnChatMessage(packet, sender));
|
||||
SendChatMessage(packet,sender);
|
||||
}
|
||||
break;
|
||||
@ -364,7 +367,7 @@ namespace RageCoop.Server
|
||||
{
|
||||
Packets.CustomEvent packet = new Packets.CustomEvent();
|
||||
packet.Unpack(data);
|
||||
API.Events.InvokeCustomEventReceived(packet, sender);
|
||||
_worker.QueueJob(() => API.Events.InvokeCustomEventReceived(packet, sender));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -381,7 +384,7 @@ namespace RageCoop.Server
|
||||
if (toRemove.Name=="Resources.zip")
|
||||
{
|
||||
sender.IsReady=true;
|
||||
API.Events.InvokePlayerReady(sender);
|
||||
_worker.QueueJob(() => API.Events.InvokePlayerReady(sender));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -632,7 +635,7 @@ namespace RageCoop.Server
|
||||
}.Pack(outgoingMessage);
|
||||
MainNetServer.SendMessage(outgoingMessage,cons , NetDeliveryMethod.ReliableOrdered, 0);
|
||||
}
|
||||
API.Events.InvokePlayerDisconnected(localClient);
|
||||
_worker.QueueJob(() => API.Events.InvokePlayerDisconnected(localClient));
|
||||
Logger?.Info($"Player {localClient.Username} disconnected! ID:{localClient.ID}");
|
||||
Clients.Remove(localClient.NetID);
|
||||
Security.RemoveConnection(localClient.Connection.RemoteEndPoint);
|
||||
@ -675,8 +678,8 @@ namespace RageCoop.Server
|
||||
if (isPlayer)
|
||||
{
|
||||
client.Player.Position=packet.Position;
|
||||
client.Player.Health=packet.Health ;
|
||||
API.Events.InvokePlayerUpdate(client);
|
||||
client.Player.Health=packet.Health ;
|
||||
_worker.QueueJob(() => API.Events.InvokePlayerUpdate(client));
|
||||
}
|
||||
|
||||
foreach (var c in Clients.Values)
|
||||
@ -746,38 +749,9 @@ namespace RageCoop.Server
|
||||
if (packet.Message.StartsWith('/'))
|
||||
{
|
||||
string[] cmdArgs = packet.Message.Split(" ");
|
||||
string cmdName = cmdArgs[0].Remove(0, 1);
|
||||
|
||||
if (API.Events.InvokeOnCommandReceived(cmdName, cmdArgs, sender))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (Commands.Any(x => x.Key.Name == cmdName))
|
||||
{
|
||||
string[] argsWithoutCmd = cmdArgs.Skip(1).ToArray();
|
||||
|
||||
CommandContext ctx = new()
|
||||
{
|
||||
Client = Clients.Values.Where(x => x.Username == packet.Username).FirstOrDefault(),
|
||||
Args = argsWithoutCmd
|
||||
};
|
||||
|
||||
KeyValuePair<Command, Action<CommandContext>> command = Commands.First(x => x.Key.Name == cmdName);
|
||||
|
||||
if (command.Key.Usage != null && command.Key.ArgsLength != argsWithoutCmd.Length)
|
||||
{
|
||||
|
||||
SendChatMessage("Server", command.Key.Usage,sender.Connection);
|
||||
return;
|
||||
}
|
||||
|
||||
command.Value.Invoke(ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
SendChatMessage("Server", "Command not found!", sender.Connection);
|
||||
}
|
||||
string cmdName = cmdArgs[0].Remove(0, 1);
|
||||
_worker.QueueJob(()=>API.Events.InvokeOnCommandReceived(cmdName, cmdArgs, sender));
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
BIN
libs/McMaster.NETCore.Plugins.dll
Normal file
BIN
libs/McMaster.NETCore.Plugins.dll
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user