Error handling, bug fixes, new API functions and more added!
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
@ -13,18 +14,16 @@ namespace CoopServer
|
||||
{
|
||||
private static Thread _mainThread;
|
||||
private static bool _hasToStop = false;
|
||||
private static Queue<Action> _actionQueue;
|
||||
private static TaskFactory _factory;
|
||||
private static Queue _actionQueue;
|
||||
private static ServerScript _script;
|
||||
|
||||
public Resource(ServerScript script)
|
||||
{
|
||||
_factory = new();
|
||||
_actionQueue = new();
|
||||
_actionQueue = Queue.Synchronized(new Queue());
|
||||
_mainThread = new(ThreadLoop) { IsBackground = true };
|
||||
_mainThread.Start();
|
||||
|
||||
lock (_actionQueue)
|
||||
lock (_actionQueue.SyncRoot)
|
||||
{
|
||||
_actionQueue.Enqueue(() =>
|
||||
{
|
||||
@ -36,60 +35,88 @@ namespace CoopServer
|
||||
|
||||
private void ThreadLoop()
|
||||
{
|
||||
do
|
||||
while (!_hasToStop)
|
||||
{
|
||||
if (_actionQueue.Count != 0)
|
||||
Queue localQueue;
|
||||
lock (_actionQueue.SyncRoot)
|
||||
{
|
||||
lock (_actionQueue)
|
||||
{
|
||||
_factory.StartNew(() => _actionQueue.Dequeue()?.Invoke());
|
||||
}
|
||||
localQueue = new(_actionQueue);
|
||||
_actionQueue.Clear();
|
||||
}
|
||||
|
||||
while (localQueue.Count > 0)
|
||||
{
|
||||
(localQueue.Dequeue() as Action)?.Invoke();
|
||||
}
|
||||
|
||||
// 16 milliseconds to sleep to reduce CPU usage
|
||||
Thread.Sleep(1000 / 60);
|
||||
} while (_hasToStop);
|
||||
}
|
||||
}
|
||||
|
||||
public bool InvokeModPacketReceived(long from, long target, string mod, byte customID, byte[] bytes)
|
||||
{
|
||||
Task<bool> shutdownTask = new(() => _script.API.InvokeModPacketReceived(from, target, mod, customID, bytes));
|
||||
shutdownTask.Start();
|
||||
shutdownTask.Wait(5000);
|
||||
Task<bool> task = new(() => _script.API.InvokeModPacketReceived(from, target, mod, customID, bytes));
|
||||
task.Start();
|
||||
task.Wait(5000);
|
||||
|
||||
return task.Result;
|
||||
}
|
||||
|
||||
return shutdownTask.Result;
|
||||
public void InvokePlayerHandshake(Client client)
|
||||
{
|
||||
lock (_actionQueue.SyncRoot)
|
||||
{
|
||||
_actionQueue.Enqueue(new Action(() => _script.API.InvokePlayerConnected(client)));
|
||||
}
|
||||
}
|
||||
|
||||
public void InvokePlayerConnected(Client client)
|
||||
{
|
||||
lock (_actionQueue)
|
||||
lock (_actionQueue.SyncRoot)
|
||||
{
|
||||
_actionQueue.Enqueue(() => _script.API.InvokePlayerConnected(client));
|
||||
_actionQueue.Enqueue(new Action(() => _script.API.InvokePlayerConnected(client)));
|
||||
}
|
||||
}
|
||||
|
||||
public void InvokePlayerDisconnected(Client client)
|
||||
{
|
||||
lock (_actionQueue)
|
||||
lock (_actionQueue.SyncRoot)
|
||||
{
|
||||
_actionQueue.Enqueue(() => _script.API.InvokePlayerDisconnected(client));
|
||||
_actionQueue.Enqueue(new Action(() => _script.API.InvokePlayerDisconnected(client)));
|
||||
}
|
||||
}
|
||||
|
||||
public bool InvokeChatMessage(string username, string message)
|
||||
{
|
||||
Task<bool> shutdownTask = new(() => _script.API.InvokeChatMessage(username, message));
|
||||
shutdownTask.Start();
|
||||
shutdownTask.Wait(5000);
|
||||
|
||||
return shutdownTask.Result;
|
||||
Task<bool> task = new(() => _script.API.InvokeChatMessage(username, message));
|
||||
task.Start();
|
||||
task.Wait(5000);
|
||||
|
||||
return task.Result;
|
||||
}
|
||||
|
||||
public void InvokePlayerPositionUpdate(PlayerData playerData)
|
||||
{
|
||||
lock (_actionQueue)
|
||||
lock (_actionQueue.SyncRoot)
|
||||
{
|
||||
_actionQueue.Enqueue(() => _script.API.InvokePlayerPositionUpdate(playerData));
|
||||
_actionQueue.Enqueue(new Action(() => _script.API.InvokePlayerPositionUpdate(playerData)));
|
||||
}
|
||||
}
|
||||
|
||||
public void InvokePlayerUpdate(Client client)
|
||||
{
|
||||
lock (_actionQueue.SyncRoot)
|
||||
{
|
||||
_actionQueue.Enqueue(new Action(() => _script.API.InvokePlayerUpdate(client)));
|
||||
}
|
||||
}
|
||||
|
||||
public void InvokePlayerHealthUpdate(PlayerData playerData)
|
||||
{
|
||||
lock (_actionQueue.SyncRoot)
|
||||
{
|
||||
_actionQueue.Enqueue(new Action(() => _script.API.InvokePlayerHealthUpdate(playerData)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -102,22 +129,31 @@ namespace CoopServer
|
||||
public class API
|
||||
{
|
||||
#region DELEGATES
|
||||
public delegate void EmptyEvent();
|
||||
public delegate void ChatEvent(string username, string message, CancelEventArgs cancel);
|
||||
public delegate void PlayerEvent(Client client);
|
||||
public delegate void ModEvent(long from, long target, string mod, byte customID, byte[] bytes, CancelEventArgs args);
|
||||
#endregion
|
||||
|
||||
#region EVENTS
|
||||
public event EventHandler OnStart;
|
||||
public event EmptyEvent OnStart;
|
||||
public event ChatEvent OnChatMessage;
|
||||
public event PlayerEvent OnPlayerHandshake;
|
||||
public event PlayerEvent OnPlayerConnected;
|
||||
public event PlayerEvent OnPlayerDisconnected;
|
||||
public event PlayerEvent OnPlayerUpdate;
|
||||
public event PlayerEvent OnPlayerHealthUpdate;
|
||||
public event PlayerEvent OnPlayerPositionUpdate;
|
||||
public event ModEvent OnModPacketReceived;
|
||||
|
||||
internal void InvokeStart()
|
||||
{
|
||||
OnStart?.Invoke(this, EventArgs.Empty);
|
||||
OnStart?.Invoke();
|
||||
}
|
||||
|
||||
internal void InvokePlayerHandshake(Client client)
|
||||
{
|
||||
OnPlayerHandshake?.Invoke(client);
|
||||
}
|
||||
|
||||
internal void InvokePlayerConnected(Client client)
|
||||
@ -130,6 +166,16 @@ namespace CoopServer
|
||||
OnPlayerDisconnected?.Invoke(client);
|
||||
}
|
||||
|
||||
internal void InvokePlayerUpdate(Client client)
|
||||
{
|
||||
OnPlayerUpdate?.Invoke(client);
|
||||
}
|
||||
|
||||
internal void InvokePlayerHealthUpdate(PlayerData playerData)
|
||||
{
|
||||
OnPlayerHealthUpdate?.Invoke(Server.Clients.First(x => x.Player.Username == playerData.Username));
|
||||
}
|
||||
|
||||
internal bool InvokeChatMessage(string username, string message)
|
||||
{
|
||||
CancelEventArgs args = new(false);
|
||||
@ -153,41 +199,55 @@ namespace CoopServer
|
||||
#region FUNCTIONS
|
||||
public static void SendModPacketToAll(string mod, byte customID, byte[] bytes)
|
||||
{
|
||||
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
|
||||
new ModPacket()
|
||||
try
|
||||
{
|
||||
ID = -1,
|
||||
Target = 0,
|
||||
Mod = mod,
|
||||
CustomPacketID = customID,
|
||||
Bytes = bytes
|
||||
}.PacketToNetOutGoingMessage(outgoingMessage);
|
||||
Server.MainNetServer.SendMessage(outgoingMessage, Server.MainNetServer.Connections, NetDeliveryMethod.ReliableOrdered, 0);
|
||||
Server.MainNetServer.FlushSendQueue();
|
||||
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
|
||||
new ModPacket()
|
||||
{
|
||||
ID = 0,
|
||||
Target = 0,
|
||||
Mod = mod,
|
||||
CustomPacketID = customID,
|
||||
Bytes = bytes
|
||||
}.PacketToNetOutGoingMessage(outgoingMessage);
|
||||
Server.MainNetServer.SendMessage(outgoingMessage, Server.MainNetServer.Connections, NetDeliveryMethod.ReliableOrdered, 0);
|
||||
Server.MainNetServer.FlushSendQueue();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Error($">> {e.Message} <<>> {e.Source ?? string.Empty} <<>> {e.StackTrace ?? string.Empty} <<");
|
||||
}
|
||||
}
|
||||
|
||||
public static void SendNativeCallToAll(ulong hash, params object[] args)
|
||||
{
|
||||
if (Server.MainNetServer.ConnectionsCount == 0)
|
||||
try
|
||||
{
|
||||
return;
|
||||
if (Server.MainNetServer.ConnectionsCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<NativeArgument> arguments;
|
||||
if ((arguments = Util.ParseNativeArguments(args)) == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NativeCallPacket packet = new()
|
||||
{
|
||||
Hash = hash,
|
||||
Args = arguments
|
||||
};
|
||||
|
||||
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
|
||||
packet.PacketToNetOutGoingMessage(outgoingMessage);
|
||||
Server.MainNetServer.SendMessage(outgoingMessage, Server.MainNetServer.Connections, NetDeliveryMethod.ReliableOrdered, 0);
|
||||
}
|
||||
|
||||
List<NativeArgument> arguments;
|
||||
if ((arguments = Util.ParseNativeArguments(args)) == null)
|
||||
catch (Exception e)
|
||||
{
|
||||
return;
|
||||
Logging.Error($">> {e.Message} <<>> {e.Source ?? string.Empty} <<>> {e.StackTrace ?? string.Empty} <<");
|
||||
}
|
||||
|
||||
NativeCallPacket packet = new()
|
||||
{
|
||||
Hash = hash,
|
||||
Args = arguments
|
||||
};
|
||||
|
||||
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
|
||||
packet.PacketToNetOutGoingMessage(outgoingMessage);
|
||||
Server.MainNetServer.SendMessage(outgoingMessage, Server.MainNetServer.Connections, NetDeliveryMethod.ReliableOrdered, 0);
|
||||
}
|
||||
|
||||
public static List<long> GetAllConnections()
|
||||
@ -211,25 +271,31 @@ namespace CoopServer
|
||||
|
||||
public static Client GetClientByUsername(string username)
|
||||
{
|
||||
return Server.Clients.FirstOrDefault(x => x.Player.Username == username);
|
||||
Client client = Server.Clients.FirstOrDefault(x => x.Player.Username == username);
|
||||
return client.Equals(default(Client)) ? null : client;
|
||||
}
|
||||
|
||||
public static void SendChatMessageToAll(string message, string username = "Server")
|
||||
{
|
||||
if (Server.MainNetServer.ConnectionsCount == 0)
|
||||
try
|
||||
{
|
||||
return;
|
||||
if (Server.MainNetServer.ConnectionsCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
|
||||
new ChatMessagePacket()
|
||||
{
|
||||
Username = username,
|
||||
Message = message
|
||||
}.PacketToNetOutGoingMessage(outgoingMessage);
|
||||
Server.MainNetServer.SendMessage(outgoingMessage, Server.MainNetServer.Connections, NetDeliveryMethod.ReliableOrdered, 0);
|
||||
}
|
||||
|
||||
ChatMessagePacket packet = new()
|
||||
catch (Exception e)
|
||||
{
|
||||
Username = username,
|
||||
Message = message
|
||||
};
|
||||
|
||||
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
|
||||
packet.PacketToNetOutGoingMessage(outgoingMessage);
|
||||
Server.MainNetServer.SendMessage(outgoingMessage, Server.MainNetServer.Connections, NetDeliveryMethod.ReliableOrdered, 0);
|
||||
Logging.Error($">> {e.Message} <<>> {e.Source ?? string.Empty} <<>> {e.StackTrace ?? string.Empty} <<");
|
||||
}
|
||||
}
|
||||
|
||||
public static void RegisterCommand(string name, Action<CommandContext> callback)
|
||||
|
Reference in New Issue
Block a user