OnTick added. Bug fixes. Remove server created objects/vehicles/peds/checkpoints/blips on disconnect. More...

This commit is contained in:
EntenKoeniq
2021-12-26 03:25:00 +01:00
parent a4ffc25823
commit f4e563f93b
8 changed files with 269 additions and 13 deletions

View File

@ -251,6 +251,59 @@ namespace CoopClient
NPCsVehicles.Clear(); NPCsVehicles.Clear();
} }
internal static readonly Dictionary<ulong, byte> CheckNativeHash = new Dictionary<ulong, byte>()
{
{ 0xD49F9B0955C367DE, 1 },
{ 0xEF29A16337FACADB, 1 },
{ 0xB4AC7D0CF06BFE8F, 1 },
{ 0x9B62392B474F44A0, 1 },
{ 0x7DD959874C1FD534, 1 },
{ 0xAF35D0D2583051B0, 2 },
{ 0x63C6CCA8E68AE8C8, 2 },
{ 0x509D5878EB39E842, 3 },
{ 0x9A294B2138ABB884, 3 },
{ 0x46818D79B1F7499A, 4 },
{ 0x5CDE92C702A8FCE7, 4 },
{ 0xBE339365C863BD36, 4 },
{ 0x5A039BB0BCA604B6, 4 },
{ 0x0134F0835AB6BFCB, 5 }
};
internal static Dictionary<int, byte> ServerItems = new Dictionary<int, byte>();
internal static void CleanUpWorld()
{
if (ServerItems.Count == 0)
{
return;
}
lock (ServerItems)
{
foreach (KeyValuePair<int, byte> item in ServerItems)
{
switch (item.Value)
{
case 1:
World.GetAllEntities().Where(x => x.Handle == item.Key).First().Delete();
break;
case 2:
World.GetAllVehicles().Where(x => x.Handle == item.Key).First().Delete();
break;
case 3:
World.GetAllProps().Where(x => x.Handle == item.Key).First().Delete();
break;
case 4:
World.GetAllBlips().Where(x => x.Handle == item.Key).First().Delete();
break;
case 5:
World.GetAllCheckpoints().Where(x => x.Handle == item.Key).First().Delete();
break;
}
}
ServerItems.Clear();
}
}
#if DEBUG #if DEBUG
private ulong ArtificialLagCounter; private ulong ArtificialLagCounter;
internal static EntitiesPlayer DebugSyncPed; internal static EntitiesPlayer DebugSyncPed;

View File

@ -135,6 +135,8 @@ namespace CoopClient
Latency = 0; Latency = 0;
LastPlayerFullSync = 0; LastPlayerFullSync = 0;
Main.CleanUpWorld();
Main.NPCsAllowed = false; Main.NPCsAllowed = false;
if (Main.MainChat.Focused) if (Main.MainChat.Focused)
@ -158,6 +160,11 @@ namespace CoopClient
switch (packetType) switch (packetType)
{ {
case (byte)PacketTypes.CleanUpWorldPacket:
{
Main.CleanUpWorld();
}
break;
case (byte)PacketTypes.PlayerConnectPacket: case (byte)PacketTypes.PlayerConnectPacket:
{ {
int len = message.ReadInt32(); int len = message.ReadInt32();
@ -602,6 +609,18 @@ namespace CoopClient
return; return;
} }
if (Main.CheckNativeHash.ContainsKey(packet.Hash))
{
foreach (KeyValuePair<ulong, byte> hash in Main.CheckNativeHash)
{
if (hash.Key == packet.Hash)
{
Main.ServerItems.Add((int)result, hash.Value);
break;
}
}
}
NetOutgoingMessage outgoingMessage = Client.CreateMessage(); NetOutgoingMessage outgoingMessage = Client.CreateMessage();
new NativeResponsePacket() new NativeResponsePacket()
{ {
@ -785,7 +804,9 @@ namespace CoopClient
new FullSyncPlayerVehPacket() new FullSyncPlayerVehPacket()
{ {
NetHandle = Main.LocalNetHandle, NetHandle = Main.LocalNetHandle,
PedHandle = player.Handle,
Health = player.Health, Health = player.Health,
VehicleHandle = veh.Handle,
ModelHash = player.Model.Hash, ModelHash = player.Model.Hash,
Clothes = player.GetPedClothes(), Clothes = player.GetPedClothes(),
VehModelHash = veh.Model.Hash, VehModelHash = veh.Model.Hash,
@ -810,6 +831,7 @@ namespace CoopClient
new FullSyncPlayerPacket() new FullSyncPlayerPacket()
{ {
NetHandle = Main.LocalNetHandle, NetHandle = Main.LocalNetHandle,
PedHandle = player.Handle,
Health = player.Health, Health = player.Health,
ModelHash = player.Model.Hash, ModelHash = player.Model.Hash,
Clothes = player.GetPedClothes(), Clothes = player.GetPedClothes(),

View File

@ -112,7 +112,8 @@ namespace CoopClient
ChatMessagePacket, ChatMessagePacket,
NativeCallPacket, NativeCallPacket,
NativeResponsePacket, NativeResponsePacket,
ModPacket ModPacket,
CleanUpWorldPacket
} }
enum ConnectionChannel enum ConnectionChannel
@ -416,6 +417,8 @@ namespace CoopClient
{ {
public long NetHandle { get; set; } public long NetHandle { get; set; }
public int PedHandle { get; set; }
public int Health { get; set; } public int Health { get; set; }
public int ModelHash { get; set; } public int ModelHash { get; set; }
@ -450,6 +453,9 @@ namespace CoopClient
// Write player netHandle // Write player netHandle
byteArray.AddRange(BitConverter.GetBytes(NetHandle)); byteArray.AddRange(BitConverter.GetBytes(NetHandle));
// Write player ped handle
byteArray.AddRange(BitConverter.GetBytes(PedHandle));
// Write player health // Write player health
byteArray.AddRange(BitConverter.GetBytes(Health)); byteArray.AddRange(BitConverter.GetBytes(Health));
@ -545,6 +551,9 @@ namespace CoopClient
// Read player netHandle // Read player netHandle
NetHandle = reader.ReadLong(); NetHandle = reader.ReadLong();
// Read player pedHandle
PedHandle = reader.ReadInt();
// Read player health // Read player health
Health = reader.ReadInt(); Health = reader.ReadInt();
@ -635,8 +644,12 @@ namespace CoopClient
{ {
public long NetHandle { get; set; } public long NetHandle { get; set; }
public int PedHandle { get; set; }
public int Health { get; set; } public int Health { get; set; }
public int VehicleHandle { get; set; }
public int ModelHash { get; set; } public int ModelHash { get; set; }
public Dictionary<byte, short> Clothes { get; set; } public Dictionary<byte, short> Clothes { get; set; }
@ -683,12 +696,18 @@ namespace CoopClient
// Write player netHandle // Write player netHandle
byteArray.AddRange(BitConverter.GetBytes(NetHandle)); byteArray.AddRange(BitConverter.GetBytes(NetHandle));
// Write player ped handle
byteArray.AddRange(BitConverter.GetBytes(PedHandle));
// Write vehicles flags // Write vehicles flags
byteArray.AddRange(BitConverter.GetBytes(Flag.Value)); byteArray.AddRange(BitConverter.GetBytes(Flag.Value));
// Write player health // Write player health
byteArray.AddRange(BitConverter.GetBytes(Health)); byteArray.AddRange(BitConverter.GetBytes(Health));
// Write player ped handle
byteArray.AddRange(BitConverter.GetBytes(VehicleHandle));
// Write player model hash // Write player model hash
byteArray.AddRange(BitConverter.GetBytes(ModelHash)); byteArray.AddRange(BitConverter.GetBytes(ModelHash));
@ -812,12 +831,18 @@ namespace CoopClient
// Read player netHandle // Read player netHandle
NetHandle = reader.ReadLong(); NetHandle = reader.ReadLong();
// Read player ped handle
PedHandle = reader.ReadInt();
// Read vehicle flags // Read vehicle flags
Flag = reader.ReadUShort(); Flag = reader.ReadUShort();
// Read player health // Read player health
Health = reader.ReadInt(); Health = reader.ReadInt();
// Read player vehicle handle
VehicleHandle = reader.ReadInt();
// Read player model hash // Read player model hash
ModelHash = reader.ReadInt(); ModelHash = reader.ReadInt();

View File

@ -11,6 +11,7 @@ namespace CoopServer
public float Latency = 0.0f; public float Latency = 0.0f;
public PlayerData Player; public PlayerData Player;
private readonly Dictionary<string, object> CustomData = new(); private readonly Dictionary<string, object> CustomData = new();
private long CallbacksCount = 0;
internal readonly Dictionary<long, Action<object>> Callbacks = new(); internal readonly Dictionary<long, Action<object>> Callbacks = new();
#region CUSTOMDATA FUNCTIONS #region CUSTOMDATA FUNCTIONS
@ -73,7 +74,7 @@ namespace CoopServer
} }
} }
public void SendNativeCall(ulong hash, List<object> args = null) public void SendNativeCall(ulong hash, params object[] args)
{ {
try try
{ {
@ -84,7 +85,7 @@ namespace CoopServer
return; return;
} }
if (args != null && args.Count == 0) if (args != null && args.Length == 0)
{ {
Logging.Error($"[Client->SendNativeCall(ulong hash, Dictionary<string, object> args)]: Missing arguments!"); Logging.Error($"[Client->SendNativeCall(ulong hash, Dictionary<string, object> args)]: Missing arguments!");
return; return;
@ -93,7 +94,7 @@ namespace CoopServer
NativeCallPacket packet = new() NativeCallPacket packet = new()
{ {
Hash = hash, Hash = hash,
Args = args ?? new List<object>(), Args = new List<object>(args) ?? new List<object>(),
}; };
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage(); NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
@ -106,7 +107,7 @@ namespace CoopServer
} }
} }
public void SendNativeResponse(Action<object> callback, ulong hash, Type returnType, List<object> args = null) public void SendNativeResponse(Action<object> callback, ulong hash, Type returnType, params object[] args)
{ {
try try
{ {
@ -117,14 +118,14 @@ namespace CoopServer
return; return;
} }
if (args != null && args.Count == 0) if (args != null && args.Length == 0)
{ {
Logging.Error($"[Client->SendNativeCall(ulong hash, Dictionary<string, object> args)]: Missing arguments!"); Logging.Error($"[Client->SendNativeCall(ulong hash, Dictionary<string, object> args)]: Missing arguments!");
return; return;
} }
long id = 0; long id = ++CallbacksCount;
Callbacks.Add(id = Environment.TickCount64, callback); Callbacks.Add(id, callback);
byte returnTypeValue = 0x00; byte returnTypeValue = 0x00;
if (returnType == typeof(int)) if (returnType == typeof(int))
@ -157,7 +158,7 @@ namespace CoopServer
new NativeResponsePacket() new NativeResponsePacket()
{ {
Hash = hash, Hash = hash,
Args = args ?? new List<object>(), Args = new List<object>(args) ?? new List<object>(),
ResultType = returnTypeValue, ResultType = returnTypeValue,
ID = id ID = id
}.PacketToNetOutGoingMessage(outgoingMessage); }.PacketToNetOutGoingMessage(outgoingMessage);
@ -169,6 +170,20 @@ namespace CoopServer
} }
} }
public void SendCleanUpWorld()
{
NetConnection userConnection = Server.MainNetServer.Connections.Find(x => x.RemoteUniqueIdentifier == NetHandle);
if (userConnection == null)
{
Logging.Error($"[Client->SendCleanUpWorld()]: Connection \"{NetHandle}\" not found!");
return;
}
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
outgoingMessage.Write((byte)PacketTypes.CleanUpWorldPacket);
Server.MainNetServer.SendMessage(outgoingMessage, userConnection, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Default);
}
public void SendModPacket(string mod, byte customID, byte[] bytes) public void SendModPacket(string mod, byte customID, byte[] bytes)
{ {
try try

View File

@ -8,6 +8,27 @@ using Newtonsoft.Json;
namespace CoopServer namespace CoopServer
{ {
public static class VectorExtensions
{
public static LVector3 Normalize(this LVector3 value)
{
float value2 = value.Length();
return value / value2;
}
public static float Distance(this LVector3 value1, LVector3 value2)
{
LVector3 vector = value1 - value2;
float num = Dot(vector, vector);
return (float)Math.Sqrt(num);
}
public static float Dot(this LVector3 vector1, LVector3 vector2)
{
return vector1.X * vector2.X + vector1.Y * vector2.Y + vector1.Z * vector2.Z;
}
}
public struct LVector3 public struct LVector3
{ {
public LVector3(float X, float Y, float Z) public LVector3(float X, float Y, float Z)
@ -27,6 +48,19 @@ namespace CoopServer
public float Length() => (float)Math.Sqrt((X * X) + (Y * Y) + (Z * Z)); public float Length() => (float)Math.Sqrt((X * X) + (Y * Y) + (Z * Z));
public static LVector3 Subtract(LVector3 pos1, LVector3 pos2) => new(pos1.X - pos2.X, pos1.Y - pos2.Y, pos1.Z - pos2.Z); public static LVector3 Subtract(LVector3 pos1, LVector3 pos2) => new(pos1.X - pos2.X, pos1.Y - pos2.Y, pos1.Z - pos2.Z);
public static bool Equals(LVector3 value1, LVector3 value2) => value1.X == value2.X && value1.Y == value2.Y && value1.Z == value2.Z; public static bool Equals(LVector3 value1, LVector3 value2) => value1.X == value2.X && value1.Y == value2.Y && value1.Z == value2.Z;
public static LVector3 operator /(LVector3 value1, float value2)
{
float num = 1f / value2;
return new LVector3(value1.X * num, value1.Y * num, value1.Z * num);
}
public static LVector3 operator -(LVector3 left, LVector3 right)
{
return new LVector3(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
}
public static LVector3 operator -(LVector3 value)
{
return default(LVector3) - value;
}
#endregion #endregion
} }
@ -64,7 +98,8 @@ namespace CoopServer
ChatMessagePacket, ChatMessagePacket,
NativeCallPacket, NativeCallPacket,
NativeResponsePacket, NativeResponsePacket,
ModPacket ModPacket,
CleanUpWorldPacket
} }
enum ConnectionChannel enum ConnectionChannel
@ -365,6 +400,8 @@ namespace CoopServer
{ {
public long NetHandle { get; set; } public long NetHandle { get; set; }
public int PedHandle { get; set; }
public int Health { get; set; } public int Health { get; set; }
public int ModelHash { get; set; } public int ModelHash { get; set; }
@ -399,6 +436,9 @@ namespace CoopServer
// Write player netHandle // Write player netHandle
byteArray.AddRange(BitConverter.GetBytes(NetHandle)); byteArray.AddRange(BitConverter.GetBytes(NetHandle));
// Write player ped handle
byteArray.AddRange(BitConverter.GetBytes(PedHandle));
// Write player health // Write player health
byteArray.AddRange(BitConverter.GetBytes(Health)); byteArray.AddRange(BitConverter.GetBytes(Health));
@ -494,6 +534,9 @@ namespace CoopServer
// Read player netHandle // Read player netHandle
NetHandle = reader.ReadLong(); NetHandle = reader.ReadLong();
// Read player pedHandle
PedHandle = reader.ReadInt();
// Read player health // Read player health
Health = reader.ReadInt(); Health = reader.ReadInt();
@ -584,8 +627,12 @@ namespace CoopServer
{ {
public long NetHandle { get; set; } public long NetHandle { get; set; }
public int PedHandle { get; set; }
public int Health { get; set; } public int Health { get; set; }
public int VehicleHandle { get; set; }
public int ModelHash { get; set; } public int ModelHash { get; set; }
public Dictionary<byte, short> Clothes { get; set; } public Dictionary<byte, short> Clothes { get; set; }
@ -632,12 +679,18 @@ namespace CoopServer
// Write player netHandle // Write player netHandle
byteArray.AddRange(BitConverter.GetBytes(NetHandle)); byteArray.AddRange(BitConverter.GetBytes(NetHandle));
// Write player ped handle
byteArray.AddRange(BitConverter.GetBytes(PedHandle));
// Write vehicles flags // Write vehicles flags
byteArray.AddRange(BitConverter.GetBytes(Flag.Value)); byteArray.AddRange(BitConverter.GetBytes(Flag.Value));
// Write player health // Write player health
byteArray.AddRange(BitConverter.GetBytes(Health)); byteArray.AddRange(BitConverter.GetBytes(Health));
// Write player ped handle
byteArray.AddRange(BitConverter.GetBytes(VehicleHandle));
// Write player model hash // Write player model hash
byteArray.AddRange(BitConverter.GetBytes(ModelHash)); byteArray.AddRange(BitConverter.GetBytes(ModelHash));
@ -761,12 +814,18 @@ namespace CoopServer
// Read player netHandle // Read player netHandle
NetHandle = reader.ReadLong(); NetHandle = reader.ReadLong();
// Read player ped handle
PedHandle = reader.ReadInt();
// Read vehicle flags // Read vehicle flags
Flag = reader.ReadUShort(); Flag = reader.ReadUShort();
// Read player health // Read player health
Health = reader.ReadInt(); Health = reader.ReadInt();
// Read player vehicle handle
VehicleHandle = reader.ReadInt();
// Read player model hash // Read player model hash
ModelHash = reader.ReadInt(); ModelHash = reader.ReadInt();

View File

@ -5,6 +5,37 @@ namespace CoopServer
public struct PlayerData public struct PlayerData
{ {
public string Username { get; set; } public string Username { get; set; }
private int LastPedHandle = 0;
private int CurrentPedHandle = 0;
public int PedHandle
{
get => CurrentPedHandle;
set
{
LastPedHandle = CurrentPedHandle;
CurrentPedHandle = value;
if (CurrentPedHandle != LastPedHandle)
{
// TODO
}
}
}
private int LastVehicleHandle { get; set; }
private int CurrentVehicleHandle { get; set; }
public int VehicleHandle
{
get => CurrentPedHandle;
set
{
LastVehicleHandle = CurrentVehicleHandle;
CurrentVehicleHandle = value;
if (CurrentVehicleHandle != LastVehicleHandle)
{
// TODO
}
}
}
public bool IsInVehicle { get; set; }
private LVector3 LastPosition { get; set; } private LVector3 LastPosition { get; set; }
private LVector3 CurrentPosition { get; set; } private LVector3 CurrentPosition { get; set; }
public LVector3 Position public LVector3 Position

View File

@ -23,6 +23,7 @@ namespace CoopServer
internal class Server internal class Server
{ {
private static readonly string CompatibleVersion = "V1_3"; private static readonly string CompatibleVersion = "V1_3";
private static long CurrentTick = 0;
public static readonly Settings MainSettings = Util.Read<Settings>("CoopSettings.xml"); public static readonly Settings MainSettings = Util.Read<Settings>("CoopSettings.xml");
private readonly Blocklist MainBlocklist = Util.Read<Blocklist>("Blocklist.xml"); private readonly Blocklist MainBlocklist = Util.Read<Blocklist>("Blocklist.xml");
@ -220,6 +221,14 @@ namespace CoopServer
while (!Program.ReadyToStop) while (!Program.ReadyToStop)
{ {
if (Resources.Count != 0)
{
Resources.ForEach(x =>
{
x.InvokeTick(++CurrentTick);
});
}
NetIncomingMessage message; NetIncomingMessage message;
while ((message = MainNetServer.ReadMessage()) != null) while ((message = MainNetServer.ReadMessage()) != null)
@ -729,6 +738,8 @@ namespace CoopServer
return; return;
} }
// Save the new data // Save the new data
client.Player.PedHandle = packet.PedHandle;
client.Player.IsInVehicle = false;
client.Player.Position = packet.Position; client.Player.Position = packet.Position;
client.Player.Health = packet.Health; client.Player.Health = packet.Health;
@ -769,6 +780,9 @@ namespace CoopServer
return; return;
} }
// Save the new data // Save the new data
client.Player.PedHandle = packet.PedHandle;
client.Player.VehicleHandle = packet.VehicleHandle;
client.Player.IsInVehicle = true;
client.Player.Position = packet.Position; client.Player.Position = packet.Position;
client.Player.Health = packet.Health; client.Player.Health = packet.Health;

View File

@ -128,12 +128,21 @@ namespace CoopServer
_actionQueue.Enqueue(new Action(() => _script.API.InvokePlayerHealthUpdate(playerData))); _actionQueue.Enqueue(new Action(() => _script.API.InvokePlayerHealthUpdate(playerData)));
} }
} }
public void InvokeTick(long tick)
{
lock (_actionQueue.SyncRoot)
{
_actionQueue.Enqueue(new Action(() => _script.API.InvokeTick(tick)));
}
}
} }
public class API public class API
{ {
#region DELEGATES #region DELEGATES
public delegate void EmptyEvent(); public delegate void EmptyEvent();
public delegate void OnTickEvent(long tick);
public delegate void ChatEvent(string username, string message, CancelEventArgs cancel); public delegate void ChatEvent(string username, string message, CancelEventArgs cancel);
public delegate void PlayerEvent(Client client); public delegate void PlayerEvent(Client client);
public delegate void ModEvent(long from, long target, string mod, byte customID, byte[] bytes, CancelEventArgs args); public delegate void ModEvent(long from, long target, string mod, byte customID, byte[] bytes, CancelEventArgs args);
@ -141,6 +150,10 @@ namespace CoopServer
#region EVENTS #region EVENTS
/// <summary> /// <summary>
/// Called every tick
/// </summary>
public event OnTickEvent OnTick;
/// <summary>
/// Called when the server has started /// Called when the server has started
/// </summary> /// </summary>
public event EmptyEvent OnStart; public event EmptyEvent OnStart;
@ -181,6 +194,11 @@ namespace CoopServer
/// </summary> /// </summary>
public event ModEvent OnModPacketReceived; public event ModEvent OnModPacketReceived;
internal void InvokeTick(long tick)
{
OnTick?.Invoke(tick);
}
internal void InvokeStart() internal void InvokeStart()
{ {
OnStart?.Invoke(); OnStart?.Invoke();
@ -276,7 +294,7 @@ namespace CoopServer
/// </summary> /// </summary>
/// <param name="hash">The hash (Example: 0x25223CA6B4D20B7F = GET_CLOCK_HOURS)</param> /// <param name="hash">The hash (Example: 0x25223CA6B4D20B7F = GET_CLOCK_HOURS)</param>
/// <param name="args">The arguments (Example: string = int, object = 5)</param> /// <param name="args">The arguments (Example: string = int, object = 5)</param>
public static void SendNativeCallToAll(ulong hash, List<object> args = null) public static void SendNativeCallToAll(ulong hash, params object[] args)
{ {
try try
{ {
@ -285,7 +303,7 @@ namespace CoopServer
return; return;
} }
if (args != null && args.Count == 0) if (args != null && args.Length == 0)
{ {
Logging.Error($"[ServerScript->SendNativeCallToAll(ulong hash, params object[] args)]: args is not null!"); Logging.Error($"[ServerScript->SendNativeCallToAll(ulong hash, params object[] args)]: args is not null!");
return; return;
@ -294,7 +312,7 @@ namespace CoopServer
NativeCallPacket packet = new() NativeCallPacket packet = new()
{ {
Hash = hash, Hash = hash,
Args = args ?? new List<object>() Args = new List<object>(args) ?? new List<object>()
}; };
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage(); NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
@ -362,6 +380,25 @@ namespace CoopServer
} }
} }
/// <summary>
///
/// </summary>
public static void SendCleanUpWorldToAll(List<long> netHandleList = null)
{
if (Server.MainNetServer.ConnectionsCount == 0)
{
return;
}
List<NetConnection> connections = netHandleList == null
? Server.MainNetServer.Connections
: Server.MainNetServer.Connections.FindAll(c => netHandleList.Contains(c.RemoteUniqueIdentifier));
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
outgoingMessage.Write((byte)PacketTypes.CleanUpWorldPacket);
Server.MainNetServer.SendMessage(outgoingMessage, connections, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Default);
}
/// <summary> /// <summary>
/// Register a new command chat command (Example: "/test") /// Register a new command chat command (Example: "/test")
/// </summary> /// </summary>