Files
RAGECOOP-V/Server/Scripting/ServerObject.cs

483 lines
10 KiB
C#
Raw Normal View History

2022-10-23 19:02:39 +08:00
using System;
using System.Threading;
using System.Threading.Tasks;
using GTA;
using GTA.Math;
2022-09-08 12:41:56 -07:00
using GTA.Native;
using RageCoop.Core;
using RageCoop.Core.Scripting;
2022-10-23 19:02:39 +08:00
namespace RageCoop.Server.Scripting;
2022-10-23 19:02:39 +08:00
/// <summary>
/// Server-side object controller
/// </summary>
public abstract class ServerObject
{
/// <summary>
2022-10-23 19:02:39 +08:00
/// Server that this object belongs to
/// </summary>
2022-10-23 19:02:39 +08:00
internal readonly Server Server;
internal Vector3 _pos;
internal Vector3 _rot;
internal ServerObject(Server server)
{
2022-10-23 19:02:39 +08:00
Server = server;
}
2022-09-08 12:41:56 -07:00
2022-10-23 19:02:39 +08:00
/// <summary>
/// Pass this as an argument in CustomEvent or NativeCall to convert this object to handle at client side.
/// </summary>
public Tuple<byte, byte[]> Handle => new Tuple<byte, byte[]>(GetTypeByte(), BitConverter.GetBytes(ID));
2022-10-23 19:02:39 +08:00
/// <summary>
/// The client that owns this object, null if it's owned by server.
/// </summary>
public Client Owner { get; internal set; }
2022-10-23 19:02:39 +08:00
/// <summary>
/// Network ID of this object.
/// </summary>
public int ID { get; internal set; }
2022-10-23 19:02:39 +08:00
/// <summary>
/// The object's model
/// </summary>
public Model Model { get; internal set; }
/// <summary>
/// Gets or sets this object's position
/// </summary>
public virtual Vector3 Position
{
get => _pos;
set
{
2022-10-23 19:02:39 +08:00
_pos = value;
Owner.SendNativeCall(Hash.SET_ENTITY_COORDS_NO_OFFSET, Handle, value.X, value.Y, value.Z, 1, 1, 1);
}
2022-10-23 19:02:39 +08:00
}
2022-10-23 19:02:39 +08:00
/// <summary>
/// Gets or sets this object's rotation
/// </summary>
public virtual Vector3 Rotation
{
get => _rot;
set
{
2022-10-23 19:02:39 +08:00
_rot = value;
Owner.SendNativeCall(Hash.SET_ENTITY_ROTATION, Handle, value.X, value.Y, value.Z, 2, 1);
}
2022-10-23 19:02:39 +08:00
}
2022-07-03 10:55:49 +08:00
2022-10-23 19:02:39 +08:00
private byte GetTypeByte()
{
switch (this)
2022-07-03 10:55:49 +08:00
{
2022-10-23 19:02:39 +08:00
case ServerProp _:
return 50;
case ServerPed _:
return 51;
case ServerVehicle _:
return 52;
default:
throw new NotImplementedException();
2022-07-03 10:55:49 +08:00
}
}
2022-10-23 19:02:39 +08:00
/// <summary>
/// Send updated information to clients, would be called automatically.
/// </summary>
/// <summary>
2022-10-23 19:02:39 +08:00
/// Delete this object
/// </summary>
2022-10-23 19:02:39 +08:00
public virtual void Delete()
{
2022-10-23 19:02:39 +08:00
Owner?.SendCustomEvent(CustomEventFlags.Queued, CustomEvents.DeleteEntity, Handle);
}
2022-10-23 19:02:39 +08:00
/// <summary>
/// Freeze this object, will throw an exception if it's a ServerProp.
/// </summary>
/// <param name="toggle"></param>
/// <exception cref="InvalidOperationException"></exception>
public virtual void Freeze(bool toggle)
{
if (GetTypeByte() == 50)
throw new InvalidOperationException("Can't freeze or unfreeze static server object");
Owner.SendNativeCall(Hash.FREEZE_ENTITY_POSITION, Handle, toggle);
}
}
2022-10-23 19:02:39 +08:00
/// <summary>
/// Represents an prop owned by server.
/// </summary>
public class ServerProp : ServerObject
{
internal ServerProp(Server server) : base(server)
{
}
2022-10-23 19:02:39 +08:00
/// <summary>
/// Gets or sets this object's position
/// </summary>
public override Vector3 Position
{
get => _pos;
set
{
2022-10-23 19:02:39 +08:00
_pos = value;
Server.API.SendNativeCall(null, Hash.SET_ENTITY_COORDS_NO_OFFSET, Handle, value.X, value.Y, value.Z, 1, 1,
1);
}
2022-10-23 19:02:39 +08:00
}
2022-10-23 19:02:39 +08:00
/// <summary>
/// Gets or sets this object's rotation
/// </summary>
public override Vector3 Rotation
{
get => _rot;
set
{
2022-10-23 19:02:39 +08:00
_rot = value;
Server.API.SendNativeCall(null, Hash.SET_ENTITY_ROTATION, Handle, value.X, value.Y, value.Z, 2, 1);
}
2022-10-23 19:02:39 +08:00
}
2022-10-23 19:02:39 +08:00
/// <summary>
/// Delete this prop
/// </summary>
public override void Delete()
{
Server.API.SendCustomEvent(CustomEventFlags.Queued, null, CustomEvents.DeleteServerProp, ID);
Server.API.Entities.RemoveProp(ID);
}
2022-07-03 10:55:49 +08:00
/// <summary>
2022-10-23 19:02:39 +08:00
/// Send updated information to clients, would be called automatically.
/// </summary>
2022-10-23 19:02:39 +08:00
internal void Update()
{
2022-10-23 19:02:39 +08:00
Server.API.Server.BaseScript.SendServerPropsTo(new List<ServerProp> { this });
}
}
2022-10-23 19:02:39 +08:00
/// <summary>
/// Represents a ped from a client
/// </summary>
public class ServerPed : ServerObject
{
internal bool _isInvincible;
2022-10-23 19:02:39 +08:00
internal ServerPed(Server server) : base(server)
{
}
2022-07-04 23:59:51 +08:00
2022-10-23 19:02:39 +08:00
/// <summary>
/// Get the ped's last vehicle
/// </summary>
public ServerVehicle LastVehicle { get; internal set; }
2022-07-04 23:59:51 +08:00
2022-10-23 19:02:39 +08:00
/// <summary>
/// Get the <see cref="PedBlip" /> attached to this ped.
/// </summary>
public PedBlip AttachedBlip { get; internal set; }
2022-08-22 00:23:46 +08:00
2022-10-23 19:02:39 +08:00
/// <summary>
/// Health
/// </summary>
public int Health { get; internal set; }
2022-08-22 00:23:46 +08:00
2022-10-23 19:02:39 +08:00
/// <summary>
/// Get or set whether this ped is invincible
/// </summary>
public bool IsInvincible
{
get => _isInvincible;
set => Owner.SendNativeCall(Hash.SET_ENTITY_INVINCIBLE, Handle, value);
}
2022-10-23 19:02:39 +08:00
/// <summary>
2022-10-23 19:02:39 +08:00
/// Attach a blip to this ped.
/// </summary>
2022-10-23 19:02:39 +08:00
/// <returns></returns>
public PedBlip AddBlip()
{
2022-10-23 19:02:39 +08:00
AttachedBlip = new PedBlip(this);
AttachedBlip.Update();
return AttachedBlip;
}
}
2022-10-23 19:02:39 +08:00
/// <summary>
/// Represents a vehicle from a client
/// </summary>
public class ServerVehicle : ServerObject
{
internal Quaternion _quat;
2022-10-23 19:02:39 +08:00
internal ServerVehicle(Server server) : base(server)
{
}
/// <summary>
/// Gets or sets vehicle rotation
/// </summary>
public override Vector3 Rotation
{
get => _quat.ToEulerAngles().ToDegree();
set => Owner.SendNativeCall(Hash.SET_ENTITY_ROTATION, Handle, value.X, value.Y, value.Z);
}
2022-07-03 15:28:28 +08:00
/// <summary>
2022-10-23 19:02:39 +08:00
/// Get this vehicle's quaternion
2022-07-03 15:28:28 +08:00
/// </summary>
2022-10-23 19:02:39 +08:00
public Quaternion Quaternion
{
2022-10-23 19:02:39 +08:00
get => _quat;
set
{
2022-10-23 19:02:39 +08:00
_quat = value;
Owner.SendNativeCall(Hash.SET_ENTITY_QUATERNION, Handle, value.X, value.Y, value.Z, value.W);
2022-07-03 15:28:28 +08:00
}
2022-10-23 19:02:39 +08:00
}
}
2022-07-03 15:28:28 +08:00
2022-10-23 19:02:39 +08:00
/// <summary>
/// A static blip owned by server.
/// </summary>
public class ServerBlip
{
private readonly Server Server;
2022-07-04 09:54:43 +08:00
2022-10-23 19:02:39 +08:00
private bool _bouncing;
2022-07-03 15:28:28 +08:00
2022-10-23 19:02:39 +08:00
internal BlipColor _color;
internal string _name = "Beeeeeee";
internal Vector3 _pos;
internal int _rot;
internal float _scale = 1;
2022-07-03 15:28:28 +08:00
2022-10-23 19:02:39 +08:00
internal BlipSprite _sprite = BlipSprite.Standard;
internal ServerBlip(Server server)
{
Server = server;
}
/// <summary>
/// Pass this as an argument in CustomEvent or NativeCall to convert this object to handle at client side.
/// </summary>
public Tuple<byte, byte[]> Handle => new Tuple<byte, byte[]>(60, BitConverter.GetBytes(ID));
/// <summary>
/// Network ID (not handle!)
/// </summary>
public int ID { get; internal set; }
/// <summary>
/// Color of this blip
/// </summary>
public BlipColor Color
{
get => _color;
set
2022-09-08 12:41:56 -07:00
{
2022-10-23 19:02:39 +08:00
_color = value;
Update();
2022-07-03 15:28:28 +08:00
}
2022-10-23 19:02:39 +08:00
}
2022-10-23 19:02:39 +08:00
/// <summary>
/// Sprite of this blip
/// </summary>
public BlipSprite Sprite
{
get => _sprite;
set
2022-07-03 15:28:28 +08:00
{
2022-10-23 19:02:39 +08:00
_sprite = value;
Update();
}
2022-10-23 19:02:39 +08:00
}
2022-10-23 19:02:39 +08:00
/// <summary>
/// Scale of this blip
/// </summary>
public float Scale
{
get => _scale;
set
2022-07-03 15:28:28 +08:00
{
2022-10-23 19:02:39 +08:00
_scale = value;
Update();
2022-07-03 15:28:28 +08:00
}
2022-10-23 19:02:39 +08:00
}
2022-07-03 15:28:28 +08:00
2022-10-23 19:02:39 +08:00
/// <summary>
/// Position of this blip
/// </summary>
public Vector3 Position
{
get => _pos;
set
2022-07-03 15:28:28 +08:00
{
2022-10-23 19:02:39 +08:00
_pos = value;
Update();
2022-07-03 15:28:28 +08:00
}
2022-10-23 19:02:39 +08:00
}
2022-07-03 15:28:28 +08:00
2022-10-23 19:02:39 +08:00
/// <summary>
/// Rotation of this blip
/// </summary>
public int Rotation
{
get => _rot;
set
{
2022-10-23 19:02:39 +08:00
_rot = value;
Update();
}
2022-10-23 19:02:39 +08:00
}
2022-10-23 19:02:39 +08:00
/// <summary>
/// Name of this blip
/// </summary>
public string Name
{
get => _name;
set
2022-07-03 15:28:28 +08:00
{
2022-10-23 19:02:39 +08:00
_name = value;
Update();
2022-07-03 15:28:28 +08:00
}
2022-10-23 19:02:39 +08:00
}
2022-07-03 15:28:28 +08:00
2022-10-23 19:02:39 +08:00
/// <summary>
/// Delete this blip
/// </summary>
public void Delete()
{
Server.API.SendCustomEvent(CustomEventFlags.Queued, null, CustomEvents.DeleteServerBlip, ID);
Server.Entities.RemoveServerBlip(ID);
}
2022-07-04 09:54:43 +08:00
2022-10-23 19:02:39 +08:00
internal void Update()
{
// 5ms debounce
if (!_bouncing)
2022-07-03 15:28:28 +08:00
{
2022-10-23 19:02:39 +08:00
_bouncing = true;
Task.Run(() =>
2022-07-03 15:28:28 +08:00
{
2022-10-23 19:02:39 +08:00
Thread.Sleep(5);
DoUpdate();
_bouncing = false;
});
2022-07-03 15:28:28 +08:00
}
2022-10-23 19:02:39 +08:00
}
2022-07-03 15:28:28 +08:00
2022-10-23 19:02:39 +08:00
private void DoUpdate()
{
// Server.Logger?.Debug("bee");
// Serve-side blip
Server.BaseScript.SendServerBlipsTo(new List<ServerBlip> { this });
}
2022-10-23 19:02:39 +08:00
}
2022-09-08 12:41:56 -07:00
2022-10-23 19:02:39 +08:00
/// <summary>
/// Represent a blip attached to ped.
/// </summary>
public class PedBlip
{
private bool _bouncing;
internal BlipColor _color;
internal float _scale = 1;
internal BlipSprite _sprite = BlipSprite.Standard;
internal PedBlip(ServerPed ped)
2022-07-04 23:59:51 +08:00
{
2022-10-23 19:02:39 +08:00
Ped = ped;
}
2022-07-04 23:59:51 +08:00
2022-10-23 19:02:39 +08:00
/// <summary>
/// Get the <see cref="ServerPed" /> that this blip attached to.
/// </summary>
public ServerPed Ped { get; internal set; }
2022-07-04 23:59:51 +08:00
2022-10-23 19:02:39 +08:00
/// <summary>
/// Color of this blip
/// </summary>
public BlipColor Color
{
get => _color;
set
2022-07-04 23:59:51 +08:00
{
2022-10-23 19:02:39 +08:00
_color = value;
Update();
2022-07-04 23:59:51 +08:00
}
2022-10-23 19:02:39 +08:00
}
2022-07-04 23:59:51 +08:00
2022-10-23 19:02:39 +08:00
/// <summary>
/// Sprite of this blip
/// </summary>
public BlipSprite Sprite
{
get => _sprite;
set
2022-07-04 23:59:51 +08:00
{
2022-10-23 19:02:39 +08:00
_sprite = value;
Update();
2022-07-04 23:59:51 +08:00
}
2022-10-23 19:02:39 +08:00
}
2022-07-04 23:59:51 +08:00
2022-10-23 19:02:39 +08:00
/// <summary>
/// Scale of this blip
/// </summary>
public float Scale
{
get => _scale;
set
2022-07-04 23:59:51 +08:00
{
2022-10-23 19:02:39 +08:00
_scale = value;
Update();
2022-07-04 23:59:51 +08:00
}
2022-10-23 19:02:39 +08:00
}
2022-07-04 23:59:51 +08:00
2022-10-23 19:02:39 +08:00
internal void Update()
{
// 5ms debounce
if (!_bouncing)
2022-07-04 23:59:51 +08:00
{
2022-10-23 19:02:39 +08:00
_bouncing = true;
Task.Run(() =>
2022-07-04 23:59:51 +08:00
{
2022-10-23 19:02:39 +08:00
Thread.Sleep(5);
DoUpdate();
_bouncing = false;
});
2022-07-04 23:59:51 +08:00
}
2022-10-23 19:02:39 +08:00
}
2022-09-08 12:41:56 -07:00
2022-10-23 19:02:39 +08:00
private void DoUpdate()
{
Ped.Owner.SendCustomEvent(CustomEventFlags.Queued, CustomEvents.UpdatePedBlip, Ped.Handle, (byte)Color,
(ushort)Sprite, Scale);
2022-07-04 23:59:51 +08:00
}
2022-10-23 19:02:39 +08:00
}