using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using GTA; using GTA.Native; using GTA.Math; using RageCoop.Core; using RageCoop.Core.Scripting; namespace RageCoop.Server { /// /// Server-side object controller /// public abstract class ServerObject { internal ServerObject() { } /// /// Pass this as an argument in CustomEvent or NativeCall to convert this object to handle at client side. /// public Tuple Handle { get { return new(GetTypeByte(), BitConverter.GetBytes(ID)); } } private byte GetTypeByte() { switch (this) { case ServerProp _: return 50; case ServerPed _: return 51; case ServerVehicle _: return 52; default: throw new NotImplementedException(); } } /// /// The client that owns this object, null if it's owned by server. /// public Client Owner { get; internal set; } /// /// Network ID of this object. /// public int ID { get; internal set; } /// /// The object's model /// public Model Model { get; internal set; } /// /// Gets or sets this object's position /// public virtual Vector3 Position { get { return _pos; } set { _pos=value; Update(); } } internal Vector3 _pos; /// /// Gets or sets this object's rotation /// public virtual Vector3 Rotation { get { return _rot; } set { _rot=value; Update(); } } internal Vector3 _rot; /// /// Send updated information to clients, would be called automatically. /// public virtual void Update() { Owner.SendCustomEvent(CustomEvents.SetEntity, Handle, Position, Rotation); } /// /// Delete this object /// public virtual void Delete() { Owner?.SendCustomEvent(CustomEvents.DeleteEntity, Handle); } /// /// Freeze this object, will throw an exception if it's a ServerProp. /// /// /// public virtual void Freeze(bool toggle) { if (GetTypeByte()==50) { throw new InvalidOperationException("Can't freeze or unfreeze static server object"); } else { Owner.SendNativeCall(Hash.FREEZE_ENTITY_POSITION, Handle, toggle); } } } /// /// Represents an prop owned by server. /// public class ServerProp : ServerObject { private Server Server; internal ServerProp(Server server) { Server= server; } /// /// Delete this prop /// public override void Delete() { Server.API.SendCustomEvent(CustomEvents.DeleteServerProp, new() { ID }); Server.Entities.RemoveProp(ID); } /// /// Send updated information to clients, would be called automatically. /// public override void Update() { Server.BaseScript.SendServerPropsTo(new() { this }); } } /// /// Represents a ped from a client /// public class ServerPed : ServerObject { internal ServerPed() { } /// /// Get the ped's last vehicle /// public ServerVehicle LastVehicle { get; internal set; } /// /// Health /// public int Health { get; internal set; } } /// /// Represents a vehicle from a client /// public class ServerVehicle : ServerObject { internal ServerVehicle() { } /// /// Gets or sets vehicle rotation /// public override Vector3 Rotation { get { return Quaternion.ToEulerAngles().ToDegree(); } set { Quaternion=value.ToQuaternion(); Update(); } } /// /// Get this vehicle's quaternion /// public Quaternion Quaternion { get; internal set; } } /// /// A static blip owned by server. /// public class ServerBlip { private readonly Server Server; internal ServerBlip(Server server) { Server = server; } /// /// Network ID (not handle!) /// public int ID { get; internal set; } internal BlipColor _color; /// /// Color of this blip /// public BlipColor Color { get { return _color; } set { _color=value; Update(); } } internal BlipSprite _sprite; /// /// Sprite of this blip /// public BlipSprite Sprite { get { return _sprite; } set { _sprite=value; Update();} } internal Vector2 _scale=new(1f,1f); /// /// Scale of this blip /// public Vector2 Scale { get { return _scale; } set { _scale=value;Update(); } } internal Vector3 _pos = new(); /// /// Position of this blip /// public Vector3 Position { get { return _pos; } set { _pos=value; Update(); } } internal int _rot; /// /// Scale of this blip /// public int Rotation { get { return _rot; } set { _rot=value; Update(); } } /// /// Delete this blip /// public void Delete() { Server.API.SendCustomEvent(CustomEvents.DeleteServerBlip, new() { ID }); Server.Entities.RemoveServerBlip(ID); } private bool _bouncing=false; internal void Update() { // 5ms debounce if (!_bouncing) { _bouncing=true; Task.Run(() => { Thread.Sleep(5); DoUpdate(); _bouncing=false; }); } } private void DoUpdate() { Server.Logger?.Debug("bee"); // Serve-side blip Server.BaseScript.SendServerBlipsTo(new() { this }); } } }