Server side entities and custom resource location
This commit is contained in:
@ -52,7 +52,7 @@ namespace RageCoop.Client
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
static string downloadFolder = $"RageCoop\\Resources\\{Main.Settings.LastServerAddress.Replace(":", ".")}";
|
static string downloadFolder = Path.Combine(Main.Settings.ResourceDirectory, Main.Settings.LastServerAddress.Replace(":", "."));
|
||||||
|
|
||||||
private static readonly Dictionary<int, DownloadFile> InProgressDownloads = new Dictionary<int, DownloadFile>();
|
private static readonly Dictionary<int, DownloadFile> InProgressDownloads = new Dictionary<int, DownloadFile>();
|
||||||
public static bool AddFile(int id, string name, long length)
|
public static bool AddFile(int id, string name, long length)
|
||||||
|
@ -14,7 +14,7 @@ namespace RageCoop.Client
|
|||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[XmlRoot(ElementName = "Map")]
|
[XmlRoot(ElementName = "Map")]
|
||||||
public class CoopMap
|
public class Map
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
@ -54,7 +54,7 @@ namespace RageCoop.Client
|
|||||||
internal static class MapLoader
|
internal static class MapLoader
|
||||||
{
|
{
|
||||||
// string = file name
|
// string = file name
|
||||||
private static readonly Dictionary<string, CoopMap> _maps = new Dictionary<string, CoopMap>();
|
private static readonly Dictionary<string, Map> _maps = new Dictionary<string, Map>();
|
||||||
private static readonly List<int> _createdObjects = new List<int>();
|
private static readonly List<int> _createdObjects = new List<int>();
|
||||||
|
|
||||||
public static void LoadAll()
|
public static void LoadAll()
|
||||||
@ -84,14 +84,14 @@ namespace RageCoop.Client
|
|||||||
string filePath = files[i];
|
string filePath = files[i];
|
||||||
string fileName = Path.GetFileName(filePath);
|
string fileName = Path.GetFileName(filePath);
|
||||||
|
|
||||||
XmlSerializer serializer = new XmlSerializer(typeof(CoopMap));
|
XmlSerializer serializer = new XmlSerializer(typeof(Map));
|
||||||
CoopMap map;
|
Map map;
|
||||||
|
|
||||||
using (var stream = new FileStream(filePath, FileMode.Open))
|
using (var stream = new FileStream(filePath, FileMode.Open))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
map = (CoopMap)serializer.Deserialize(stream);
|
map = (Map)serializer.Deserialize(stream);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -117,7 +117,7 @@ namespace RageCoop.Client
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CoopMap map = _maps[name];
|
Map map = _maps[name];
|
||||||
|
|
||||||
foreach (CoopProp prop in map.Props)
|
foreach (CoopProp prop in map.Props)
|
||||||
{
|
{
|
||||||
|
@ -217,7 +217,7 @@ namespace RageCoop.Client.Scripting
|
|||||||
get { return Main.CurrentVersion; }
|
get { return Main.CurrentVersion; }
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Send an event and data to the specified clients.
|
/// Send an event and data to the server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="eventHash">An unique identifier of the event</param>
|
/// <param name="eventHash">An unique identifier of the event</param>
|
||||||
/// <param name="args">The objects conataing your data, supported types:
|
/// <param name="args">The objects conataing your data, supported types:
|
||||||
@ -231,6 +231,20 @@ namespace RageCoop.Client.Scripting
|
|||||||
};
|
};
|
||||||
Networking.Send(p, ConnectionChannel.Event, Lidgren.Network.NetDeliveryMethod.ReliableOrdered);
|
Networking.Send(p, ConnectionChannel.Event, Lidgren.Network.NetDeliveryMethod.ReliableOrdered);
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Send an event and data to the server.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="eventHash"></param>
|
||||||
|
/// <param name="args"></param>
|
||||||
|
public static void SendCustomEvent(int eventHash,params object[] args)
|
||||||
|
{
|
||||||
|
var p = new Packets.CustomEvent()
|
||||||
|
{
|
||||||
|
Args=new List<object>(args),
|
||||||
|
Hash=eventHash
|
||||||
|
};
|
||||||
|
Networking.Send(p, ConnectionChannel.Event, Lidgren.Network.NetDeliveryMethod.ReliableOrdered);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Register an handler to the specifed event hash, one event can have multiple handlers. This will be invoked from backgound thread, use <see cref="QueueAction(Action)"/> in the handler to dispatch code to script thread.
|
/// Register an handler to the specifed event hash, one event can have multiple handlers. This will be invoked from backgound thread, use <see cref="QueueAction(Action)"/> in the handler to dispatch code to script thread.
|
||||||
|
@ -11,7 +11,9 @@ namespace RageCoop.Client.Scripting
|
|||||||
{
|
{
|
||||||
API.RegisterCustomEventHandler(CustomEvents.SetAutoRespawn,SetAutoRespawn);
|
API.RegisterCustomEventHandler(CustomEvents.SetAutoRespawn,SetAutoRespawn);
|
||||||
API.RegisterCustomEventHandler(CustomEvents.NativeCall,NativeCall);
|
API.RegisterCustomEventHandler(CustomEvents.NativeCall,NativeCall);
|
||||||
|
API.Events.OnPedDeleted+=(s,p) => { API.SendCustomEvent(CustomEvents.OnPedDeleted,p.ID); };
|
||||||
|
API.Events.OnVehicleDeleted+=(s, p) => { API.SendCustomEvent(CustomEvents.OnVehicleDeleted, p.ID); };
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnStop()
|
public override void OnStop()
|
||||||
|
@ -63,5 +63,9 @@ namespace RageCoop.Client
|
|||||||
/// The game won't spawn more NPC traffic if the limit is exceeded. -1 for unlimited (not recommended).
|
/// The game won't spawn more NPC traffic if the limit is exceeded. -1 for unlimited (not recommended).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int WorldPedSoftLimit { get; set; } = 50;
|
public int WorldPedSoftLimit { get; set; } = 50;
|
||||||
|
/// <summary>
|
||||||
|
/// The directory where resources downloaded from server will be placed.
|
||||||
|
/// </summary>
|
||||||
|
public string ResourceDirectory { get; set; } = "RageCoop\\Resources";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ using GTA.Native;
|
|||||||
using RageCoop.Core;
|
using RageCoop.Core;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using RageCoop.Client.Scripting;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -138,6 +139,10 @@ namespace RageCoop.Client
|
|||||||
{
|
{
|
||||||
Handle_Peds.Add(c.MainPed.Handle, c);
|
Handle_Peds.Add(c.MainPed.Handle, c);
|
||||||
}
|
}
|
||||||
|
if (c.IsMine)
|
||||||
|
{
|
||||||
|
API.Events.InvokePedSpawned(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public static void RemovePed(int id,string reason="Cleanup")
|
public static void RemovePed(int id,string reason="Cleanup")
|
||||||
{
|
{
|
||||||
@ -160,6 +165,10 @@ namespace RageCoop.Client
|
|||||||
c.PedBlip?.Delete();
|
c.PedBlip?.Delete();
|
||||||
c.ParachuteProp?.Delete();
|
c.ParachuteProp?.Delete();
|
||||||
ID_Peds.Remove(id);
|
ID_Peds.Remove(id);
|
||||||
|
if (c.IsMine)
|
||||||
|
{
|
||||||
|
API.Events.InvokePedDeleted(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@ -196,6 +205,10 @@ namespace RageCoop.Client
|
|||||||
{
|
{
|
||||||
Handle_Vehicles.Add(v.MainVehicle.Handle, v);
|
Handle_Vehicles.Add(v.MainVehicle.Handle, v);
|
||||||
}
|
}
|
||||||
|
if (v.IsMine)
|
||||||
|
{
|
||||||
|
API.Events.InvokeVehicleSpawned(v);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public static void RemoveVehicle(int id,string reason = "Cleanup")
|
public static void RemoveVehicle(int id,string reason = "Cleanup")
|
||||||
{
|
{
|
||||||
@ -215,6 +228,7 @@ namespace RageCoop.Client
|
|||||||
veh.Delete();
|
veh.Delete();
|
||||||
}
|
}
|
||||||
ID_Vehicles.Remove(id);
|
ID_Vehicles.Remove(id);
|
||||||
|
if (v.IsMine) { API.Events.InvokeVehicleDeleted(v); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using GTA;
|
|
||||||
/*
|
|
||||||
namespace RageCoop.Client.Sync
|
|
||||||
{
|
|
||||||
internal class VehicleStateThread : Script
|
|
||||||
{
|
|
||||||
public VehicleStateThread()
|
|
||||||
{
|
|
||||||
Tick+=OnTick;
|
|
||||||
}
|
|
||||||
int current;
|
|
||||||
int toSendPerFrame;
|
|
||||||
int sent;
|
|
||||||
private void OnTick(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
toSendPerFrame=EntityPool.allVehicles.Length*5/(int)Game.FPS+1;
|
|
||||||
if (!Networking.IsOnServer) { return; }
|
|
||||||
for(; sent<toSendPerFrame; sent++)
|
|
||||||
{
|
|
||||||
if (current>=EntityPool.allVehicles.Length)
|
|
||||||
{
|
|
||||||
current=0;
|
|
||||||
}
|
|
||||||
Networking.SendVehicleState(EntityPool.allVehicles[current])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
@ -13,7 +13,8 @@ namespace RageCoop.Core.Scripting
|
|||||||
static MD5 Hasher = MD5.Create();
|
static MD5 Hasher = MD5.Create();
|
||||||
static Dictionary<int,string> Hashed=new Dictionary<int,string>();
|
static Dictionary<int,string> Hashed=new Dictionary<int,string>();
|
||||||
internal static readonly int SetWeather = Hash("RageCoop.SetWeather");
|
internal static readonly int SetWeather = Hash("RageCoop.SetWeather");
|
||||||
internal static readonly int OnPlayerDied = Hash("RageCoop.OnPlayerDied");
|
internal static readonly int OnPedDeleted = Hash("RageCoop.OnPedDeleted");
|
||||||
|
internal static readonly int OnVehicleDeleted = Hash("RageCoop.OnVehicleDeleted");
|
||||||
internal static readonly int SetAutoRespawn = Hash("RageCoop.SetAutoRespawn");
|
internal static readonly int SetAutoRespawn = Hash("RageCoop.SetAutoRespawn");
|
||||||
internal static readonly int NativeCall = Hash("RageCoop.NativeCall");
|
internal static readonly int NativeCall = Hash("RageCoop.NativeCall");
|
||||||
internal static readonly int NativeResponse = Hash("RageCoop.NativeResponse");
|
internal static readonly int NativeResponse = Hash("RageCoop.NativeResponse");
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
|
@ -2,38 +2,12 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using RageCoop.Core;
|
using RageCoop.Core;
|
||||||
using Lidgren.Network;
|
using Lidgren.Network;
|
||||||
using GTA.Math;
|
using System.Linq;
|
||||||
using RageCoop.Core.Scripting;
|
using RageCoop.Core.Scripting;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
namespace RageCoop.Server
|
namespace RageCoop.Server
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Represents a ped from a client
|
|
||||||
/// </summary>
|
|
||||||
public class ServerPed
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The <see cref="Client"/> that is responsible synchronizing for this ped.
|
|
||||||
/// </summary>
|
|
||||||
public Client Owner { get; internal set; }
|
|
||||||
/// <summary>
|
|
||||||
/// The ped's ID (not handle!).
|
|
||||||
/// </summary>
|
|
||||||
public int ID { get;internal set; }
|
|
||||||
/// <summary>
|
|
||||||
/// The ID of the ped's last vehicle.
|
|
||||||
/// </summary>
|
|
||||||
public int VehicleID { get; internal set; }
|
|
||||||
/// <summary>
|
|
||||||
/// Position of this ped
|
|
||||||
/// </summary>
|
|
||||||
public Vector3 Position { get; internal set; }
|
|
||||||
/// <summary>
|
|
||||||
/// Health
|
|
||||||
/// </summary>
|
|
||||||
public int Health { get; internal set; }
|
|
||||||
}
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -84,7 +58,7 @@ namespace RageCoop.Server
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Th client's IP address and port.
|
/// Th client's IP address and port.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public System.Net.IPEndPoint EndPoint { get { return Connection.RemoteEndPoint; } }
|
public System.Net.IPEndPoint EndPoint { get { return Connection?.RemoteEndPoint; } }
|
||||||
internal long NetID = 0;
|
internal long NetID = 0;
|
||||||
internal NetConnection Connection { get;set; }
|
internal NetConnection Connection { get;set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -260,6 +234,31 @@ namespace RageCoop.Server
|
|||||||
Server.Logger?.Error(ex);
|
Server.Logger?.Error(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public void SendCustomEvent(int hash,params object[] args)
|
||||||
|
{
|
||||||
|
if (!IsReady)
|
||||||
|
{
|
||||||
|
Server.Logger?.Warning($"Player \"{Username}\" is not ready!");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
|
||||||
|
new Packets.CustomEvent()
|
||||||
|
{
|
||||||
|
Hash=hash,
|
||||||
|
Args=new(args)
|
||||||
|
}.Pack(outgoingMessage);
|
||||||
|
Server.MainNetServer.SendMessage(outgoingMessage, Connection, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Event);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Server.Logger?.Error(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,45 +144,12 @@ namespace RageCoop.Server.Scripting
|
|||||||
/// Server side events
|
/// Server side events
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly APIEvents Events;
|
public readonly APIEvents Events;
|
||||||
#region FUNCTIONS
|
|
||||||
/*
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Send a native call (Function.Call) to all players.
|
/// All synchronized entities on this server.
|
||||||
/// Keys = int, float, bool, string and lvector3
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="hash">The hash (Example: 0x25223CA6B4D20B7F = GET_CLOCK_HOURS)</param>
|
public ServerEntities Entities { get { return Server.Entities; } }
|
||||||
/// <param name="args">The arguments (Example: string = int, object = 5)</param>
|
#region FUNCTIONS
|
||||||
public void SendNativeCallToAll(GTA.Native.Hash hash, params object[] args)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (Server.MainNetServer.ConnectionsCount == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args != null && args.Length == 0)
|
|
||||||
{
|
|
||||||
Server.Logger?.Error($"[ServerScript->SendNativeCallToAll(ulong hash, params object[] args)]: args is not null!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Packets.NativeCall packet = new()
|
|
||||||
{
|
|
||||||
Hash = (ulong)hash,
|
|
||||||
Args = new List<object>(args) ?? new List<object>()
|
|
||||||
};
|
|
||||||
|
|
||||||
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
|
|
||||||
packet.Pack(outgoingMessage);
|
|
||||||
Server.MainNetServer.SendMessage(outgoingMessage, Server.MainNetServer.Connections, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.Native);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Server.Logger?.Error($">> {e.Message} <<>> {e.Source ?? string.Empty} <<>> {e.StackTrace ?? string.Empty} <<");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a list of all Clients
|
/// Get a list of all Clients
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -12,13 +12,21 @@ namespace RageCoop.Server.Scripting
|
|||||||
public override void OnStart()
|
public override void OnStart()
|
||||||
{
|
{
|
||||||
API.RegisterCustomEventHandler(CustomEvents.NativeResponse, NativeResponse);
|
API.RegisterCustomEventHandler(CustomEvents.NativeResponse, NativeResponse);
|
||||||
|
API.RegisterCustomEventHandler(CustomEvents.OnVehicleDeleted, (e) =>
|
||||||
|
{
|
||||||
|
API.Entities.RemoveVehicle((int)e.Args[0]);
|
||||||
|
});
|
||||||
|
API.RegisterCustomEventHandler(CustomEvents.OnPedDeleted, (e) =>
|
||||||
|
{
|
||||||
|
API.Entities.RemovePed((int)e.Args[0]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
public override void OnStop()
|
public override void OnStop()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
public void SetAutoRespawn(Client c,bool toggle)
|
public void SetAutoRespawn(Client c,bool toggle)
|
||||||
{
|
{
|
||||||
c.SendCustomEvent(CustomEvents.SetAutoRespawn, new() { toggle });
|
c.SendCustomEvent(CustomEvents.SetAutoRespawn, toggle );
|
||||||
}
|
}
|
||||||
void NativeResponse(CustomEventReceivedArgs e)
|
void NativeResponse(CustomEventReceivedArgs e)
|
||||||
{
|
{
|
||||||
|
@ -36,6 +36,7 @@ namespace RageCoop.Server
|
|||||||
internal BaseScript BaseScript { get; set; }=new BaseScript();
|
internal BaseScript BaseScript { get; set; }=new BaseScript();
|
||||||
internal readonly ServerSettings Settings;
|
internal readonly ServerSettings Settings;
|
||||||
internal NetServer MainNetServer;
|
internal NetServer MainNetServer;
|
||||||
|
internal ServerEntities Entities;
|
||||||
|
|
||||||
internal readonly Dictionary<Command, Action<CommandContext>> Commands = new();
|
internal readonly Dictionary<Command, Action<CommandContext>> Commands = new();
|
||||||
internal readonly Dictionary<long,Client> Clients = new();
|
internal readonly Dictionary<long,Client> Clients = new();
|
||||||
@ -67,6 +68,7 @@ namespace RageCoop.Server
|
|||||||
API=new API(this);
|
API=new API(this);
|
||||||
Resources=new Resources(this);
|
Resources=new Resources(this);
|
||||||
Security=new Security(Logger);
|
Security=new Security(Logger);
|
||||||
|
Entities=new ServerEntities(this);
|
||||||
|
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -670,6 +672,7 @@ namespace RageCoop.Server
|
|||||||
}.Pack(outgoingMessage);
|
}.Pack(outgoingMessage);
|
||||||
MainNetServer.SendMessage(outgoingMessage,cons , NetDeliveryMethod.ReliableOrdered, 0);
|
MainNetServer.SendMessage(outgoingMessage,cons , NetDeliveryMethod.ReliableOrdered, 0);
|
||||||
}
|
}
|
||||||
|
Entities.CleanUp(localClient);
|
||||||
_worker.QueueJob(() => API.Events.InvokePlayerDisconnected(localClient));
|
_worker.QueueJob(() => API.Events.InvokePlayerDisconnected(localClient));
|
||||||
Logger?.Info($"Player {localClient.Username} disconnected! ID:{localClient.Player.ID}");
|
Logger?.Info($"Player {localClient.Username} disconnected! ID:{localClient.Player.ID}");
|
||||||
Clients.Remove(localClient.NetID);
|
Clients.Remove(localClient.NetID);
|
||||||
@ -693,14 +696,8 @@ namespace RageCoop.Server
|
|||||||
}
|
}
|
||||||
private void VehicleStateSync(Packets.VehicleStateSync packet, Client client)
|
private void VehicleStateSync(Packets.VehicleStateSync packet, Client client)
|
||||||
{
|
{
|
||||||
// Save the new data
|
_worker.QueueJob(() => Entities.Update(packet, client));
|
||||||
_worker.QueueJob(() =>
|
|
||||||
{
|
|
||||||
if (packet.Passengers.ContainsValue(client.Player.ID))
|
|
||||||
{
|
|
||||||
client.Player.VehicleID = packet.ID;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
foreach (var c in Clients.Values)
|
foreach (var c in Clients.Values)
|
||||||
{
|
{
|
||||||
@ -712,12 +709,11 @@ namespace RageCoop.Server
|
|||||||
}
|
}
|
||||||
private void PedSync(Packets.PedSync packet, Client client)
|
private void PedSync(Packets.PedSync packet, Client client)
|
||||||
{
|
{
|
||||||
|
_worker.QueueJob(() => Entities.Update(packet, client));
|
||||||
|
|
||||||
bool isPlayer = packet.ID==client.Player.ID;
|
bool isPlayer = packet.ID==client.Player.ID;
|
||||||
if (isPlayer)
|
if (isPlayer)
|
||||||
{
|
{
|
||||||
client.Player.Position=packet.Position;
|
|
||||||
client.Player.Health=packet.Health ;
|
|
||||||
client.Player.Owner=client;
|
|
||||||
_worker.QueueJob(() => API.Events.InvokePlayerUpdate(client));
|
_worker.QueueJob(() => API.Events.InvokePlayerUpdate(client));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -747,7 +743,8 @@ namespace RageCoop.Server
|
|||||||
}
|
}
|
||||||
private void VehicleSync(Packets.VehicleSync packet, Client client)
|
private void VehicleSync(Packets.VehicleSync packet, Client client)
|
||||||
{
|
{
|
||||||
bool isPlayer = packet.ID==client.Player.VehicleID;
|
_worker.QueueJob(() => Entities.Update(packet, client));
|
||||||
|
bool isPlayer = packet.ID==client.Player?.LastVehicle?.ID;
|
||||||
foreach (var c in Clients.Values)
|
foreach (var c in Clients.Values)
|
||||||
{
|
{
|
||||||
if (c.NetID==client.NetID) { continue; }
|
if (c.NetID==client.NetID) { continue; }
|
||||||
|
228
RageCoop.Server/ServerEntities.cs
Normal file
228
RageCoop.Server/ServerEntities.cs
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using RageCoop.Core;
|
||||||
|
using GTA.Math;
|
||||||
|
using GTA;
|
||||||
|
|
||||||
|
namespace RageCoop.Server
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a ped from a client
|
||||||
|
/// </summary>
|
||||||
|
public class ServerPed
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="Client"/> that is responsible synchronizing for this ped.
|
||||||
|
/// </summary>
|
||||||
|
public Client Owner { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ped's network ID (not handle!).
|
||||||
|
/// </summary>
|
||||||
|
public int ID { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether this ped is a player.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsPlayer { get { return Owner?.Player==this; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ped's last vehicle.
|
||||||
|
/// </summary>
|
||||||
|
public ServerVehicle LastVehicle { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Position of this ped
|
||||||
|
/// </summary>
|
||||||
|
public Vector3 Position { get; internal set; }
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets this ped's rotation
|
||||||
|
/// </summary>
|
||||||
|
public Vector3 Rotation { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Health
|
||||||
|
/// </summary>
|
||||||
|
public int Health { get; internal set; }
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a vehicle from a client
|
||||||
|
/// </summary>
|
||||||
|
public class ServerVehicle
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="Client"/> that is responsible synchronizing for this vehicle.
|
||||||
|
/// </summary>
|
||||||
|
public Client Owner { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The vehicle's network ID (not handle!).
|
||||||
|
/// </summary>
|
||||||
|
public int ID { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Position of this vehicle
|
||||||
|
/// </summary>
|
||||||
|
public Vector3 Position { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets this vehicle's quaternion
|
||||||
|
/// </summary>
|
||||||
|
public Quaternion Quaternion { get; internal set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an object owned by server.
|
||||||
|
/// </summary>
|
||||||
|
public class ServerObject
|
||||||
|
{
|
||||||
|
internal ServerObject()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// The object's model
|
||||||
|
/// </summary>
|
||||||
|
public Model Model { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets this object's position
|
||||||
|
/// </summary>
|
||||||
|
public Vector3 Position { get;set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets this object's quaternion
|
||||||
|
/// </summary>
|
||||||
|
public Quaternion Quaternion { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether this object is invincible
|
||||||
|
/// </summary>
|
||||||
|
public bool IsInvincible { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Manipulate entities from the server
|
||||||
|
/// </summary>
|
||||||
|
public class ServerEntities
|
||||||
|
{
|
||||||
|
private readonly Server Server;
|
||||||
|
internal ServerEntities(Server server)
|
||||||
|
{
|
||||||
|
Server = server;
|
||||||
|
}
|
||||||
|
internal Dictionary<int, ServerPed> Peds { get; set; } = new();
|
||||||
|
internal Dictionary<int, ServerVehicle> Vehicles { get; set; } = new();
|
||||||
|
internal Dictionary<int,ServerObject> ServerObjects { get; set; }=new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all peds on this server
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public ServerPed[] GetAllPeds()
|
||||||
|
{
|
||||||
|
return Peds.Values.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all vehicles on this server
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public ServerVehicle[] GetAllVehicle()
|
||||||
|
{
|
||||||
|
return Vehicles.Values.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all static objects owned by server
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public ServerObject[] GetAllObjects()
|
||||||
|
{
|
||||||
|
return ServerObjects.Values.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Not thread safe
|
||||||
|
/// </summary>
|
||||||
|
internal void Update(Packets.PedSync p,Client sender)
|
||||||
|
{
|
||||||
|
ServerPed ped;
|
||||||
|
if(!Peds.TryGetValue(p.ID,out ped))
|
||||||
|
{
|
||||||
|
Peds.Add(p.ID,ped=new ServerPed());
|
||||||
|
ped.ID=p.ID;
|
||||||
|
}
|
||||||
|
ped.Position = p.Position;
|
||||||
|
ped.Owner=sender;
|
||||||
|
ped.Health=p.Health;
|
||||||
|
ped.Rotation=p.Rotation;
|
||||||
|
ped.Owner=sender;
|
||||||
|
}
|
||||||
|
internal void Update(Packets.VehicleSync p, Client sender)
|
||||||
|
{
|
||||||
|
ServerVehicle veh;
|
||||||
|
if (!Vehicles.TryGetValue(p.ID, out veh))
|
||||||
|
{
|
||||||
|
Vehicles.Add(p.ID, veh=new ServerVehicle());
|
||||||
|
veh.ID=p.ID;
|
||||||
|
}
|
||||||
|
veh.Position = p.Position;
|
||||||
|
veh.Owner=sender;
|
||||||
|
veh.Quaternion=p.Quaternion;
|
||||||
|
}
|
||||||
|
internal void Update(Packets.VehicleStateSync p, Client sender)
|
||||||
|
{
|
||||||
|
ServerVehicle veh;
|
||||||
|
if (!Vehicles.TryGetValue(p.ID, out veh))
|
||||||
|
{
|
||||||
|
Vehicles.Add(p.ID, veh=new ServerVehicle());
|
||||||
|
veh.ID=p.ID;
|
||||||
|
}
|
||||||
|
foreach(var pair in p.Passengers)
|
||||||
|
{
|
||||||
|
if(Peds.TryGetValue(pair.Value,out var ped))
|
||||||
|
{
|
||||||
|
ped.LastVehicle=veh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal void CleanUp(Client left)
|
||||||
|
{
|
||||||
|
Server.Logger?.Trace("Removing all entities from: "+left.Username);
|
||||||
|
|
||||||
|
foreach (var pair in Peds)
|
||||||
|
{
|
||||||
|
if (pair.Value.Owner==left)
|
||||||
|
{
|
||||||
|
Server.QueueJob(()=>Peds.Remove(pair.Key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (var pair in Vehicles)
|
||||||
|
{
|
||||||
|
if (pair.Value.Owner==left)
|
||||||
|
{
|
||||||
|
Server.QueueJob(() => Vehicles.Remove(pair.Key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Server.QueueJob(() =>
|
||||||
|
Server.Logger?.Trace("Remaining entities: "+(Peds.Count+Vehicles.Count)));
|
||||||
|
}
|
||||||
|
internal void RemoveVehicle(int id)
|
||||||
|
{
|
||||||
|
// Server.Logger?.Trace($"Removing vehicle:{id}");
|
||||||
|
if (Vehicles.ContainsKey(id)) { Vehicles.Remove(id); }
|
||||||
|
}
|
||||||
|
internal void RemovePed(int id)
|
||||||
|
{
|
||||||
|
// Server.Logger?.Trace($"Removing ped:{id}");
|
||||||
|
if (Peds.ContainsKey(id)) { Peds.Remove(id); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -27,18 +27,18 @@
|
|||||||
public string WelcomeMessage { get; set; } = "Welcome on this server :)";
|
public string WelcomeMessage { get; set; } = "Welcome on this server :)";
|
||||||
// public bool HolePunch { get; set; } = true;
|
// public bool HolePunch { get; set; } = true;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether or not to announce this server so that it'll appear on server list.
|
/// Whether or not to announce this server so it'll appear on server list.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool AnnounceSelf { get; set; } = false;
|
public bool AnnounceSelf { get; set; } = false;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Master server address, mostly doesn't to be changed.
|
/// Master server address, mostly doesn't need to be changed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string MasterServer { get; set; } = "[AUTO]";
|
public string MasterServer { get; set; } = "[AUTO]";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// See <see cref="Core.Logger.LogLevel"/>.
|
/// See <see cref="Core.Logger.LogLevel"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int LogLevel=2;
|
public int LogLevel { get; set; }=2;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// NPC data won't be sent to a player if their distance is greater than this value. -1 for unlimited.
|
/// NPC data won't be sent to a player if their distance is greater than this value. -1 for unlimited.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
Reference in New Issue
Block a user