Error handling, bug fixes, new API functions and more added!

This commit is contained in:
EntenKoeniq
2021-11-25 16:32:04 +01:00
parent ed46155138
commit 5c7e7f45a0
7 changed files with 411 additions and 185 deletions

View File

@ -442,7 +442,7 @@ namespace CoopClient
if (VehicleSteeringAngle != MainVehicle.SteeringAngle)
{
MainVehicle.Handle.CustomSteeringAngle((float)(Math.PI / 180) * VehicleSteeringAngle);
MainVehicle.CustomSteeringAngle((float)(Math.PI / 180) * VehicleSteeringAngle);
}
// Good enough for now, but we need to create a better sync

View File

@ -25,8 +25,11 @@ namespace FirstGameMode
RunningSinceTimer.Start();
RunningSinceTimer.Elapsed += new ElapsedEventHandler((sender, e) => RunningSince += 1);
API.OnStart += OnResourceStarted;
API.OnPlayerConnected += OnPlayerConnected;
API.OnPlayerDisconnected += OnPlayerDisconnected;
API.OnPlayerHealthUpdate += OnPlayerHealthUpdate;
API.OnPlayerPositionUpdate += OnPlayerPositionUpdate;
API.OnChatMessage += OnChatMessage;
API.OnModPacketReceived += OnModPacketReceived;
@ -34,7 +37,25 @@ namespace FirstGameMode
API.RegisterCommands<Commands>();
}
private void OnModPacketReceived(long from, long target, string mod, byte customID, byte[] bytes, CancelEventArgs args)
public void OnResourceStarted()
{
Logging.Info("Resource started successfully!");
}
public void OnPlayerHealthUpdate(Client client)
{
if (client.Player.Health == 0)
{
Logging.Warning($"Player {client.Player.Username} has died!");
}
}
public void OnPlayerPositionUpdate(Client client)
{
// Code...
}
public void OnModPacketReceived(long from, long target, string mod, byte customID, byte[] bytes, CancelEventArgs args)
{
if (mod != "FirstScript" || customID != 1)
{
@ -56,22 +77,22 @@ namespace FirstGameMode
targetClient.SendNativeCall(0x47C3B5848C3E45D8, setPlayerTime.Hours, setPlayerTime.Minutes, setPlayerTime.Seconds);
}
public static void RunningCommand(CommandContext ctx)
public void RunningCommand(CommandContext ctx)
{
ctx.Client.SendChatMessage("Server has been running for: " + RunningSince + " seconds!");
ctx.Client.SendChatMessage($"Server has been running for: {RunningSince} seconds!");
}
public static void OnPlayerConnected(Client client)
public void OnPlayerConnected(Client client)
{
API.SendChatMessageToAll("Player " + client.Player.Username + " connected!");
client.SendChatMessage($"Welcome {client.Player.Username}!");
}
public static void OnPlayerDisconnected(Client client)
public void OnPlayerDisconnected(Client client)
{
API.SendChatMessageToAll("Player " + client.Player.Username + " disconnected!");
API.SendChatMessageToAll($"Player {client.Player.Username} disconnected!");
}
public static void OnChatMessage(string username, string message, CancelEventArgs e)
public void OnChatMessage(string username, string message, CancelEventArgs e)
{
e.Cancel = true;

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using Lidgren.Network;
@ -43,14 +44,21 @@ namespace CoopServer
}
#endregion
#region FUNCTIONS
public void Kick(string[] reason)
{
Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == ID).Disconnect(string.Join(" ", reason));
Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == ID)?.Disconnect(string.Join(" ", reason));
}
public void SendChatMessage(string message, string from = "Server")
{
try
{
NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == ID);
if (userConnection == null)
{
return;
}
ChatMessagePacket packet = new()
{
@ -62,10 +70,21 @@ namespace CoopServer
packet.PacketToNetOutGoingMessage(outgoingMessage);
Server.MainNetServer.SendMessage(outgoingMessage, userConnection, NetDeliveryMethod.ReliableOrdered, 0);
}
catch (Exception e)
{
Logging.Error($">> {e.Message} <<>> {e.Source ?? string.Empty} <<>> {e.StackTrace ?? string.Empty} <<");
}
}
public void SendNativeCall(ulong hash, params object[] args)
{
try
{
NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == ID);
if (userConnection == null)
{
return;
}
List<NativeArgument> arguments = Util.ParseNativeArguments(args);
if (arguments == null)
@ -83,15 +102,26 @@ namespace CoopServer
packet.PacketToNetOutGoingMessage(outgoingMessage);
Server.MainNetServer.SendMessage(outgoingMessage, userConnection, NetDeliveryMethod.ReliableOrdered, 0);
}
catch (Exception e)
{
Logging.Error($">> {e.Message} <<>> {e.Source ?? string.Empty} <<>> {e.StackTrace ?? string.Empty} <<");
}
}
public void SendModPacket(string mod, byte customID, byte[] bytes)
{
try
{
NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == ID);
if (userConnection == null)
{
return;
}
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
new ModPacket()
{
ID = -1,
ID = 0,
Target = 0,
Mod = mod,
CustomPacketID = customID,
@ -100,5 +130,11 @@ namespace CoopServer
Server.MainNetServer.SendMessage(outgoingMessage, userConnection, NetDeliveryMethod.ReliableOrdered, 0);
Server.MainNetServer.FlushSendQueue();
}
catch (Exception e)
{
Logging.Error($">> {e.Message} <<>> {e.Source ?? string.Empty} <<>> {e.StackTrace ?? string.Empty} <<");
}
}
#endregion
}
}

View File

@ -8,11 +8,7 @@
private LVector3 CurrentPosition { get; set; }
public LVector3 Position
{
get
{
return CurrentPosition;
}
get => CurrentPosition;
set
{
LastPosition = CurrentPosition;
@ -24,6 +20,20 @@
}
}
}
private int CurrentHealth { get; set; }
public int Health
{
get => CurrentHealth;
set
{
if (CurrentHealth != value && Server.MainResource != null)
{
Server.MainResource.InvokePlayerHealthUpdate(this);
}
CurrentHealth = value;
}
}
public bool IsInRangeOf(LVector3 position, float distance)
{

View File

@ -299,15 +299,16 @@ namespace CoopServer
if (modPacket.Target != 0)
{
NetConnection target = MainNetServer.Connections.FirstOrDefault(x => x.RemoteUniqueIdentifier == modPacket.Target);
if (target == null)
if (target.Equals(default(Client)))
{
Logging.Error($"[ModPacket] target \"{modPacket.Target}\" not found!");
return;
}
else
{
// Send back to target
MainNetServer.SendMessage(outgoingMessage, target, NetDeliveryMethod.ReliableOrdered, 0);
}
}
else
{
// Send back to all players
@ -331,7 +332,7 @@ namespace CoopServer
break;
case NetIncomingMessageType.ConnectionLatencyUpdated:
Client client = Clients.FirstOrDefault(x => x.ID == message.SenderConnection.RemoteUniqueIdentifier);
if (client != default)
if (!client.Equals(default(Client)))
{
client.Latency = message.ReadFloat();
}
@ -420,9 +421,13 @@ namespace CoopServer
long localID = local.RemoteUniqueIdentifier;
Client tmpClient;
// Add the player to Players
lock (Clients)
{
Clients.Add(
new Client()
tmpClient = new Client()
{
ID = localID,
Player = new()
@ -432,6 +437,7 @@ namespace CoopServer
}
}
);
}
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
@ -447,47 +453,51 @@ namespace CoopServer
// Accept the connection and send back a new handshake packet with the connection ID
local.Approve(outgoingMessage);
if (MainResource != null)
{
MainResource.InvokePlayerHandshake(tmpClient);
}
}
// The connection has been approved, now we need to send all other players to the new player and the new player to all players
private static void SendPlayerConnectPacket(NetConnection local, PlayerConnectPacket packet)
{
Client localClient = Clients.FirstOrDefault(x => x.ID == packet.ID);
if (localClient.Equals(default(Client)))
{
local.Disconnect("No data found!");
return;
}
if (!string.IsNullOrEmpty(MainSettings.WelcomeMessage))
{
SendChatMessage(new ChatMessagePacket() { Username = "Server", Message = MainSettings.WelcomeMessage }, new List<NetConnection>() { local });
}
if (MainResource != null)
{
MainResource.InvokePlayerConnected(Clients.Find(x => x.ID == packet.ID));
}
List<NetConnection> clients;
if ((clients = Util.FilterAllLocal(local)).Count == 0)
if ((clients = Util.FilterAllLocal(local)).Count > 0)
{
return;
}
// Send all players to local
clients.ForEach(targetPlayer =>
{
long targetPlayerID = targetPlayer.RemoteUniqueIdentifier;
Client targetEntity = Clients.First(x => x.ID == targetPlayerID);
Client targetClient = Clients.FirstOrDefault(x => x.ID == targetPlayerID);
if (!targetClient.Equals(default(Client)))
{
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
new PlayerConnectPacket()
{
ID = targetPlayerID,
SocialClubName = targetEntity.Player.SocialClubName,
Username = targetEntity.Player.Username
SocialClubName = targetClient.Player.SocialClubName,
Username = targetClient.Player.Username
}.PacketToNetOutGoingMessage(outgoingMessage);
MainNetServer.SendMessage(outgoingMessage, local, NetDeliveryMethod.ReliableOrdered, 0);
}
});
// Send local to all players
Client localClient = Clients.First(x => x.ID == packet.ID);
NetOutgoingMessage outgoingMessage = MainNetServer.CreateMessage();
new PlayerConnectPacket()
{
@ -498,14 +508,15 @@ namespace CoopServer
MainNetServer.SendMessage(outgoingMessage, clients, NetDeliveryMethod.ReliableOrdered, 0);
}
if (MainResource != null)
{
MainResource.InvokePlayerConnected(localClient);
}
}
// Send all players a message that someone has left the server
private static void SendPlayerDisconnectPacket(PlayerDisconnectPacket packet)
{
if (MainResource != null)
{
MainResource.InvokePlayerDisconnected(Clients.Find(x => x.ID == packet.ID));
}
List<NetConnection> clients;
if ((clients = Util.FilterAllLocal(packet.ID)).Count > 0)
{
@ -514,16 +525,40 @@ namespace CoopServer
MainNetServer.SendMessage(outgoingMessage, clients, NetDeliveryMethod.ReliableOrdered, 0);
}
Clients.Remove(Clients.Find(x => x.ID == packet.ID));
Client localClient = Clients.FirstOrDefault(x => x.ID == packet.ID);
if (localClient.Equals(default(Client)))
{
return;
}
if (MainResource != null)
{
MainResource.InvokePlayerDisconnected(localClient);
}
lock (Clients)
{
Clients.Remove(localClient);
}
}
private static void FullSyncPlayer(FullSyncPlayerPacket packet)
{
Client client = Clients.First(x => x.ID == packet.Extra.ID);
client.Player.Position = packet.Extra.Position;
Client tmpClient = Clients.FirstOrDefault(x => x.ID == packet.Extra.ID);
if (tmpClient.Equals(default(Client)))
{
NetConnection localConn = MainNetServer.Connections.Find(x => packet.Extra.ID == x.RemoteUniqueIdentifier);
if (localConn != null)
{
localConn.Disconnect("No data found!");
}
return;
}
tmpClient.Player.Position = packet.Extra.Position;
tmpClient.Player.Health = packet.Extra.Health;
PlayerPacket playerPacket = packet.Extra;
playerPacket.Latency = client.Latency;
playerPacket.Latency = tmpClient.Latency;
packet.Extra = playerPacket;
@ -545,15 +580,30 @@ namespace CoopServer
MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, 0);
});
if (MainResource != null)
{
MainResource.InvokePlayerUpdate(tmpClient);
}
}
private static void FullSyncPlayerVeh(FullSyncPlayerVehPacket packet)
{
Client client = Clients.First(x => x.ID == packet.Extra.ID);
client.Player.Position = packet.Extra.Position;
Client tmpClient = Clients.FirstOrDefault(x => x.ID == packet.Extra.ID);
if (tmpClient.Equals(default(Client)))
{
NetConnection localConn = MainNetServer.Connections.Find(x => packet.Extra.ID == x.RemoteUniqueIdentifier);
if (localConn != null)
{
localConn.Disconnect("No data found!");
}
return;
}
tmpClient.Player.Position = packet.Extra.Position;
tmpClient.Player.Health = packet.Extra.Health;
PlayerPacket playerPacket = packet.Extra;
playerPacket.Latency = client.Latency;
playerPacket.Latency = tmpClient.Latency;
packet.Extra = playerPacket;
@ -575,15 +625,30 @@ namespace CoopServer
MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, 0);
});
if (MainResource != null)
{
MainResource.InvokePlayerUpdate(tmpClient);
}
}
private static void LightSyncPlayer(LightSyncPlayerPacket packet)
{
Client client = Clients.First(x => x.ID == packet.Extra.ID);
client.Player.Position = packet.Extra.Position;
Client tmpClient = Clients.FirstOrDefault(x => x.ID == packet.Extra.ID);
if (tmpClient.Equals(default(Client)))
{
NetConnection localConn = MainNetServer.Connections.Find(x => packet.Extra.ID == x.RemoteUniqueIdentifier);
if (localConn != null)
{
localConn.Disconnect("No data found!");
}
return;
}
tmpClient.Player.Position = packet.Extra.Position;
tmpClient.Player.Health = packet.Extra.Health;
PlayerPacket playerPacket = packet.Extra;
playerPacket.Latency = client.Latency;
playerPacket.Latency = tmpClient.Latency;
packet.Extra = playerPacket;
@ -605,15 +670,30 @@ namespace CoopServer
MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, 0);
});
if (MainResource != null)
{
MainResource.InvokePlayerUpdate(tmpClient);
}
}
private static void LightSyncPlayerVeh(LightSyncPlayerVehPacket packet)
{
Client client = Clients.First(x => x.ID == packet.Extra.ID);
client.Player.Position = packet.Extra.Position;
Client tmpClient = Clients.FirstOrDefault(x => x.ID == packet.Extra.ID);
if (tmpClient.Equals(default(Client)))
{
NetConnection localConn = MainNetServer.Connections.Find(x => packet.Extra.ID == x.RemoteUniqueIdentifier);
if (localConn != null)
{
localConn.Disconnect("No data found!");
}
return;
}
tmpClient.Player.Position = packet.Extra.Position;
tmpClient.Player.Health = packet.Extra.Health;
PlayerPacket playerPacket = packet.Extra;
playerPacket.Latency = client.Latency;
playerPacket.Latency = tmpClient.Latency;
packet.Extra = playerPacket;
@ -635,6 +715,11 @@ namespace CoopServer
MainNetServer.SendMessage(outgoingMessage, x, NetDeliveryMethod.UnreliableSequenced, 0);
});
if (MainResource != null)
{
MainResource.InvokePlayerUpdate(tmpClient);
}
}
// Send a message to targets or all players

View File

@ -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 shutdownTask.Result;
return task.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);
Task<bool> task = new(() => _script.API.InvokeChatMessage(username, message));
task.Start();
task.Wait(5000);
return shutdownTask.Result;
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);
@ -152,11 +198,13 @@ namespace CoopServer
#region FUNCTIONS
public static void SendModPacketToAll(string mod, byte customID, byte[] bytes)
{
try
{
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
new ModPacket()
{
ID = -1,
ID = 0,
Target = 0,
Mod = mod,
CustomPacketID = customID,
@ -165,8 +213,15 @@ namespace CoopServer
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)
{
try
{
if (Server.MainNetServer.ConnectionsCount == 0)
{
@ -189,6 +244,11 @@ namespace CoopServer
packet.PacketToNetOutGoingMessage(outgoingMessage);
Server.MainNetServer.SendMessage(outgoingMessage, Server.MainNetServer.Connections, NetDeliveryMethod.ReliableOrdered, 0);
}
catch (Exception e)
{
Logging.Error($">> {e.Message} <<>> {e.Source ?? string.Empty} <<>> {e.StackTrace ?? string.Empty} <<");
}
}
public static List<long> GetAllConnections()
{
@ -211,26 +271,32 @@ 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")
{
try
{
if (Server.MainNetServer.ConnectionsCount == 0)
{
return;
}
ChatMessagePacket packet = new()
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
new ChatMessagePacket()
{
Username = username,
Message = message
};
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
packet.PacketToNetOutGoingMessage(outgoingMessage);
}.PacketToNetOutGoingMessage(outgoingMessage);
Server.MainNetServer.SendMessage(outgoingMessage, Server.MainNetServer.Connections, NetDeliveryMethod.ReliableOrdered, 0);
}
catch (Exception e)
{
Logging.Error($">> {e.Message} <<>> {e.Source ?? string.Empty} <<>> {e.StackTrace ?? string.Empty} <<");
}
}
public static void RegisterCommand(string name, Action<CommandContext> callback)
{

View File

@ -50,13 +50,13 @@ namespace CoopServer
public static NetConnection GetConnectionByUsername(string username)
{
long clientID;
if ((clientID = Server.Clients.FirstOrDefault(x => x.Player.Username == username).ID) == default)
Client client = Server.Clients.FirstOrDefault(x => x.Player.Username == username);
if (client.Equals(default(Client)))
{
return null;
}
return Server.MainNetServer.Connections.FirstOrDefault(x => x.RemoteUniqueIdentifier == clientID);
return Server.MainNetServer.Connections.FirstOrDefault(x => x.RemoteUniqueIdentifier == client.ID);
}
// Return a list of all connections but not the local connection
@ -72,12 +72,20 @@ namespace CoopServer
// Return a list of players within range of ...
public static List<NetConnection> GetAllInRange(LVector3 position, float range)
{
return new(Server.MainNetServer.Connections.FindAll(e => Server.Clients.First(x => x.ID == e.RemoteUniqueIdentifier).Player.IsInRangeOf(position, range)));
return new(Server.MainNetServer.Connections.FindAll(e =>
{
Client client = Server.Clients.First(x => x.ID == e.RemoteUniqueIdentifier);
return !client.Equals(default(Client)) && client.Player.IsInRangeOf(position, range);
}));
}
// Return a list of players within range of ... but not the local one
public static List<NetConnection> GetAllInRange(LVector3 position, float range, NetConnection local)
{
return new(Server.MainNetServer.Connections.Where(e => e != local && Server.Clients.First(x => x.ID == e.RemoteUniqueIdentifier).Player.IsInRangeOf(position, range)));
return new(Server.MainNetServer.Connections.Where(e =>
{
Client client = Server.Clients.First(x => x.ID == e.RemoteUniqueIdentifier);
return e != local && !client.Equals(default(Client)) && client.Player.IsInRangeOf(position, range);
}));
}
public static T Read<T>(string file) where T : new()