RAGECOOP-V/RageCoop.Server/ServerEntities.cs

392 lines
11 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RageCoop.Core;
2022-07-02 17:14:56 +08:00
using RageCoop.Core.Scripting;
using System.Security.Cryptography;
using GTA.Math;
using GTA;
namespace RageCoop.Server
{
2022-07-02 17:14:56 +08:00
/// <summary>
/// Represents an prop owned by server.
/// </summary>
public class ServerProp
{
private Server Server;
internal ServerProp(Server server)
{
Server= server;
}
/// <summary>
2022-07-02 18:30:16 +08:00
/// Pass this as an argument in CustomEvent or NativeCall to convert this object to handle at client side.
/// </summary>
public Tuple<byte,byte[]> Handle
{
get
{
return new(50, BitConverter.GetBytes(ID));
}
}
2022-07-02 17:14:56 +08:00
/// <summary>
/// Delete this prop
/// </summary>
public void Delete()
{
Server.API.SendCustomEvent(CustomEvents.DeleteServerProp, new() { ID });
}
/// <summary>
/// Network ID of this object.
/// </summary>
public int ID { get; internal set; }
/// <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 { return _pos; }
set { _pos=value; Server.BaseScript.SendServerObjectsTo(new() { this }); }
}
private Vector3 _pos;
2022-07-02 17:14:56 +08:00
/// <summary>
/// Gets or sets this object's rotation
/// </summary>
public Vector3 Rotation
{
get { return _rot; }
set { _rot=value; Server.BaseScript.SendServerObjectsTo(new() { this }); }
}
private Vector3 _rot;
}
/// <summary>
/// Represents a ped from a client
/// </summary>
public class ServerPed
{
internal ServerPed()
{
}
/// <summary>
2022-07-02 18:30:16 +08:00
/// Pass this as an argument in CustomEvent or NativeCall to convert this object to handle at client side.
/// </summary>
public Tuple<byte, byte[]> Handle
{
get
{
return new(51, BitConverter.GetBytes(ID));
}
}
/// <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
{
internal ServerVehicle()
{
}
/// <summary>
2022-07-02 18:30:16 +08:00
/// Pass this as an argument in CustomEvent or NativeCall to convert this object to handle at client side.
/// </summary>
public Tuple<byte, byte[]> Handle
{
get{
return new(52, BitConverter.GetBytes(ID));
}
}
/// <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; }
}
2022-07-02 17:14:56 +08:00
/// <summary>
2022-07-02 17:14:56 +08:00
/// Manipulate entities from the server
/// </summary>
2022-07-02 17:14:56 +08:00
public class ServerEntities
{
2022-07-02 17:14:56 +08:00
private readonly Server Server;
internal ServerEntities(Server server)
{
2022-07-02 17:14:56 +08:00
Server = server;
}
2022-07-02 17:14:56 +08:00
internal Dictionary<int, ServerPed> Peds { get; set; } = new();
internal Dictionary<int, ServerVehicle> Vehicles { get; set; } = new();
internal Dictionary<int,ServerProp> ServerProps { get; set; }=new();
/// <summary>
2022-07-02 17:14:56 +08:00
/// Get a <see cref="ServerPed"/> by it's id
/// </summary>
2022-07-02 17:14:56 +08:00
/// <param name="id"></param>
/// <returns></returns>
public ServerPed GetPedByID(int id)
{
if(Peds.TryGetValue(id,out var ped))
{
return ped;
}
else
{
return null;
}
}
/// <summary>
2022-07-02 17:14:56 +08:00
/// Get a <see cref="ServerVehicle"/> by it's id
/// </summary>
2022-07-02 17:14:56 +08:00
/// <param name="id"></param>
/// <returns></returns>
public ServerVehicle GetVehicleByID(int id)
{
if (Vehicles.TryGetValue(id, out var veh))
{
return veh;
}
else
{
return null;
}
}
/// <summary>
2022-07-02 17:14:56 +08:00
/// Get a <see cref="ServerProp"/> owned by server from it's ID.
/// </summary>
2022-07-02 17:14:56 +08:00
/// <param name="id"></param>
/// <returns></returns>
public ServerProp GetPropByID(int id)
{
if (ServerProps.TryGetValue(id, out var obj))
{
return obj;
}
else
{
return null;
}
}
/// <summary>
2022-07-02 17:14:56 +08:00
/// Create a static prop owned by server.
/// </summary>
2022-07-02 17:14:56 +08:00
/// <param name="model"></param>
/// <param name="pos"></param>
/// <param name="rot"></param>
/// <returns></returns>
public ServerProp CreateProp(Model model,Vector3 pos,Vector3 rot)
{
2022-07-02 17:14:56 +08:00
int id = RequestID();
ServerProp prop;
ServerProps.Add(id,prop=new ServerProp(Server)
{
ID=id,
Model=model,
Position=pos,
Rotation=rot
});
return prop;
}
2022-07-02 17:14:56 +08:00
/// <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 ServerProp[] GetAllProps()
{
2022-07-02 17:14:56 +08:00
return ServerProps.Values.ToArray();
2022-07-02 12:39:50 +08:00
}
/// <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(() =>
2022-07-02 17:14:56 +08:00
Server.Logger?.Trace("Remaining entities: "+(Peds.Count+Vehicles.Count+ServerProps.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); }
}
2022-07-02 12:39:50 +08:00
internal void Add(ServerPed ped)
{
if (Peds.ContainsKey(ped.ID))
{
Peds[ped.ID]=ped;
}
else
{
Peds.Add(ped.ID, ped);
}
}
2022-07-02 17:14:56 +08:00
internal int RequestID()
{
int ID = 0;
while ((ID==0)
|| ServerProps.ContainsKey(ID)
|| Peds.ContainsKey(ID)
|| Vehicles.ContainsKey(ID))
{
byte[] rngBytes = new byte[4];
RandomNumberGenerator.Create().GetBytes(rngBytes);
// Convert the bytes into an integer
ID = BitConverter.ToInt32(rngBytes, 0);
}
return ID;
}
}
}