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>();
|
||||
public static bool AddFile(int id, string name, long length)
|
||||
|
@ -14,7 +14,7 @@ namespace RageCoop.Client
|
||||
///
|
||||
/// </summary>
|
||||
[XmlRoot(ElementName = "Map")]
|
||||
public class CoopMap
|
||||
public class Map
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
@ -54,7 +54,7 @@ namespace RageCoop.Client
|
||||
internal static class MapLoader
|
||||
{
|
||||
// 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>();
|
||||
|
||||
public static void LoadAll()
|
||||
@ -84,14 +84,14 @@ namespace RageCoop.Client
|
||||
string filePath = files[i];
|
||||
string fileName = Path.GetFileName(filePath);
|
||||
|
||||
XmlSerializer serializer = new XmlSerializer(typeof(CoopMap));
|
||||
CoopMap map;
|
||||
XmlSerializer serializer = new XmlSerializer(typeof(Map));
|
||||
Map map;
|
||||
|
||||
using (var stream = new FileStream(filePath, FileMode.Open))
|
||||
{
|
||||
try
|
||||
{
|
||||
map = (CoopMap)serializer.Deserialize(stream);
|
||||
map = (Map)serializer.Deserialize(stream);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -117,7 +117,7 @@ namespace RageCoop.Client
|
||||
return;
|
||||
}
|
||||
|
||||
CoopMap map = _maps[name];
|
||||
Map map = _maps[name];
|
||||
|
||||
foreach (CoopProp prop in map.Props)
|
||||
{
|
||||
|
@ -217,7 +217,7 @@ namespace RageCoop.Client.Scripting
|
||||
get { return Main.CurrentVersion; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Send an event and data to the specified clients.
|
||||
/// Send an event and data to the server.
|
||||
/// </summary>
|
||||
/// <param name="eventHash">An unique identifier of the event</param>
|
||||
/// <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);
|
||||
}
|
||||
/// <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>
|
||||
/// 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,6 +11,8 @@ namespace RageCoop.Client.Scripting
|
||||
{
|
||||
API.RegisterCustomEventHandler(CustomEvents.SetAutoRespawn,SetAutoRespawn);
|
||||
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); };
|
||||
|
||||
}
|
||||
|
||||
|
@ -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).
|
||||
/// </summary>
|
||||
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 System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using RageCoop.Client.Scripting;
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
@ -138,6 +139,10 @@ namespace RageCoop.Client
|
||||
{
|
||||
Handle_Peds.Add(c.MainPed.Handle, c);
|
||||
}
|
||||
if (c.IsMine)
|
||||
{
|
||||
API.Events.InvokePedSpawned(c);
|
||||
}
|
||||
}
|
||||
public static void RemovePed(int id,string reason="Cleanup")
|
||||
{
|
||||
@ -160,6 +165,10 @@ namespace RageCoop.Client
|
||||
c.PedBlip?.Delete();
|
||||
c.ParachuteProp?.Delete();
|
||||
ID_Peds.Remove(id);
|
||||
if (c.IsMine)
|
||||
{
|
||||
API.Events.InvokePedDeleted(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
@ -196,6 +205,10 @@ namespace RageCoop.Client
|
||||
{
|
||||
Handle_Vehicles.Add(v.MainVehicle.Handle, v);
|
||||
}
|
||||
if (v.IsMine)
|
||||
{
|
||||
API.Events.InvokeVehicleSpawned(v);
|
||||
}
|
||||
}
|
||||
public static void RemoveVehicle(int id,string reason = "Cleanup")
|
||||
{
|
||||
@ -215,6 +228,7 @@ namespace RageCoop.Client
|
||||
veh.Delete();
|
||||
}
|
||||
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 Dictionary<int,string> Hashed=new Dictionary<int,string>();
|
||||
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 NativeCall = Hash("RageCoop.NativeCall");
|
||||
internal static readonly int NativeResponse = Hash("RageCoop.NativeResponse");
|
||||
|
@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
|
@ -2,38 +2,12 @@
|
||||
using System.Collections.Generic;
|
||||
using RageCoop.Core;
|
||||
using Lidgren.Network;
|
||||
using GTA.Math;
|
||||
using System.Linq;
|
||||
using RageCoop.Core.Scripting;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
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>
|
||||
@ -84,7 +58,7 @@ namespace RageCoop.Server
|
||||
/// <summary>
|
||||
/// Th client's IP address and port.
|
||||
/// </summary>
|
||||
public System.Net.IPEndPoint EndPoint { get { return Connection.RemoteEndPoint; } }
|
||||
public System.Net.IPEndPoint EndPoint { get { return Connection?.RemoteEndPoint; } }
|
||||
internal long NetID = 0;
|
||||
internal NetConnection Connection { get;set; }
|
||||
/// <summary>
|
||||
@ -260,6 +234,31 @@ namespace RageCoop.Server
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -144,45 +144,12 @@ namespace RageCoop.Server.Scripting
|
||||
/// Server side events
|
||||
/// </summary>
|
||||
public readonly APIEvents Events;
|
||||
#region FUNCTIONS
|
||||
/*
|
||||
|
||||
/// <summary>
|
||||
/// Send a native call (Function.Call) to all players.
|
||||
/// Keys = int, float, bool, string and lvector3
|
||||
/// All synchronized entities on this server.
|
||||
/// </summary>
|
||||
/// <param name="hash">The hash (Example: 0x25223CA6B4D20B7F = GET_CLOCK_HOURS)</param>
|
||||
/// <param name="args">The arguments (Example: string = int, object = 5)</param>
|
||||
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} <<");
|
||||
}
|
||||
}
|
||||
*/
|
||||
public ServerEntities Entities { get { return Server.Entities; } }
|
||||
#region FUNCTIONS
|
||||
/// <summary>
|
||||
/// Get a list of all Clients
|
||||
/// </summary>
|
||||
|
@ -12,13 +12,21 @@ namespace RageCoop.Server.Scripting
|
||||
public override void OnStart()
|
||||
{
|
||||
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 void SetAutoRespawn(Client c,bool toggle)
|
||||
{
|
||||
c.SendCustomEvent(CustomEvents.SetAutoRespawn, new() { toggle });
|
||||
c.SendCustomEvent(CustomEvents.SetAutoRespawn, toggle );
|
||||
}
|
||||
void NativeResponse(CustomEventReceivedArgs e)
|
||||
{
|
||||
|
@ -36,6 +36,7 @@ namespace RageCoop.Server
|
||||
internal BaseScript BaseScript { get; set; }=new BaseScript();
|
||||
internal readonly ServerSettings Settings;
|
||||
internal NetServer MainNetServer;
|
||||
internal ServerEntities Entities;
|
||||
|
||||
internal readonly Dictionary<Command, Action<CommandContext>> Commands = new();
|
||||
internal readonly Dictionary<long,Client> Clients = new();
|
||||
@ -67,6 +68,7 @@ namespace RageCoop.Server
|
||||
API=new API(this);
|
||||
Resources=new Resources(this);
|
||||
Security=new Security(Logger);
|
||||
Entities=new ServerEntities(this);
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
@ -670,6 +672,7 @@ namespace RageCoop.Server
|
||||
}.Pack(outgoingMessage);
|
||||
MainNetServer.SendMessage(outgoingMessage,cons , NetDeliveryMethod.ReliableOrdered, 0);
|
||||
}
|
||||
Entities.CleanUp(localClient);
|
||||
_worker.QueueJob(() => API.Events.InvokePlayerDisconnected(localClient));
|
||||
Logger?.Info($"Player {localClient.Username} disconnected! ID:{localClient.Player.ID}");
|
||||
Clients.Remove(localClient.NetID);
|
||||
@ -693,14 +696,8 @@ namespace RageCoop.Server
|
||||
}
|
||||
private void VehicleStateSync(Packets.VehicleStateSync packet, Client client)
|
||||
{
|
||||
// Save the new data
|
||||
_worker.QueueJob(() =>
|
||||
{
|
||||
if (packet.Passengers.ContainsValue(client.Player.ID))
|
||||
{
|
||||
client.Player.VehicleID = packet.ID;
|
||||
}
|
||||
});
|
||||
_worker.QueueJob(() => Entities.Update(packet, client));
|
||||
|
||||
|
||||
foreach (var c in Clients.Values)
|
||||
{
|
||||
@ -712,12 +709,11 @@ namespace RageCoop.Server
|
||||
}
|
||||
private void PedSync(Packets.PedSync packet, Client client)
|
||||
{
|
||||
_worker.QueueJob(() => Entities.Update(packet, client));
|
||||
|
||||
bool isPlayer = packet.ID==client.Player.ID;
|
||||
if (isPlayer)
|
||||
{
|
||||
client.Player.Position=packet.Position;
|
||||
client.Player.Health=packet.Health ;
|
||||
client.Player.Owner=client;
|
||||
_worker.QueueJob(() => API.Events.InvokePlayerUpdate(client));
|
||||
}
|
||||
|
||||
@ -747,7 +743,8 @@ namespace RageCoop.Server
|
||||
}
|
||||
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)
|
||||
{
|
||||
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 bool HolePunch { get; set; } = true;
|
||||
/// <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>
|
||||
public bool AnnounceSelf { get; set; } = false;
|
||||
/// <summary>
|
||||
/// Master server address, mostly doesn't to be changed.
|
||||
/// Master server address, mostly doesn't need to be changed.
|
||||
/// </summary>
|
||||
public string MasterServer { get; set; } = "[AUTO]";
|
||||
|
||||
/// <summary>
|
||||
/// See <see cref="Core.Logger.LogLevel"/>.
|
||||
/// </summary>
|
||||
public int LogLevel=2;
|
||||
public int LogLevel { get; set; }=2;
|
||||
/// <summary>
|
||||
/// NPC data won't be sent to a player if their distance is greater than this value. -1 for unlimited.
|
||||
/// </summary>
|
||||
|
Reference in New Issue
Block a user