Merge pull request #31 from EntenKoeniq/main
Added multithreading and SendModPacket from the server
This commit is contained in:
commit
490ec02a3c
@ -83,5 +83,22 @@ namespace CoopServer
|
||||
packet.PacketToNetOutGoingMessage(outgoingMessage);
|
||||
Server.MainNetServer.SendMessage(outgoingMessage, userConnection, NetDeliveryMethod.ReliableOrdered, 0);
|
||||
}
|
||||
|
||||
public void SendModPacket(string mod, byte customID, byte[] bytes)
|
||||
{
|
||||
NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == ID);
|
||||
|
||||
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
|
||||
new ModPacket()
|
||||
{
|
||||
ID = -1,
|
||||
Target = 0,
|
||||
Mod = mod,
|
||||
CustomPacketID = customID,
|
||||
Bytes = bytes
|
||||
}.PacketToNetOutGoingMessage(outgoingMessage);
|
||||
Server.MainNetServer.SendMessage(outgoingMessage, userConnection, NetDeliveryMethod.ReliableOrdered, 0);
|
||||
Server.MainNetServer.FlushSendQueue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,9 +18,9 @@
|
||||
LastPosition = CurrentPosition;
|
||||
CurrentPosition = value;
|
||||
|
||||
if (Server.GameMode != null && !LVector3.Equals(CurrentPosition, LastPosition))
|
||||
if (Server.MainResource != null && !LVector3.Equals(CurrentPosition, LastPosition))
|
||||
{
|
||||
Server.GameMode.API.InvokePlayerPositionUpdate(this);
|
||||
Server.MainResource.InvokePlayerPositionUpdate(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ namespace CoopServer
|
||||
|
||||
public static NetServer MainNetServer;
|
||||
|
||||
public static ServerScript GameMode;
|
||||
public static Resource MainResource;
|
||||
public static Dictionary<Command, Action<CommandContext>> Commands;
|
||||
|
||||
public static readonly List<Client> Clients = new();
|
||||
@ -62,13 +62,13 @@ namespace CoopServer
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(MainSettings.GameMode))
|
||||
if (!string.IsNullOrEmpty(MainSettings.Resource))
|
||||
{
|
||||
try
|
||||
{
|
||||
Logging.Info("Loading gamemode...");
|
||||
Logging.Info("Loading resource...");
|
||||
|
||||
Assembly asm = Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory + "gamemodes" + Path.DirectorySeparatorChar + MainSettings.GameMode + ".dll");
|
||||
Assembly asm = Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory + "resources" + Path.DirectorySeparatorChar + MainSettings.Resource + ".dll");
|
||||
Type[] types = asm.GetExportedTypes();
|
||||
IEnumerable<Type> validTypes = types.Where(t => !t.IsInterface && !t.IsAbstract).Where(t => typeof(ServerScript).IsAssignableFrom(t));
|
||||
Type[] enumerable = validTypes as Type[] ?? validTypes.ToArray();
|
||||
@ -81,14 +81,13 @@ namespace CoopServer
|
||||
{
|
||||
Commands = new();
|
||||
|
||||
GameMode = Activator.CreateInstance(enumerable.ToArray()[0]) as ServerScript;
|
||||
if (GameMode == null)
|
||||
if (Activator.CreateInstance(enumerable.ToArray()[0]) is ServerScript script)
|
||||
{
|
||||
Logging.Warning("Could not create gamemode: it is null.");
|
||||
MainResource = new(script);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMode.API.InvokeStart();
|
||||
Logging.Warning("Could not create resource: it is null.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -107,9 +106,6 @@ namespace CoopServer
|
||||
|
||||
while (true)
|
||||
{
|
||||
// 16 milliseconds to sleep to reduce CPU usage
|
||||
Thread.Sleep(1000 / 60);
|
||||
|
||||
NetIncomingMessage message;
|
||||
|
||||
while ((message = MainNetServer.ReadMessage()) != null)
|
||||
@ -289,9 +285,9 @@ namespace CoopServer
|
||||
packet.NetIncomingMessageToPacket(message);
|
||||
|
||||
ModPacket modPacket = (ModPacket)packet;
|
||||
if (GameMode != null)
|
||||
if (MainResource != null)
|
||||
{
|
||||
if (GameMode.API.InvokeModPacketReceived(modPacket.ID, modPacket.Target, modPacket.Mod, modPacket.CustomPacketID, modPacket.Bytes))
|
||||
if (MainResource.InvokeModPacketReceived(modPacket.ID, modPacket.Target, modPacket.Mod, modPacket.CustomPacketID, modPacket.Bytes))
|
||||
{
|
||||
break;
|
||||
}
|
||||
@ -357,6 +353,9 @@ namespace CoopServer
|
||||
|
||||
MainNetServer.Recycle(message);
|
||||
}
|
||||
|
||||
// 16 milliseconds to sleep to reduce CPU usage
|
||||
Thread.Sleep(1000 / 60);
|
||||
}
|
||||
}
|
||||
|
||||
@ -458,9 +457,9 @@ namespace CoopServer
|
||||
SendChatMessage(new ChatMessagePacket() { Username = "Server", Message = MainSettings.WelcomeMessage }, new List<NetConnection>() { local });
|
||||
}
|
||||
|
||||
if (GameMode != null)
|
||||
if (MainResource != null)
|
||||
{
|
||||
GameMode.API.InvokePlayerConnected(Clients.Find(x => x.ID == packet.ID));
|
||||
MainResource.InvokePlayerConnected(Clients.Find(x => x.ID == packet.ID));
|
||||
}
|
||||
|
||||
List<NetConnection> clients;
|
||||
@ -502,9 +501,9 @@ namespace CoopServer
|
||||
// Send all players a message that someone has left the server
|
||||
private static void SendPlayerDisconnectPacket(PlayerDisconnectPacket packet)
|
||||
{
|
||||
if (GameMode != null)
|
||||
if (MainResource != null)
|
||||
{
|
||||
GameMode.API.InvokePlayerDisconnected(Clients.Find(x => x.ID == packet.ID));
|
||||
MainResource.InvokePlayerDisconnected(Clients.Find(x => x.ID == packet.ID));
|
||||
}
|
||||
|
||||
List<NetConnection> clients;
|
||||
@ -643,7 +642,7 @@ namespace CoopServer
|
||||
{
|
||||
NetOutgoingMessage outgoingMessage;
|
||||
|
||||
if (GameMode != null)
|
||||
if (MainResource != null)
|
||||
{
|
||||
if (packet.Message.StartsWith("/"))
|
||||
{
|
||||
@ -679,7 +678,8 @@ namespace CoopServer
|
||||
|
||||
return;
|
||||
}
|
||||
else if (GameMode.API.InvokeChatMessage(packet.Username, packet.Message))
|
||||
|
||||
if (MainResource.InvokeChatMessage(packet.Username, packet.Message))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -2,11 +2,98 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Lidgren.Network;
|
||||
|
||||
namespace CoopServer
|
||||
{
|
||||
internal class Resource
|
||||
{
|
||||
private static Thread _mainThread;
|
||||
private static bool _hasToStop = false;
|
||||
private static Queue<Action> _actionQueue;
|
||||
private static TaskFactory _factory;
|
||||
private static ServerScript _script;
|
||||
|
||||
public Resource(ServerScript script)
|
||||
{
|
||||
_factory = new();
|
||||
_actionQueue = new();
|
||||
_mainThread = new(ThreadLoop) { IsBackground = true };
|
||||
_mainThread.Start();
|
||||
|
||||
lock (_actionQueue)
|
||||
{
|
||||
_actionQueue.Enqueue(() =>
|
||||
{
|
||||
_script = script;
|
||||
_script.API.InvokeStart();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void ThreadLoop()
|
||||
{
|
||||
while (_hasToStop)
|
||||
{
|
||||
if (_actionQueue.Count != 0)
|
||||
{
|
||||
lock (_actionQueue)
|
||||
{
|
||||
_factory.StartNew(() => _actionQueue.Dequeue()?.Invoke());
|
||||
}
|
||||
}
|
||||
|
||||
// 16 milliseconds to sleep to reduce CPU usage
|
||||
Thread.Sleep(1000 / 60);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return shutdownTask.Result;
|
||||
}
|
||||
|
||||
public void InvokePlayerConnected(Client client)
|
||||
{
|
||||
lock (_actionQueue)
|
||||
{
|
||||
_actionQueue.Enqueue(() => _script.API.InvokePlayerConnected(client));
|
||||
}
|
||||
}
|
||||
|
||||
public void InvokePlayerDisconnected(Client client)
|
||||
{
|
||||
lock (_actionQueue)
|
||||
{
|
||||
_actionQueue.Enqueue(() => _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;
|
||||
}
|
||||
|
||||
public void InvokePlayerPositionUpdate(PlayerData playerData)
|
||||
{
|
||||
lock (_actionQueue)
|
||||
{
|
||||
_actionQueue.Enqueue(() => _script.API.InvokePlayerPositionUpdate(playerData));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class ServerScript
|
||||
{
|
||||
public API API { get; } = new();
|
||||
@ -64,6 +151,21 @@ namespace CoopServer
|
||||
#endregion
|
||||
|
||||
#region FUNCTIONS
|
||||
public static void SendModPacketToAll(string mod, byte customID, byte[] bytes)
|
||||
{
|
||||
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
|
||||
new ModPacket()
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
public static void SendNativeCallToAll(ulong hash, params object[] args)
|
||||
{
|
||||
if (Server.MainNetServer.ConnectionsCount == 0)
|
||||
|
@ -6,7 +6,7 @@
|
||||
public int MaxPlayers { get; set; } = 16;
|
||||
public string ServerName { get; set; } = "GTACoop:R server";
|
||||
public string WelcomeMessage { get; set; } = "Welcome on this server :)";
|
||||
public string GameMode { get; set; } = "";
|
||||
public string Resource { get; set; } = "";
|
||||
public bool Allowlist { get; set; } = false;
|
||||
public bool NpcsAllowed { get; set; } = true;
|
||||
public bool ModsAllowed { get; set; } = false;
|
||||
|
Loading…
x
Reference in New Issue
Block a user