From 64922c77749f2d17884719ef883f60ebe030ad86 Mon Sep 17 00:00:00 2001 From: Tim Potze Date: Mon, 25 May 2026 22:44:10 +0200 Subject: [PATCH] Fix use-after-free bugs in components --- .../SAMP/Components/Actor.cs | 47 ++- .../SAMP/Components/BaseGangZone.cs | 33 +- .../SAMP/Components/BasePickup.cs | 33 +- .../SAMP/Components/Class.cs | 29 +- .../SAMP/Components/GangZone.cs | 33 +- .../SAMP/Components/GlobalObject.cs | 63 ++-- .../SAMP/Components/IdProvider.cs | 11 +- .../SAMP/Components/Menu.cs | 61 ++-- .../SAMP/Components/Npc.cs | 269 +++++++------- .../SAMP/Components/Pickup.cs | 23 +- .../SAMP/Components/Player.cs | 343 +++++++++--------- .../SAMP/Components/PlayerGangZone.cs | 28 +- .../SAMP/Components/PlayerObject.cs | 59 +-- .../SAMP/Components/PlayerPickup.cs | 19 +- .../SAMP/Components/PlayerTextDraw.cs | 101 +++--- .../SAMP/Components/PlayerTextLabel.cs | 47 ++- .../SAMP/Components/TextDraw.cs | 103 +++--- .../SAMP/Components/TextLabel.cs | 57 +-- .../SAMP/Components/Vehicle.cs | 162 +++++---- .../SAMP/Components/WorldEntity.cs | 25 +- .../Infrastructure/Startup.cs | 13 +- .../Infrastructure/XunitSystem.cs | 1 + .../ServerServiceTests.cs | 5 +- 23 files changed, 848 insertions(+), 717 deletions(-) diff --git a/src/SampSharp.OpenMp.Entities/SAMP/Components/Actor.cs b/src/SampSharp.OpenMp.Entities/SAMP/Components/Actor.cs index ffa7eeb0..308258cc 100644 --- a/src/SampSharp.OpenMp.Entities/SAMP/Components/Actor.cs +++ b/src/SampSharp.OpenMp.Entities/SAMP/Components/Actor.cs @@ -8,7 +8,6 @@ namespace SampSharp.Entities.SAMP; /// public class Actor : WorldEntity { - private readonly IActor _actor; private readonly IActorsComponent _actors; /// @@ -17,20 +16,24 @@ public class Actor : WorldEntity protected Actor(IActorsComponent actors, IActor actor) : base((IEntity)actor) { _actors = actors; - _actor = actor; + Resource = actor; } - /// - /// Gets a value indicating whether the open.mp entity counterpart has been destroyed. - /// - protected bool IsOmpEntityDestroyed => _actor.TryGetExtension()?.IsOmpEntityDestroyed ?? true; + private IActor Resource + { + get + { + ObjectDisposedException.ThrowIf(!IsComponentAlive, typeof(Actor)); + return field; + } + } /// /// Gets or sets the facing angle of this actor. /// public virtual float Angle { - get => float.RadiansToDegrees(MathHelper.GetZAngleFromRotationMatrix(Matrix4x4.CreateFromQuaternion(_actor.GetRotation()))); + get => float.RadiansToDegrees(MathHelper.GetZAngleFromRotationMatrix(Matrix4x4.CreateFromQuaternion(Resource.GetRotation()))); set => Rotation = Quaternion.CreateFromAxisAngle(GtaVector.Up, float.DegreesToRadians(value)); } @@ -39,8 +42,8 @@ public virtual float Angle /// public virtual int Skin { - get => _actor.GetSkin(); - set => _actor.SetSkin(value); + get => Resource.GetSkin(); + set => Resource.SetSkin(value); } /// @@ -48,8 +51,8 @@ public virtual int Skin /// public virtual float Health { - get => _actor.GetHealth(); - set => _actor.SetHealth(value); + get => Resource.GetHealth(); + set => Resource.SetHealth(value); } /// @@ -57,8 +60,8 @@ public virtual float Health /// public virtual bool IsInvulnerable { - get => _actor.IsInvulnerable(); - set => _actor.SetInvulnerable(value); + get => Resource.IsInvulnerable(); + set => Resource.SetInvulnerable(value); } /// @@ -70,7 +73,7 @@ public virtual bool IsStreamedIn(Player player) { ArgumentNullException.ThrowIfNull(player); - return _actor.IsStreamedInForPlayer(player); + return Resource.IsStreamedInForPlayer(player); } /// @@ -89,7 +92,7 @@ public virtual void ApplyAnimation(string library, string name, float fDelta, bo { ArgumentNullException.ThrowIfNull(library); ArgumentNullException.ThrowIfNull(name); - _actor.ApplyAnimation(new AnimationData(fDelta, loop, lockX, lockY, freeze, (uint)time.TotalMilliseconds, library, name)); + Resource.ApplyAnimation(new AnimationData(fDelta, loop, lockX, lockY, freeze, (uint)time.TotalMilliseconds, library, name)); } /// @@ -102,22 +105,26 @@ public virtual void ApplyAnimation(string library, string name, float fDelta, bo /// public virtual void ClearAnimations() { - _actor.ClearAnimations(); + Resource.ClearAnimations(); } /// protected override void OnDestroyComponent() { - if (!IsOmpEntityDestroyed) + if (!Resource.GetExtension().IsOmpEntityDestroyed) { - _actors.AsPool().Release(Id); + _actors.AsPool().Release(Resource.GetID()); } } /// public override string ToString() { - return $"(Id: {Id})"; + if (!IsComponentAlive) + { + return "(Destroyed)"; + } + return $"(Id: {Id}, Health: {Health}, Position: {Position})"; } /// @@ -125,6 +132,6 @@ public override string ToString() /// public static implicit operator IActor(Actor? actor) { - return actor?._actor ?? default; + return actor?.Resource ?? default; } } \ No newline at end of file diff --git a/src/SampSharp.OpenMp.Entities/SAMP/Components/BaseGangZone.cs b/src/SampSharp.OpenMp.Entities/SAMP/Components/BaseGangZone.cs index 8c74389c..85c4fd1e 100644 --- a/src/SampSharp.OpenMp.Entities/SAMP/Components/BaseGangZone.cs +++ b/src/SampSharp.OpenMp.Entities/SAMP/Components/BaseGangZone.cs @@ -10,7 +10,6 @@ namespace SampSharp.Entities.SAMP; public abstract class BaseGangZone : IdProvider { private readonly IOmpEntityProvider _entityProvider; - private readonly IGangZone _gangZone; private readonly IGangZonesComponent _gangZones; /// @@ -19,24 +18,28 @@ public abstract class BaseGangZone : IdProvider protected BaseGangZone(IOmpEntityProvider entityProvider, IGangZonesComponent gangZones, IGangZone gangZone) : base((IIDProvider)gangZone) { _entityProvider = entityProvider; - _gangZone = gangZone; + Resource = gangZone; _gangZones = gangZones; } - /// - /// Gets a value indicating whether the open.mp entity counterpart has been destroyed. - /// - protected bool IsOmpEntityDestroyed => _gangZone.TryGetExtension()?.IsOmpEntityDestroyed ?? true; + private IGangZone Resource + { + get + { + ObjectDisposedException.ThrowIf(!IsComponentAlive, typeof(BaseGangZone)); + return field; + } + } /// /// Gets the minimum position of this gang zone as a . /// - public virtual Vector2 Min => _gangZone.GetPosition().Min; + public virtual Vector2 Min => Resource.GetPosition().Min; /// /// Gets the maximum position of this gang zone as a . /// - public virtual Vector2 Max => _gangZone.GetPosition().Max; + public virtual Vector2 Max => Resource.GetPosition().Max; /// /// Gets the minimum x coordinate of this gang zone. @@ -69,7 +72,7 @@ protected BaseGangZone(IOmpEntityProvider entityProvider, IGangZonesComponent ga /// A lazy sequence of components. public virtual IEnumerable GetShownFor() { - foreach (var raw in _gangZone.GetShownFor()) + foreach (var raw in Resource.GetShownFor()) { var component = _entityProvider.GetComponent(raw); if (component != null) @@ -87,13 +90,13 @@ public virtual IEnumerable GetShownFor() public virtual void SetPosition(Vector2 min, Vector2 max) { var pos = new GangZonePos(min, max); - _gangZone.SetPosition(ref pos); + Resource.SetPosition(ref pos); } /// protected override void OnDestroyComponent() { - if (!IsOmpEntityDestroyed) + if (!Resource.GetExtension().IsOmpEntityDestroyed) { _gangZones.AsPool().Release(Id); } @@ -102,7 +105,11 @@ protected override void OnDestroyComponent() /// public override string ToString() { - return $"(Id: {Id}, Color: {Color})"; + if (!IsComponentAlive) + { + return "(Destroyed)"; + } + return $"(Id: {Id}, Color: {Color}, Min: {Min}, Max: {Max})"; } /// @@ -110,6 +117,6 @@ public override string ToString() /// public static implicit operator IGangZone(BaseGangZone? gangZone) { - return gangZone?._gangZone ?? default; + return gangZone?.Resource ?? default; } } \ No newline at end of file diff --git a/src/SampSharp.OpenMp.Entities/SAMP/Components/BasePickup.cs b/src/SampSharp.OpenMp.Entities/SAMP/Components/BasePickup.cs index 20d8bb3b..f02f52a7 100644 --- a/src/SampSharp.OpenMp.Entities/SAMP/Components/BasePickup.cs +++ b/src/SampSharp.OpenMp.Entities/SAMP/Components/BasePickup.cs @@ -9,7 +9,6 @@ namespace SampSharp.Entities.SAMP; /// public abstract class BasePickup : WorldEntity { - private readonly IPickup _pickup; private readonly IPickupsComponent _pickups; /// @@ -18,30 +17,34 @@ public abstract class BasePickup : WorldEntity protected BasePickup(IPickupsComponent pickups, IPickup pickup) : base((IEntity)pickup) { _pickups = pickups; - _pickup = pickup; + Resource = pickup; } - /// - /// Gets a value indicating whether the open.mp entity counterpart has been destroyed. - /// - protected bool IsOmpEntityDestroyed => _pickup.TryGetExtension()?.IsOmpEntityDestroyed ?? true; + private IPickup Resource + { + get + { + ObjectDisposedException.ThrowIf(!IsComponentAlive, typeof(BasePickup)); + return field; + } + } /// /// Gets the model of this pickup. /// - public virtual int Model => _pickup.GetModel(); + public virtual int Model => Resource.GetModel(); /// /// Gets the type of this pickup. /// - public virtual PickupType SpawnType => (PickupType)_pickup.GetPickupType(); + public virtual PickupType SpawnType => (PickupType)Resource.GetPickupType(); /// Changes the type of this pickup. /// The new . /// Whether to update the pickup visually for streamed-in players. public virtual void SetType(PickupType type, bool update = true) { - _pickup.SetType((byte)type, update); + Resource.SetType((byte)type, update); } /// Changes the model of this pickup. @@ -49,20 +52,20 @@ public virtual void SetType(PickupType type, bool update = true) /// Whether to update the pickup visually for streamed-in players. public virtual void SetModel(int model, bool update = true) { - _pickup.SetModel(model, update); + Resource.SetModel(model, update); } /// Sets the position of this pickup without sending a visual update. /// The new position. public virtual void SetPositionNoUpdate(Vector3 position) { - _pickup.SetPositionNoUpdate(position); + Resource.SetPositionNoUpdate(position); } /// protected override void OnDestroyComponent() { - if (!IsOmpEntityDestroyed) + if (!Resource.GetExtension().IsOmpEntityDestroyed) { _pickups.AsPool().Release(Id); } @@ -71,6 +74,10 @@ protected override void OnDestroyComponent() /// public override string ToString() { + if (!IsComponentAlive) + { + return "(Destroyed)"; + } return $"(Id: {Id}, Model: {Model})"; } @@ -79,6 +86,6 @@ public override string ToString() /// public static implicit operator IPickup(BasePickup? pickup) { - return pickup?._pickup ?? default; + return pickup?.Resource ?? default; } } \ No newline at end of file diff --git a/src/SampSharp.OpenMp.Entities/SAMP/Components/Class.cs b/src/SampSharp.OpenMp.Entities/SAMP/Components/Class.cs index 09c2250e..2f771687 100644 --- a/src/SampSharp.OpenMp.Entities/SAMP/Components/Class.cs +++ b/src/SampSharp.OpenMp.Entities/SAMP/Components/Class.cs @@ -8,7 +8,6 @@ namespace SampSharp.Entities.SAMP; /// public class Class : IdProvider { - private readonly IClass _class; private readonly IClassesComponent _classes; /// @@ -17,13 +16,17 @@ public class Class : IdProvider protected Class(IClassesComponent classes, IClass playerClass) : base((IIDProvider)playerClass) { _classes = classes; - _class = playerClass; + Resource = playerClass; } - /// - /// Gets a value indicating whether the open.mp entity counterpart has been destroyed. - /// - protected bool IsOmpEntityDestroyed => _class.TryGetExtension()?.IsOmpEntityDestroyed ?? true; + private IClass Resource + { + get + { + ObjectDisposedException.ThrowIf(!IsComponentAlive, typeof(Class)); + return field; + } + } /// /// Gets or sets the team ID for this player class. @@ -59,7 +62,7 @@ public virtual void SetSpawnData(PlayerSpawnData data) ArgumentNullException.ThrowIfNull(data); var omp = data.ToOmpData(); - _class.SetClass(ref omp); + Resource.SetClass(ref omp); } /// @@ -68,22 +71,26 @@ public virtual void SetSpawnData(PlayerSpawnData data) /// A instance containing the player's spawn information. public virtual PlayerSpawnData GetSpawnData() { - ref var dat = ref _class.GetClass(); + ref var dat = ref Resource.GetClass(); return PlayerSpawnData.FromOmpData(ref dat); } /// protected override void OnDestroyComponent() { - if (!IsOmpEntityDestroyed) + if (!Resource.GetExtension().IsOmpEntityDestroyed) { - _classes.AsPool().Release(Id); + _classes.AsPool().Release(Resource.GetID()); } } /// public override string ToString() { + if (!IsComponentAlive) + { + return "(Destroyed)"; + } return $"(Id: {Id})"; } @@ -92,6 +99,6 @@ public override string ToString() /// public static implicit operator IClass(Class? playerClass) { - return playerClass?._class ?? default; + return playerClass?.Resource ?? default; } } \ No newline at end of file diff --git a/src/SampSharp.OpenMp.Entities/SAMP/Components/GangZone.cs b/src/SampSharp.OpenMp.Entities/SAMP/Components/GangZone.cs index f173b06c..d5c96446 100644 --- a/src/SampSharp.OpenMp.Entities/SAMP/Components/GangZone.cs +++ b/src/SampSharp.OpenMp.Entities/SAMP/Components/GangZone.cs @@ -9,15 +9,22 @@ namespace SampSharp.Entities.SAMP; /// public class GangZone : BaseGangZone { - private readonly IGangZone _gangZone; - /// /// Initializes a new instance of the class. /// protected GangZone(IOmpEntityProvider entityProvider, IGangZonesComponent gangZones, IGangZone gangZone) : base(entityProvider, gangZones, gangZone) { - _gangZone = gangZone; + Resource = gangZone; + } + + private IGangZone Resource + { + get + { + ObjectDisposedException.ThrowIf(!IsComponentAlive, typeof(GangZone)); + return field; + } } /// @@ -41,7 +48,7 @@ public virtual void Show(Player player, Color color) ArgumentNullException.ThrowIfNull(player); Colour clr = color; - _gangZone.ShowForPlayer(player, ref clr); + Resource.ShowForPlayer(player, ref clr); } /// @@ -53,7 +60,7 @@ public virtual void Show(Player player) ArgumentNullException.ThrowIfNull(player); Colour clr = Color; - _gangZone.ShowForPlayer(player, ref clr); + Resource.ShowForPlayer(player, ref clr); } /// @@ -75,7 +82,7 @@ public virtual void Hide(Player player) { ArgumentNullException.ThrowIfNull(player); - _gangZone.HideForPlayer(player); + Resource.HideForPlayer(player); } /// @@ -100,7 +107,7 @@ public virtual void Flash(Player player, Color color) ArgumentNullException.ThrowIfNull(player); Colour clr = color; - _gangZone.FlashForPlayer(player, ref clr); + Resource.FlashForPlayer(player, ref clr); } /// @@ -121,7 +128,7 @@ public virtual void StopFlash() public virtual void StopFlash(Player player) { ArgumentNullException.ThrowIfNull(player); - _gangZone.StopFlashForPlayer(player); + Resource.StopFlashForPlayer(player); } /// @@ -132,7 +139,7 @@ public virtual void StopFlash(Player player) public virtual bool IsShownForPlayer(Player player) { ArgumentNullException.ThrowIfNull(player); - return _gangZone.IsShownForPlayer(player); + return Resource.IsShownForPlayer(player); } /// @@ -143,7 +150,7 @@ public virtual bool IsShownForPlayer(Player player) public virtual bool IsFlashingForPlayer(Player player) { ArgumentNullException.ThrowIfNull(player); - return _gangZone.IsFlashingForPlayer(player); + return Resource.IsFlashingForPlayer(player); } /// @@ -154,7 +161,7 @@ public virtual bool IsFlashingForPlayer(Player player) public virtual Color GetColorForPlayer(Player player) { ArgumentNullException.ThrowIfNull(player); - return _gangZone.GetColourForPlayer(player); + return Resource.GetColourForPlayer(player); } /// @@ -165,7 +172,7 @@ public virtual Color GetColorForPlayer(Player player) public virtual Color GetFlashingColorForPlayer(Player player) { ArgumentNullException.ThrowIfNull(player); - return _gangZone.GetFlashingColourForPlayer(player); + return Resource.GetFlashingColourForPlayer(player); } /// @@ -180,6 +187,6 @@ public virtual Color GetFlashingColorForPlayer(Player player) public virtual bool IsPlayerInside(Player player) { ArgumentNullException.ThrowIfNull(player); - return _gangZone.IsPlayerInside(player); + return Resource.IsPlayerInside(player); } } diff --git a/src/SampSharp.OpenMp.Entities/SAMP/Components/GlobalObject.cs b/src/SampSharp.OpenMp.Entities/SAMP/Components/GlobalObject.cs index 6bb47dec..f26c29a8 100644 --- a/src/SampSharp.OpenMp.Entities/SAMP/Components/GlobalObject.cs +++ b/src/SampSharp.OpenMp.Entities/SAMP/Components/GlobalObject.cs @@ -9,7 +9,6 @@ namespace SampSharp.Entities.SAMP; public class GlobalObject : WorldEntity { private readonly IOmpEntityProvider _entityProvider; - private readonly IObject _object; private readonly IObjectsComponent _objects; /// @@ -19,36 +18,40 @@ protected GlobalObject(IOmpEntityProvider entityProvider, IObjectsComponent obje { _entityProvider = entityProvider; _objects = objects; - _object = @object; + Resource = @object; } - /// - /// Gets a value indicating whether the open.mp entity counterpart has been destroyed. - /// - protected bool IsOmpEntityDestroyed => _object.TryGetExtension()?.IsOmpEntityDestroyed ?? true; + private IObject Resource + { + get + { + ObjectDisposedException.ThrowIf(!IsComponentAlive, typeof(GlobalObject)); + return field; + } + } /// /// Gets a value indicating whether this object is moving. /// - public virtual bool IsMoving => _object.IsMoving(); + public virtual bool IsMoving => Resource.IsMoving(); /// /// Gets the model ID of this object. /// - public virtual int ModelId => _object.GetModel(); + public virtual int ModelId => Resource.GetModel(); /// /// Gets the draw distance of this object. /// - public virtual float DrawDistance => _object.GetDrawDistance(); + public virtual float DrawDistance => Resource.GetDrawDistance(); /// /// Gets or sets a value indicating whether this global object collides with players' cameras. /// public virtual bool HasCameraCollision { - get => _object.GetCameraCollision(); - set => _object.SetCameraCollision(value); + get => Resource.GetCameraCollision(); + set => Resource.SetCameraCollision(value); } /// @@ -58,7 +61,7 @@ public virtual Player? AttachedPlayer { get { - var data = _object.GetAttachmentData(); + var data = Resource.GetAttachmentData(); return data.Type == AttachmentType.Player ? _entityProvider.GetPlayer(data.Id) : null; } } @@ -70,7 +73,7 @@ public virtual Vehicle? AttachedVehicle { get { - var data = _object.GetAttachmentData(); + var data = Resource.GetAttachmentData(); return data.Type == AttachmentType.Vehicle ? _entityProvider.GetVehicle(data.Id) : null; } } @@ -82,7 +85,7 @@ public virtual GlobalObject? AttachedObject { get { - var data = _object.GetAttachmentData(); + var data = Resource.GetAttachmentData(); return data.Type == AttachmentType.Object ? _entityProvider.GetObject(data.Id) : null; } } @@ -99,7 +102,7 @@ public virtual TimeSpan Move(Vector3 position, float speed, Vector3 rotation) var time = (position - Position).Length() / speed; var moveDat = new ObjectMoveData(position, rotation, speed); - _object.Move(ref moveDat); + Resource.Move(ref moveDat); return TimeSpan.FromSeconds((int)time); } @@ -120,7 +123,7 @@ public virtual TimeSpan Move(Vector3 position, float speed) /// public virtual void Stop() { - _object.Stop(); + Resource.Stop(); } /// @@ -136,7 +139,7 @@ public virtual void SetMaterial(int materialIndex, int modelId, string txdName, ArgumentNullException.ThrowIfNull(txdName); ArgumentNullException.ThrowIfNull(textureName); - _object.SetMaterial((uint)materialIndex, modelId, txdName, textureName, materialColor); + Resource.SetMaterial((uint)materialIndex, modelId, txdName, textureName, materialColor); } /// @@ -157,9 +160,9 @@ public virtual void SetMaterialText(int materialIndex, string text, ObjectMateri ArgumentNullException.ThrowIfNull(text); ArgumentNullException.ThrowIfNull(fontface); ArgumentOutOfRangeException.ThrowIfGreaterThan(text.Length, 2048, nameof(text)); - ArgumentOutOfRangeException.ThrowIfGreaterThan(fontSize, 255, nameof(fontSize)); + ArgumentOutOfRangeException.ThrowIfGreaterThan(fontSize, 255); - _object.SetMaterialText((uint)materialIndex, text, (OpenMp.Core.Api.ObjectMaterialSize)materialSize, fontface, fontSize, bold, foreColor, backColor, (OpenMp.Core.Api.ObjectMaterialTextAlign)textAlignment); + Resource.SetMaterialText((uint)materialIndex, text, (OpenMp.Core.Api.ObjectMaterialSize)materialSize, fontface, fontSize, bold, foreColor, backColor, (OpenMp.Core.Api.ObjectMaterialTextAlign)textAlignment); } /// @@ -167,7 +170,7 @@ public virtual void SetMaterialText(int materialIndex, string text, ObjectMateri /// public virtual void DisableCameraCollisions() { - _object.SetCameraCollision(false); + Resource.SetCameraCollision(false); } /// @@ -176,7 +179,7 @@ public virtual void DisableCameraCollisions() /// The describing the current move target. public virtual ObjectMoveData GetMovingData() { - return _object.GetMovingData(); + return Resource.GetMovingData(); } /// @@ -184,7 +187,7 @@ public virtual ObjectMoveData GetMovingData() /// public virtual void ResetAttachment() { - _object.ResetAttachment(); + Resource.ResetAttachment(); } /// @@ -194,7 +197,7 @@ public virtual void ResetAttachment() /// The material data, or if no material has been set in that slot. public virtual ObjectMaterialData? GetMaterialData(int materialIndex) { - return _object.GetMaterialData((uint)materialIndex, out var data) ? data : null; + return Resource.GetMaterialData((uint)materialIndex, out var data) ? data : null; } /// @@ -207,7 +210,7 @@ public virtual void AttachTo(Player target, Vector3 offset, Vector3 rotation) { ArgumentNullException.ThrowIfNull(target); - _object.AttachToPlayer(target, offset, rotation); + Resource.AttachToPlayer(target, offset, rotation); } /// @@ -220,7 +223,7 @@ public virtual void AttachTo(Vehicle target, Vector3 offset, Vector3 rotation) { ArgumentNullException.ThrowIfNull(target); - _object.AttachToVehicle(target, offset, rotation); + Resource.AttachToVehicle(target, offset, rotation); } /// @@ -234,13 +237,13 @@ public virtual void AttachTo(GlobalObject target, Vector3 offset, Vector3 rotati { ArgumentNullException.ThrowIfNull(target); - _object.AttachToObject(target, offset, rotation, syncRotation); + Resource.AttachToObject(target, offset, rotation, syncRotation); } /// protected override void OnDestroyComponent() { - if (!IsOmpEntityDestroyed) + if (!Resource.GetExtension().IsOmpEntityDestroyed) { _objects.AsPool().Release(Id); } @@ -249,6 +252,10 @@ protected override void OnDestroyComponent() /// public override string ToString() { + if (!IsComponentAlive) + { + return "(Destroyed)"; + } return $"(Id: {Id}, Model: {ModelId})"; } @@ -257,6 +264,6 @@ public override string ToString() /// public static implicit operator IObject(GlobalObject? @object) { - return @object?._object ?? default; + return @object?.Resource ?? default; } } \ No newline at end of file diff --git a/src/SampSharp.OpenMp.Entities/SAMP/Components/IdProvider.cs b/src/SampSharp.OpenMp.Entities/SAMP/Components/IdProvider.cs index cbeb6cd2..43747ee1 100644 --- a/src/SampSharp.OpenMp.Entities/SAMP/Components/IdProvider.cs +++ b/src/SampSharp.OpenMp.Entities/SAMP/Components/IdProvider.cs @@ -8,8 +8,17 @@ namespace SampSharp.Entities.SAMP; /// The open.mp id provider this component represents. public abstract class IdProvider(IIDProvider idProvider) : Component { + private IIDProvider Resource + { + get + { + ObjectDisposedException.ThrowIf(!IsComponentAlive, typeof(IdProvider)); + return field; + } + } = idProvider; + /// /// Gets the identifier of this component. /// - public virtual int Id => idProvider.GetID(); + public virtual int Id => Resource.GetID(); } \ No newline at end of file diff --git a/src/SampSharp.OpenMp.Entities/SAMP/Components/Menu.cs b/src/SampSharp.OpenMp.Entities/SAMP/Components/Menu.cs index c0faedf2..da0afaa2 100644 --- a/src/SampSharp.OpenMp.Entities/SAMP/Components/Menu.cs +++ b/src/SampSharp.OpenMp.Entities/SAMP/Components/Menu.cs @@ -8,7 +8,6 @@ namespace SampSharp.Entities.SAMP; /// public class Menu : IdProvider { - private readonly IMenu _menu; private readonly IMenusComponent _menus; /// @@ -17,14 +16,18 @@ public class Menu : IdProvider protected Menu(IMenusComponent menus, IMenu menu, string title) : base((IIDProvider)menu) { _menus = menus; - _menu = menu; + Resource = menu; Title = title; // no getter available in IMenu } - /// - /// Gets a value indicating whether the open.mp entity counterpart has been destroyed. - /// - protected bool IsOmpEntityDestroyed => _menu.TryGetExtension()?.IsOmpEntityDestroyed ?? true; + private IMenu Resource + { + get + { + ObjectDisposedException.ThrowIf(!IsComponentAlive, typeof(Menu)); + return field; + } + } /// /// Gets the title of this menu. @@ -34,30 +37,30 @@ protected Menu(IMenusComponent menus, IMenu menu, string title) : base((IIDProvi /// /// Gets the number of columns in this menu. /// - public virtual int Columns => _menu.GetColumnCount(); + public virtual int Columns => Resource.GetColumnCount(); /// /// Gets the position of this menu. /// - public virtual Vector2 Position => _menu.GetPosition(); + public virtual Vector2 Position => Resource.GetPosition(); /// /// Gets the width of the left column in this menu. /// - public virtual float Col0Width => _menu.GetColumnWidths().X; + public virtual float Col0Width => Resource.GetColumnWidths().X; /// /// Gets the width of the right column in this menu. /// - public virtual float Col1Width => _menu.GetColumnWidths().Y; + public virtual float Col1Width => Resource.GetColumnWidths().Y; /// /// Gets or sets the header text of the left column in this menu. /// public virtual string Col0Header { - get => _menu.GetColumnHeader(0) ?? string.Empty; - set => _menu.SetColumnHeader(value, 0); + get => Resource.GetColumnHeader(0) ?? string.Empty; + set => Resource.SetColumnHeader(value, 0); } /// @@ -65,24 +68,24 @@ public virtual string Col0Header /// public virtual string Col1Header { - get => _menu.GetColumnHeader(1) ?? string.Empty; - set => _menu.SetColumnHeader(value, 1); + get => Resource.GetColumnHeader(1) ?? string.Empty; + set => Resource.SetColumnHeader(value, 1); } /// /// Gets a value indicating whether this menu accepts input. /// - public virtual bool IsEnabled => _menu.IsEnabled(); + public virtual bool IsEnabled => Resource.IsEnabled(); /// /// Gets the number of rows in the left column of this menu. /// - public virtual int Col0RowCount => _menu.GetRowCount(0); + public virtual int Col0RowCount => Resource.GetRowCount(0); /// /// Gets the number of rows in the right column of this menu. /// - public virtual int Col1RowCount => _menu.GetRowCount(1); + public virtual int Col1RowCount => Resource.GetRowCount(1); /// /// Adds an item to this menu. @@ -102,11 +105,11 @@ public virtual int AddItem(string col0Text, string? col1Text = null) throw new ArgumentNullException(nameof(col1Text), "The text for the right column may not be null because this menu has 2 columns."); } - var result = _menu.AddCell(col0Text, 0); + var result = Resource.AddCell(col0Text, 0); if (Columns == 2) { - _menu.AddCell(col1Text!, 1); + Resource.AddCell(col1Text!, 1); } return result; @@ -120,7 +123,7 @@ public virtual void Show(Player player) { ArgumentNullException.ThrowIfNull(player); - _menu.ShowForPlayer(player); + Resource.ShowForPlayer(player); } /// @@ -131,7 +134,7 @@ public virtual void Hide(Player player) { ArgumentNullException.ThrowIfNull(player); - _menu.HideForPlayer(player); + Resource.HideForPlayer(player); } /// @@ -139,7 +142,7 @@ public virtual void Hide(Player player) /// public virtual void Disable() { - _menu.Disable(); + Resource.Disable(); } /// @@ -148,7 +151,7 @@ public virtual void Disable() /// The index of the row to disable. public virtual void DisableRow(int row) { - _menu.DisableRow((byte)row); + Resource.DisableRow((byte)row); } /// @@ -158,7 +161,7 @@ public virtual void DisableRow(int row) /// if enabled; otherwise . public virtual bool IsRowEnabled(int row) { - return _menu.IsRowEnabled((byte)row); + return Resource.IsRowEnabled((byte)row); } /// @@ -169,13 +172,13 @@ public virtual bool IsRowEnabled(int row) /// The cell text, or if no cell exists at the given coordinates. public virtual string? GetCell(int row, int column) { - return _menu.GetCell((byte)column, (byte)row); + return Resource.GetCell((byte)column, (byte)row); } /// protected override void OnDestroyComponent() { - if (!IsOmpEntityDestroyed) + if (!Resource.GetExtension().IsOmpEntityDestroyed) { _menus.AsPool().Release(Id); } @@ -184,6 +187,10 @@ protected override void OnDestroyComponent() /// public override string ToString() { + if (!IsComponentAlive) + { + return "(Destroyed)"; + } return $"(Id: {Id}, Title: {Title})"; } @@ -192,6 +199,6 @@ public override string ToString() /// public static implicit operator IMenu(Menu? menu) { - return menu?._menu ?? default; + return menu?.Resource ?? default; } } \ No newline at end of file diff --git a/src/SampSharp.OpenMp.Entities/SAMP/Components/Npc.cs b/src/SampSharp.OpenMp.Entities/SAMP/Components/Npc.cs index 113f062e..9e904e7b 100644 --- a/src/SampSharp.OpenMp.Entities/SAMP/Components/Npc.cs +++ b/src/SampSharp.OpenMp.Entities/SAMP/Components/Npc.cs @@ -22,7 +22,6 @@ public class Npc : IdProvider { private const int DefaultPositionCheckUpdateDelayMs = 500; - private readonly INPC _npc; private readonly INPCComponent _npcs; /// @@ -31,26 +30,30 @@ public class Npc : IdProvider protected Npc(INPCComponent npcs, INPC npc) : base((IIDProvider)npc) { _npcs = npcs; - _npc = npc; + Resource = npc; } - /// - /// Gets a value indicating whether the open.mp entity counterpart has been destroyed. - /// - protected bool IsOmpEntityDestroyed => _npc.TryGetExtension()?.IsOmpEntityDestroyed ?? true; + private INPC Resource + { + get + { + ObjectDisposedException.ThrowIf(!IsComponentAlive, typeof(Npc)); + return field; + } + } /// /// Gets the underlying handle that this NPC drives. /// - public virtual IPlayer Player => _npc.GetPlayer(); + public virtual IPlayer Player => Resource.GetPlayer(); /// /// Gets or sets the NPC's position in the world as a . Use for the immediate-update overload. /// public virtual Vector3 Position { - get => _npc.GetPosition(); - set => _npc.SetPosition(value, false); + get => Resource.GetPosition(); + set => Resource.SetPosition(value, false); } /// @@ -58,8 +61,8 @@ public virtual Vector3 Position /// public virtual Quaternion Rotation { - get => _npc.GetRotation(); - set => _npc.SetRotation(value, false); + get => Resource.GetRotation(); + set => Resource.SetRotation(value, false); } /// @@ -67,8 +70,8 @@ public virtual Quaternion Rotation /// public virtual int VirtualWorld { - get => _npc.GetVirtualWorld(); - set => _npc.SetVirtualWorld(value); + get => Resource.GetVirtualWorld(); + set => Resource.SetVirtualWorld(value); } /// @@ -76,7 +79,7 @@ public virtual int VirtualWorld /// public virtual int Skin { - set => _npc.SetSkin(value); + set => Resource.SetSkin(value); } /// @@ -84,8 +87,8 @@ public virtual int Skin /// public virtual byte Weapon { - get => _npc.GetWeapon(); - set => _npc.SetWeapon(value); + get => Resource.GetWeapon(); + set => Resource.SetWeapon(value); } /// @@ -93,8 +96,8 @@ public virtual byte Weapon /// public virtual int Ammo { - get => _npc.GetAmmo(); - set => _npc.SetAmmo(value); + get => Resource.GetAmmo(); + set => Resource.SetAmmo(value); } /// @@ -102,8 +105,8 @@ public virtual int Ammo /// public virtual float Health { - get => _npc.GetHealth(); - set => _npc.SetHealth(value); + get => Resource.GetHealth(); + set => Resource.SetHealth(value); } /// @@ -111,8 +114,8 @@ public virtual float Health /// public virtual float Armour { - get => _npc.GetArmour(); - set => _npc.SetArmour(value); + get => Resource.GetArmour(); + set => Resource.SetArmour(value); } /// @@ -120,8 +123,8 @@ public virtual float Armour /// public virtual bool IsInvulnerable { - get => _npc.IsInvulnerable(); - set => _npc.SetInvulnerable(value); + get => Resource.IsInvulnerable(); + set => Resource.SetInvulnerable(value); } /// @@ -129,32 +132,32 @@ public virtual bool IsInvulnerable /// public virtual int Interior { - get => (int)_npc.GetInterior(); - set => _npc.SetInterior((uint)value); + get => (int)Resource.GetInterior(); + set => Resource.SetInterior((uint)value); } /// /// Gets a value indicating whether this NPC has been killed and not yet respawned. /// - public virtual bool IsDead => _npc.IsDead(); + public virtual bool IsDead => Resource.IsDead(); /// /// Gets a value indicating whether this NPC is currently executing any movement command. /// - public virtual bool IsMoving => _npc.IsMoving(); + public virtual bool IsMoving => Resource.IsMoving(); /// /// Gets the velocity of this NPC as a . /// - public virtual Vector3 Velocity => _npc.GetVelocity(); + public virtual Vector3 Velocity => Resource.GetVelocity(); /// /// Gets or sets the NPC's current weapon state. /// public virtual PlayerWeaponState WeaponState { - get => _npc.GetWeaponState(); - set => _npc.SetWeaponState(value); + get => Resource.GetWeaponState(); + set => Resource.SetWeaponState(value); } /// @@ -162,8 +165,8 @@ public virtual PlayerWeaponState WeaponState /// public virtual int AmmoInClip { - get => _npc.GetAmmoInClip(); - set => _npc.SetAmmoInClip(value); + get => Resource.GetAmmoInClip(); + set => Resource.SetAmmoInClip(value); } /// @@ -171,8 +174,8 @@ public virtual int AmmoInClip /// public virtual PlayerFightingStyle FightingStyle { - get => _npc.GetFightingStyle(); - set => _npc.SetFightingStyle(value); + get => Resource.GetFightingStyle(); + set => Resource.SetFightingStyle(value); } /// @@ -180,87 +183,87 @@ public virtual PlayerFightingStyle FightingStyle /// public virtual PlayerSpecialAction SpecialAction { - get => _npc.GetSpecialAction(); - set => _npc.SetSpecialAction(value); + get => Resource.GetSpecialAction(); + set => Resource.SetSpecialAction(value); } /// /// Gets a value indicating whether this NPC is currently shooting. /// - public virtual bool IsShooting => _npc.IsShooting(); + public virtual bool IsShooting => Resource.IsShooting(); /// /// Gets a value indicating whether this NPC is currently aiming. /// - public virtual bool IsAiming => _npc.IsAiming(); + public virtual bool IsAiming => Resource.IsAiming(); /// /// Gets a value indicating whether this NPC is currently performing a melee attack. /// - public virtual bool IsMeleeAttacking => _npc.IsMeleeAttacking(); + public virtual bool IsMeleeAttacking => Resource.IsMeleeAttacking(); /// /// Gets a value indicating whether weapon reloading is enabled for this NPC. /// - public virtual bool IsReloadEnabled => _npc.IsReloadEnabled(); + public virtual bool IsReloadEnabled => Resource.IsReloadEnabled(); /// /// Gets a value indicating whether this NPC is currently reloading. /// - public virtual bool IsReloading => _npc.IsReloading(); + public virtual bool IsReloading => Resource.IsReloading(); /// /// Gets a value indicating whether infinite ammo is enabled for this NPC. /// - public virtual bool IsInfiniteAmmoEnabled => _npc.IsInfiniteAmmoEnabled(); + public virtual bool IsInfiniteAmmoEnabled => Resource.IsInfiniteAmmoEnabled(); /// /// Gets a value indicating whether this NPC is currently moving along a path. /// - public virtual bool IsMovingByPath => _npc.IsMovingByPath(); + public virtual bool IsMovingByPath => Resource.IsMovingByPath(); /// /// Gets a value indicating whether path-based movement is currently paused. /// - public virtual bool IsPathPaused => _npc.IsPathPaused(); + public virtual bool IsPathPaused => Resource.IsPathPaused(); /// /// Gets the ID of the path this NPC is currently following, or -1 if none. /// - public virtual int CurrentPathId => _npc.GetCurrentPathId(); + public virtual int CurrentPathId => Resource.GetCurrentPathId(); /// /// Gets the index of the current waypoint within the active path. /// - public virtual int CurrentPathPointIndex => _npc.GetCurrentPathPointIndex(); + public virtual int CurrentPathPointIndex => Resource.GetCurrentPathPointIndex(); /// /// Gets the vehicle this NPC is currently in, or a handle with no value if not in a vehicle. /// - public virtual IVehicle Vehicle => _npc.GetVehicle(); + public virtual IVehicle Vehicle => Resource.GetVehicle(); /// /// Gets the seat index this NPC occupies in the current vehicle. /// - public virtual int VehicleSeat => _npc.GetVehicleSeat(); + public virtual int VehicleSeat => Resource.GetVehicleSeat(); /// /// Gets the vehicle the NPC is in the process of entering, or a handle with no value if not entering one. /// - public virtual IVehicle EnteringVehicle => _npc.GetEnteringVehicle(); + public virtual IVehicle EnteringVehicle => Resource.GetEnteringVehicle(); /// /// Gets the seat index the NPC is targeting while entering a vehicle. /// - public virtual int EnteringVehicleSeat => _npc.GetEnteringVehicleSeat(); + public virtual int EnteringVehicleSeat => Resource.GetEnteringVehicleSeat(); /// /// Gets or sets a value indicating whether the siren on this NPC's vehicle is active. /// public virtual bool IsVehicleSirenUsed { - get => _npc.IsVehicleSirenUsed(); - set => _npc.UseVehicleSiren(value); + get => Resource.IsVehicleSirenUsed(); + set => Resource.UseVehicleSiren(value); } /// @@ -268,8 +271,8 @@ public virtual bool IsVehicleSirenUsed /// public virtual float VehicleHealth { - get => _npc.GetVehicleHealth(); - set => _npc.SetVehicleHealth(value); + get => Resource.GetVehicleHealth(); + set => Resource.SetVehicleHealth(value); } /// @@ -277,8 +280,8 @@ public virtual float VehicleHealth /// public virtual int VehicleHydraThrusters { - get => _npc.GetVehicleHydraThrusters(); - set => _npc.SetVehicleHydraThrusters(value); + get => Resource.GetVehicleHydraThrusters(); + set => Resource.SetVehicleHydraThrusters(value); } /// @@ -286,8 +289,8 @@ public virtual int VehicleHydraThrusters /// public virtual int VehicleGearState { - get => _npc.GetVehicleGearState(); - set => _npc.SetVehicleGearState(value); + get => Resource.GetVehicleGearState(); + set => Resource.SetVehicleGearState(value); } /// @@ -295,52 +298,52 @@ public virtual int VehicleGearState /// public virtual float VehicleTrainSpeed { - get => _npc.GetVehicleTrainSpeed(); - set => _npc.SetVehicleTrainSpeed(value); + get => Resource.GetVehicleTrainSpeed(); + set => Resource.SetVehicleTrainSpeed(value); } /// /// Gets a value indicating whether this NPC is currently playing a recording. /// - public virtual bool IsPlayingPlayback => _npc.IsPlayingPlayback(); + public virtual bool IsPlayingPlayback => Resource.IsPlayingPlayback(); /// /// Gets a value indicating whether playback is currently paused. /// - public virtual bool IsPlaybackPaused => _npc.IsPlaybackPaused(); + public virtual bool IsPlaybackPaused => Resource.IsPlaybackPaused(); /// /// Gets a value indicating whether this NPC is currently following a node path. /// - public virtual bool IsPlayingNode => _npc.IsPlayingNode(); + public virtual bool IsPlayingNode => Resource.IsPlayingNode(); /// /// Gets a value indicating whether node-based movement is currently paused. /// - public virtual bool IsPlayingNodePaused => _npc.IsPlayingNodePaused(); + public virtual bool IsPlayingNodePaused => Resource.IsPlayingNodePaused(); /// /// Gets the world position this NPC is currently moving to. /// - public virtual Vector3 PositionMovingTo => _npc.GetPositionMovingTo(); + public virtual Vector3 PositionMovingTo => Resource.GetPositionMovingTo(); /// /// Gets the player this NPC is currently aiming at, or a handle with no value if not aiming at any player. /// - public virtual IPlayer PlayerAimingAt => _npc.GetPlayerAimingAt(); + public virtual IPlayer PlayerAimingAt => Resource.GetPlayerAimingAt(); /// /// Gets the player this NPC is currently moving towards, or a handle with no value if not following a player. /// - public virtual IPlayer PlayerMovingTo => _npc.GetPlayerMovingTo(); + public virtual IPlayer PlayerMovingTo => Resource.GetPlayerMovingTo(); /// /// Gets or sets the surfing data for this NPC. /// public virtual PlayerSurfingData SurfingData { - get => _npc.GetSurfingData(); - set => _npc.SetSurfingData(value); + get => Resource.GetSurfingData(); + set => Resource.SetSurfingData(value); } /// @@ -350,7 +353,7 @@ public virtual PlayerSurfingData SurfingData /// A value indicating whether to broadcast a sync to streamed-in players immediately instead of waiting for the next tick. public virtual void SetPosition(Vector3 position, bool immediateUpdate) { - _npc.SetPosition(position, immediateUpdate); + Resource.SetPosition(position, immediateUpdate); } /// @@ -360,7 +363,7 @@ public virtual void SetPosition(Vector3 position, bool immediateUpdate) /// A value indicating whether to broadcast a sync to streamed-in players immediately instead of waiting for the next tick. public virtual void SetRotation(Quaternion rotation, bool immediateUpdate) { - _npc.SetRotation(rotation, immediateUpdate); + Resource.SetRotation(rotation, immediateUpdate); } /// @@ -368,7 +371,7 @@ public virtual void SetRotation(Quaternion rotation, bool immediateUpdate) /// public virtual void Spawn() { - _npc.Spawn(); + Resource.Spawn(); } /// @@ -376,7 +379,7 @@ public virtual void Spawn() /// public virtual void Respawn() { - _npc.Respawn(); + Resource.Respawn(); } /// @@ -389,7 +392,7 @@ public virtual void Respawn() /// if the movement command was successful; otherwise. public virtual bool MoveTo(Vector3 position, NPCMoveType moveType, float moveSpeed = -1f, float stopRange = 1.0f) { - return _npc.Move(position, moveType, moveSpeed, stopRange); + return Resource.Move(position, moveType, moveSpeed, stopRange); } /// @@ -406,7 +409,7 @@ public virtual bool MoveToPlayer(Player player, NPCMoveType moveType, float move TimeSpan posCheckUpdateDelay = default, bool autoRestart = false) { ArgumentNullException.ThrowIfNull(player); - return _npc.MoveToPlayer(player, moveType, moveSpeed, stopRange, + return Resource.MoveToPlayer(player, moveType, moveSpeed, stopRange, posCheckUpdateDelay == default ? new Milliseconds(DefaultPositionCheckUpdateDelayMs) : (Milliseconds)posCheckUpdateDelay, autoRestart); } @@ -416,7 +419,7 @@ public virtual bool MoveToPlayer(Player player, NPCMoveType moveType, float move /// public virtual void StopMoving() { - _npc.StopMove(); + Resource.StopMove(); } /// @@ -435,7 +438,7 @@ public virtual void ApplyAnimation(string library, string name, float fDelta, bo { ArgumentNullException.ThrowIfNull(library); ArgumentNullException.ThrowIfNull(name); - _npc.ApplyAnimation(new AnimationData(fDelta, loop, lockX, lockY, freeze, + Resource.ApplyAnimation(new AnimationData(fDelta, loop, lockX, lockY, freeze, (uint)time.TotalMilliseconds, library, name)); } @@ -444,7 +447,7 @@ public virtual void ApplyAnimation(string library, string name, float fDelta, bo /// public virtual void ClearAnimations() { - _npc.ClearAnimations(); + Resource.ClearAnimations(); } /// @@ -452,7 +455,7 @@ public virtual void ClearAnimations() /// public virtual void ResetAnimation() { - _npc.ResetAnimation(); + Resource.ResetAnimation(); } /// @@ -460,7 +463,7 @@ public virtual void ResetAnimation() /// public virtual void SetAnimation(int animationId, float delta, bool loop, bool lockX, bool lockY, bool freeze, int time) { - _npc.SetAnimation(animationId, delta, loop, lockX, lockY, freeze, time); + Resource.SetAnimation(animationId, delta, loop, lockX, lockY, freeze, time); } /// @@ -468,7 +471,7 @@ public virtual void SetAnimation(int animationId, float delta, bool loop, bool l /// public virtual void GetAnimation(out int animationId, out float delta, out bool loop, out bool lockX, out bool lockY, out bool freeze, out int time) { - _npc.GetAnimation(out animationId, out delta, out loop, out lockX, out lockY, out freeze, out time); + Resource.GetAnimation(out animationId, out delta, out loop, out lockX, out lockY, out freeze, out time); } /// @@ -478,7 +481,7 @@ public virtual void GetAnimation(out int animationId, out float delta, out bool /// A value indicating whether to update immediately. public virtual void SetVelocity(Vector3 velocity, bool update = false) { - _npc.SetVelocity(velocity, update); + Resource.SetVelocity(velocity, update); } /// @@ -488,7 +491,7 @@ public virtual void SetVelocity(Vector3 velocity, bool update = false) /// if this NPC is streamed in for the player; otherwise. public virtual bool IsStreamedIn(Player player) { - return player != null && _npc.IsStreamedInForPlayer(player); + return player != null && Resource.IsStreamedInForPlayer(player); } /// @@ -496,7 +499,7 @@ public virtual bool IsStreamedIn(Player player) /// public virtual void SetWeaponSkillLevel(PlayerWeaponSkill weaponSkill, int level) { - _npc.SetWeaponSkillLevel(weaponSkill, level); + Resource.SetWeaponSkillLevel(weaponSkill, level); } /// @@ -504,7 +507,7 @@ public virtual void SetWeaponSkillLevel(PlayerWeaponSkill weaponSkill, int level /// public virtual int GetWeaponSkillLevel(PlayerWeaponSkill weaponSkill) { - return _npc.GetWeaponSkillLevel(weaponSkill); + return Resource.GetWeaponSkillLevel(weaponSkill); } /// @@ -512,7 +515,7 @@ public virtual int GetWeaponSkillLevel(PlayerWeaponSkill weaponSkill) /// public virtual void SetKeys(ushort upAndDown, ushort leftAndRight, ushort keys) { - _npc.SetKeys(upAndDown, leftAndRight, keys); + Resource.SetKeys(upAndDown, leftAndRight, keys); } /// @@ -520,7 +523,7 @@ public virtual void SetKeys(ushort upAndDown, ushort leftAndRight, ushort keys) /// public virtual void GetKeys(out ushort upAndDown, out ushort leftAndRight, out ushort keys) { - _npc.GetKeys(out upAndDown, out leftAndRight, out keys); + Resource.GetKeys(out upAndDown, out leftAndRight, out keys); } /// @@ -530,7 +533,7 @@ public virtual void GetKeys(out ushort upAndDown, out ushort leftAndRight, out u /// If , performs the secondary melee attack. public virtual void MeleeAttack(int time, bool secondaryMeleeAttack = false) { - _npc.MeleeAttack(time, secondaryMeleeAttack); + Resource.MeleeAttack(time, secondaryMeleeAttack); } /// @@ -538,7 +541,7 @@ public virtual void MeleeAttack(int time, bool secondaryMeleeAttack = false) /// public virtual void StopMeleeAttack() { - _npc.StopMeleeAttack(); + Resource.StopMeleeAttack(); } /// @@ -546,7 +549,7 @@ public virtual void StopMeleeAttack() /// public virtual void EnableReloading(bool toggle) { - _npc.EnableReloading(toggle); + Resource.EnableReloading(toggle); } /// @@ -554,7 +557,7 @@ public virtual void EnableReloading(bool toggle) /// public virtual void EnableInfiniteAmmo(bool enable) { - _npc.EnableInfiniteAmmo(enable); + Resource.EnableInfiniteAmmo(enable); } /// @@ -562,7 +565,7 @@ public virtual void EnableInfiniteAmmo(bool enable) /// public virtual void Shoot(int hitId, PlayerBulletHitType hitType, byte weapon, Vector3 endPoint, Vector3 offset, bool isHit, EntityCheckType betweenCheckFlags) { - _npc.Shoot(hitId, hitType, weapon, endPoint, offset, isHit, betweenCheckFlags); + Resource.Shoot(hitId, hitType, weapon, endPoint, offset, isHit, betweenCheckFlags); } /// @@ -570,7 +573,7 @@ public virtual void Shoot(int hitId, PlayerBulletHitType hitType, byte weapon, V /// public virtual void AimAt(Vector3 point, bool shoot, int shootDelay, bool setAngle, Vector3 offsetFrom, EntityCheckType betweenCheckFlags) { - _npc.AimAt(point, shoot, shootDelay, setAngle, offsetFrom, betweenCheckFlags); + Resource.AimAt(point, shoot, shootDelay, setAngle, offsetFrom, betweenCheckFlags); } /// @@ -579,7 +582,7 @@ public virtual void AimAt(Vector3 point, bool shoot, int shootDelay, bool setAng public virtual void AimAtPlayer(Player player, bool shoot, int shootDelay, bool setAngle, Vector3 offset, Vector3 offsetFrom, EntityCheckType betweenCheckFlags) { ArgumentNullException.ThrowIfNull(player); - _npc.AimAtPlayer(player, shoot, shootDelay, setAngle, offset, offsetFrom, betweenCheckFlags); + Resource.AimAtPlayer(player, shoot, shootDelay, setAngle, offset, offsetFrom, betweenCheckFlags); } /// @@ -587,7 +590,7 @@ public virtual void AimAtPlayer(Player player, bool shoot, int shootDelay, bool /// public virtual void StopAim() { - _npc.StopAim(); + Resource.StopAim(); } /// @@ -595,7 +598,7 @@ public virtual void StopAim() /// public virtual bool IsAimingAtPlayer(Player player) { - return player != null && _npc.IsAimingAtPlayer(player); + return player != null && Resource.IsAimingAtPlayer(player); } /// @@ -603,7 +606,7 @@ public virtual bool IsAimingAtPlayer(Player player) /// public virtual void SetWeaponAccuracy(byte weapon, float accuracy) { - _npc.SetWeaponAccuracy(weapon, accuracy); + Resource.SetWeaponAccuracy(weapon, accuracy); } /// @@ -611,7 +614,7 @@ public virtual void SetWeaponAccuracy(byte weapon, float accuracy) /// public virtual float GetWeaponAccuracy(byte weapon) { - return _npc.GetWeaponAccuracy(weapon); + return Resource.GetWeaponAccuracy(weapon); } /// @@ -619,7 +622,7 @@ public virtual float GetWeaponAccuracy(byte weapon) /// public virtual void SetWeaponReloadTime(byte weapon, int time) { - _npc.SetWeaponReloadTime(weapon, time); + Resource.SetWeaponReloadTime(weapon, time); } /// @@ -627,7 +630,7 @@ public virtual void SetWeaponReloadTime(byte weapon, int time) /// public virtual int GetWeaponReloadTime(byte weapon) { - return _npc.GetWeaponReloadTime(weapon); + return Resource.GetWeaponReloadTime(weapon); } /// @@ -635,7 +638,7 @@ public virtual int GetWeaponReloadTime(byte weapon) /// public virtual int GetWeaponActualReloadTime(byte weapon) { - return _npc.GetWeaponActualReloadTime(weapon); + return Resource.GetWeaponActualReloadTime(weapon); } /// @@ -643,7 +646,7 @@ public virtual int GetWeaponActualReloadTime(byte weapon) /// public virtual void SetWeaponShootTime(byte weapon, int time) { - _npc.SetWeaponShootTime(weapon, time); + Resource.SetWeaponShootTime(weapon, time); } /// @@ -651,7 +654,7 @@ public virtual void SetWeaponShootTime(byte weapon, int time) /// public virtual int GetWeaponShootTime(byte weapon) { - return _npc.GetWeaponShootTime(weapon); + return Resource.GetWeaponShootTime(weapon); } /// @@ -659,7 +662,7 @@ public virtual int GetWeaponShootTime(byte weapon) /// public virtual void SetWeaponClipSize(byte weapon, int size) { - _npc.SetWeaponClipSize(weapon, size); + Resource.SetWeaponClipSize(weapon, size); } /// @@ -667,7 +670,7 @@ public virtual void SetWeaponClipSize(byte weapon, int size) /// public virtual int GetWeaponClipSize(byte weapon) { - return _npc.GetWeaponClipSize(weapon); + return Resource.GetWeaponClipSize(weapon); } /// @@ -675,7 +678,7 @@ public virtual int GetWeaponClipSize(byte weapon) /// public virtual int GetWeaponActualClipSize(byte weapon) { - return _npc.GetWeaponActualClipSize(weapon); + return Resource.GetWeaponActualClipSize(weapon); } /// @@ -683,7 +686,7 @@ public virtual int GetWeaponActualClipSize(byte weapon) /// public virtual void EnterVehicle(IVehicle vehicle, byte seatId, NPCMoveType moveType) { - _npc.EnterVehicle(vehicle, seatId, moveType); + Resource.EnterVehicle(vehicle, seatId, moveType); } /// @@ -691,7 +694,7 @@ public virtual void EnterVehicle(IVehicle vehicle, byte seatId, NPCMoveType move /// public virtual void ExitVehicle() { - _npc.ExitVehicle(); + Resource.ExitVehicle(); } /// @@ -699,7 +702,7 @@ public virtual void ExitVehicle() /// public virtual bool PutInVehicle(IVehicle vehicle, byte seat) { - return _npc.PutInVehicle(vehicle, seat); + return Resource.PutInVehicle(vehicle, seat); } /// @@ -707,7 +710,7 @@ public virtual bool PutInVehicle(IVehicle vehicle, byte seat) /// public virtual bool RemoveFromVehicle() { - return _npc.RemoveFromVehicle(); + return Resource.RemoveFromVehicle(); } /// @@ -715,7 +718,7 @@ public virtual bool RemoveFromVehicle() /// public virtual bool MoveByPath(int pathId, NPCMoveType moveType = NPCMoveType.Auto, float moveSpeed = -1f, bool reverse = false) { - return _npc.MoveByPath(pathId, moveType, moveSpeed, reverse); + return Resource.MoveByPath(pathId, moveType, moveSpeed, reverse); } /// @@ -723,7 +726,7 @@ public virtual bool MoveByPath(int pathId, NPCMoveType moveType = NPCMoveType.Au /// public virtual void PausePath() { - _npc.PausePath(); + Resource.PausePath(); } /// @@ -731,7 +734,7 @@ public virtual void PausePath() /// public virtual void ResumePath() { - _npc.ResumePath(); + Resource.ResumePath(); } /// @@ -739,7 +742,7 @@ public virtual void ResumePath() /// public virtual void StopPath() { - _npc.StopPath(); + Resource.StopPath(); } /// @@ -752,7 +755,7 @@ public virtual void StopPath() public virtual bool StartPlayback(string recordName, bool autoUnload = true, Vector3 point = default, Quaternion rotation = default) { ArgumentNullException.ThrowIfNull(recordName); - return _npc.StartPlaybackByName(recordName, autoUnload, point, rotation); + return Resource.StartPlaybackByName(recordName, autoUnload, point, rotation); } /// @@ -764,7 +767,7 @@ public virtual bool StartPlayback(string recordName, bool autoUnload = true, Vec /// The starting rotation for playback. public virtual bool StartPlayback(int recordId, bool autoUnload = true, Vector3 point = default, Quaternion rotation = default) { - return _npc.StartPlaybackById(recordId, autoUnload, point, rotation); + return Resource.StartPlaybackById(recordId, autoUnload, point, rotation); } /// @@ -772,7 +775,7 @@ public virtual bool StartPlayback(int recordId, bool autoUnload = true, Vector3 /// public virtual void StopPlayback() { - _npc.StopPlayback(); + Resource.StopPlayback(); } /// @@ -780,7 +783,7 @@ public virtual void StopPlayback() /// public virtual void PausePlayback(bool paused = true) { - _npc.PausePlayback(paused); + Resource.PausePlayback(paused); } /// @@ -788,7 +791,7 @@ public virtual void PausePlayback(bool paused = true) /// public virtual bool PlayNode(int nodeId, NPCMoveType moveType = NPCMoveType.Auto, float moveSpeed = -1f, float radius = 0f, bool setAngle = true) { - return _npc.PlayNode(nodeId, moveType, moveSpeed, radius, setAngle); + return Resource.PlayNode(nodeId, moveType, moveSpeed, radius, setAngle); } /// @@ -796,7 +799,7 @@ public virtual bool PlayNode(int nodeId, NPCMoveType moveType = NPCMoveType.Auto /// public virtual void StopPlayingNode() { - _npc.StopPlayingNode(); + Resource.StopPlayingNode(); } /// @@ -804,7 +807,7 @@ public virtual void StopPlayingNode() /// public virtual void PausePlayingNode() { - _npc.PausePlayingNode(); + Resource.PausePlayingNode(); } /// @@ -812,7 +815,7 @@ public virtual void PausePlayingNode() /// public virtual void ResumePlayingNode() { - _npc.ResumePlayingNode(); + Resource.ResumePlayingNode(); } /// @@ -820,7 +823,7 @@ public virtual void ResumePlayingNode() /// public virtual ushort ChangeNode(int nodeId, ushort targetPointId) { - return _npc.ChangeNode(nodeId, targetPointId); + return Resource.ChangeNode(nodeId, targetPointId); } /// @@ -828,7 +831,7 @@ public virtual ushort ChangeNode(int nodeId, ushort targetPointId) /// public virtual bool UpdateNodePoint(ushort pointId) { - return _npc.UpdateNodePoint(pointId); + return Resource.UpdateNodePoint(pointId); } /// @@ -836,7 +839,7 @@ public virtual bool UpdateNodePoint(ushort pointId) /// public virtual void ResetSurfingData() { - _npc.ResetSurfingData(); + Resource.ResetSurfingData(); } /// @@ -844,7 +847,7 @@ public virtual void ResetSurfingData() /// public virtual bool IsMovingToPlayer(Player player) { - return player != null && _npc.IsMovingToPlayer(player); + return player != null && Resource.IsMovingToPlayer(player); } /// @@ -854,21 +857,25 @@ public virtual bool IsMovingToPlayer(Player player) /// The weapon used to kill the NPC. public virtual void Kill(Player? killer, byte weapon) { - _npc.Kill(killer != null ? (IPlayer)killer : default, weapon); + Resource.Kill(killer != null ? (IPlayer)killer : default, weapon); } /// protected override void OnDestroyComponent() { - if (!IsOmpEntityDestroyed && _npcs.HasValue) + if (!Resource.GetExtension().IsOmpEntityDestroyed) { - _npcs.Destroy(_npc); + _npcs.Destroy(Resource); } } /// public override string ToString() { + if (!IsComponentAlive) + { + return "(Destroyed)"; + } return $"(Id: {Id})"; } @@ -877,6 +884,6 @@ public override string ToString() /// public static implicit operator INPC(Npc? npc) { - return npc?._npc ?? default; + return npc?.Resource ?? default; } } diff --git a/src/SampSharp.OpenMp.Entities/SAMP/Components/Pickup.cs b/src/SampSharp.OpenMp.Entities/SAMP/Components/Pickup.cs index 0643635d..ab866891 100644 --- a/src/SampSharp.OpenMp.Entities/SAMP/Components/Pickup.cs +++ b/src/SampSharp.OpenMp.Entities/SAMP/Components/Pickup.cs @@ -8,14 +8,21 @@ namespace SampSharp.Entities.SAMP; /// public class Pickup : BasePickup { - private readonly IPickup _pickup; - /// /// Initializes a new instance of the class. /// protected Pickup(IPickupsComponent pickups, IPickup pickup) : base(pickups, pickup) { - _pickup = pickup; + Resource = pickup; + } + + private IPickup Resource + { + get + { + ObjectDisposedException.ThrowIf(!IsComponentAlive, typeof(Pickup)); + return field; + } } /// Checks whether this pickup is streamed in for the specified . @@ -24,7 +31,7 @@ protected Pickup(IPickupsComponent pickups, IPickup pickup) : base(pickups, pick public virtual bool IsStreamedInForPlayer(Player player) { ArgumentNullException.ThrowIfNull(player); - return _pickup.IsStreamedInForPlayer(player); + return Resource.IsStreamedInForPlayer(player); } /// Streams this pickup in for the specified . @@ -32,7 +39,7 @@ public virtual bool IsStreamedInForPlayer(Player player) public virtual void StreamInForPlayer(Player player) { ArgumentNullException.ThrowIfNull(player); - _pickup.StreamInForPlayer(player); + Resource.StreamInForPlayer(player); } /// Streams this pickup out for the specified . @@ -40,7 +47,7 @@ public virtual void StreamInForPlayer(Player player) public virtual void StreamOutForPlayer(Player player) { ArgumentNullException.ThrowIfNull(player); - _pickup.StreamOutForPlayer(player); + Resource.StreamOutForPlayer(player); } /// Hides or shows this pickup for the specified . @@ -49,7 +56,7 @@ public virtual void StreamOutForPlayer(Player player) public virtual void SetHiddenForPlayer(Player player, bool hidden) { ArgumentNullException.ThrowIfNull(player); - _pickup.SetPickupHiddenForPlayer(player, hidden); + Resource.SetPickupHiddenForPlayer(player, hidden); } /// Checks whether this pickup is hidden for the specified . @@ -58,6 +65,6 @@ public virtual void SetHiddenForPlayer(Player player, bool hidden) public virtual bool IsHiddenForPlayer(Player player) { ArgumentNullException.ThrowIfNull(player); - return _pickup.IsPickupHiddenForPlayer(player); + return Resource.IsPickupHiddenForPlayer(player); } } diff --git a/src/SampSharp.OpenMp.Entities/SAMP/Components/Player.cs b/src/SampSharp.OpenMp.Entities/SAMP/Components/Player.cs index 7dd45b9e..142adddc 100644 --- a/src/SampSharp.OpenMp.Entities/SAMP/Components/Player.cs +++ b/src/SampSharp.OpenMp.Entities/SAMP/Components/Player.cs @@ -13,7 +13,6 @@ public class Player : WorldEntity { private static readonly PlayerState[] _deadStates = [PlayerState.None, PlayerState.Spectating, PlayerState.Wasted]; private readonly IOmpEntityProvider _entityProvider; - private readonly IPlayer _rawPlayer; /// /// Constructs an instance of , should be used internally. @@ -21,26 +20,15 @@ public class Player : WorldEntity protected Player(IOmpEntityProvider entityProvider, IPlayer player) : base((IEntity)player) { _entityProvider = entityProvider; - _rawPlayer = player; + Resource = player; } - /// - /// Safe accessor for the underlying handle. Throws - /// if the component has been destroyed, - /// which means open.mp already fired - /// and the native pointer is (or is about to be) freed. Without this guard, - /// P/Invokes against a stale handle AV the process (0xC0000005) when gamemode - /// code holds onto a reference across disconnect (e.g. via - /// an async continuation). - /// - private IPlayer _player + private IPlayer Resource { get { - if (!IsComponentAlive) - throw new ObjectDisposedException(nameof(Player), - "Player has disconnected; native IPlayer handle is no longer valid."); - return _rawPlayer; + ObjectDisposedException.ThrowIf(!IsComponentAlive, typeof(Player)); + return field; } } @@ -48,7 +36,7 @@ private IPlayerCheckpointData CheckpointData { get { - var data = _player.QueryExtension(); + var data = Resource.QueryExtension(); if (data == null) { throw new InvalidOperationException("Missing checkpoint data"); @@ -62,7 +50,7 @@ private IPlayerVehicleData VehicleData { get { - var data = _player.QueryExtension(); + var data = Resource.QueryExtension(); if (data == null) { throw new InvalidOperationException("Missing vehicle data"); @@ -75,7 +63,7 @@ private IPlayerObjectData ObjectData { get { - var data = _player.QueryExtension(); + var data = Resource.QueryExtension(); if (data == null) { @@ -89,7 +77,7 @@ private IPlayerMenuData MenuData { get { - var data = _player.QueryExtension(); + var data = Resource.QueryExtension(); if (data == null) { @@ -103,7 +91,7 @@ private IPlayerConsoleData ConsoleData { get { - var data = _player.QueryExtension(); + var data = Resource.QueryExtension(); if (data == null) { @@ -117,7 +105,7 @@ private IPlayerTextDrawData TextDrawData { get { - var data = _player.QueryExtension(); + var data = Resource.QueryExtension(); if (data == null) { throw new InvalidOperationException("Missing text draw data"); @@ -130,7 +118,7 @@ private IPlayerClassData ClassData { get { - var data = _player.QueryExtension(); + var data = Resource.QueryExtension(); if (data == null) { throw new InvalidOperationException("Missing class data"); @@ -143,7 +131,7 @@ private IPlayerRecordingData RecordingData { get { - var data = _player.QueryExtension(); + var data = Resource.QueryExtension(); if (data == null) { throw new InvalidOperationException("Missing recording data"); @@ -152,17 +140,12 @@ private IPlayerRecordingData RecordingData } } - /// - /// Gets a value indicating whether the open.mp entity counterpart has been destroyed. - /// - protected bool IsOmpEntityDestroyed => _player.TryGetExtension()?.IsOmpEntityDestroyed ?? true; - /// /// Gets or sets the name of this player. /// public virtual string Name { - get => _player.GetName(); + get => Resource.GetName(); [Obsolete("Use SetName(string) instead")] set => SetName(value); } @@ -181,8 +164,8 @@ public virtual float Angle /// public virtual int Interior { - get => (int)_player.GetInterior(); - set => _player.SetInterior((uint)value); + get => (int)Resource.GetInterior(); + set => Resource.SetInterior((uint)value); } /// @@ -190,8 +173,8 @@ public virtual int Interior /// public virtual float Health { - get => _player.GetHealth(); - set => _player.SetHealth(value); + get => Resource.GetHealth(); + set => Resource.SetHealth(value); } /// @@ -199,24 +182,24 @@ public virtual float Health /// public virtual float Armour { - get => _player.GetArmour(); - set => _player.SetArmour(value); + get => Resource.GetArmour(); + set => Resource.SetArmour(value); } /// /// Gets the ammunition of the this player is currently holding. /// - public virtual int WeaponAmmo => _player.GetArmedWeaponAmmo(); + public virtual int WeaponAmmo => Resource.GetArmedWeaponAmmo(); /// /// Gets the of the this player is currently holding. /// - public virtual WeaponState WeaponState => (WeaponState)_player.GetAimData().weaponState; + public virtual WeaponState WeaponState => (WeaponState)Resource.GetAimData().weaponState; /// /// Gets the this player is currently holding. /// - public virtual Weapon Weapon => (Weapon)_player.GetArmedWeapon(); + public virtual Weapon Weapon => (Weapon)Resource.GetArmedWeapon(); /// /// Gets the this player is aiming at. @@ -225,7 +208,7 @@ public virtual Player? TargetPlayer { get { - var player = _player.GetTargetPlayer(); + var player = Resource.GetTargetPlayer(); if (!player.HasValue) { return null; @@ -239,8 +222,8 @@ public virtual Player? TargetPlayer /// public virtual int Team { - get => _player.GetTeam(); - set => _player.SetTeam(value); + get => Resource.GetTeam(); + set => Resource.SetTeam(value); } /// @@ -248,8 +231,8 @@ public virtual int Team /// public virtual int Score { - get => _player.GetScore(); - set => _player.SetScore(value); + get => Resource.GetScore(); + set => Resource.SetScore(value); } /// @@ -257,8 +240,8 @@ public virtual int Score /// public virtual int DrunkLevel { - get => _player.GetDrunkLevel(); - set => _player.SetDrunkLevel(value); + get => Resource.GetDrunkLevel(); + set => Resource.SetDrunkLevel(value); } /// @@ -266,8 +249,8 @@ public virtual int DrunkLevel /// public virtual Color Color { - get => _player.GetColour(); - set => _player.SetColour(value); + get => Resource.GetColour(); + set => Resource.SetColour(value); } /// @@ -275,8 +258,8 @@ public virtual Color Color /// public virtual int Skin { - get => _player.GetSkin(); - set => _player.SetSkin(value); + get => Resource.GetSkin(); + set => Resource.SetSkin(value); } /// @@ -284,14 +267,14 @@ public virtual int Skin /// public virtual int Money { - get => _player.GetMoney(); - set => _player.SetMoney(value); + get => Resource.GetMoney(); + set => Resource.SetMoney(value); } /// /// Gets the of this player. /// - public virtual PlayerState State => (PlayerState)_player.GetState(); + public virtual PlayerState State => (PlayerState)Resource.GetState(); /// /// Gets the IP of this player as a string. @@ -301,25 +284,25 @@ public virtual int Money /// /// Gets the of this player. /// - public virtual IPAddress IpAddress => _player.GetNetworkData().Value.PeerNetworkID.Address.ToAddress(); + public virtual IPAddress IpAddress => Resource.GetNetworkData().Value.PeerNetworkID.Address.ToAddress(); /// /// Gets the end point ( and port) of this player. /// - public virtual IPEndPoint EndPoint => _player.GetNetworkData().Value.PeerNetworkID.ToEndpoint(); + public virtual IPEndPoint EndPoint => Resource.GetNetworkData().Value.PeerNetworkID.ToEndpoint(); /// /// Gets the ping of this player. /// - public virtual int Ping => (int)_player.GetPing(); + public virtual int Ping => (int)Resource.GetPing(); /// /// Gets or sets the wanted level of this player. /// public virtual int WantedLevel { - get => (int)_player.GetWantedLevel(); - set => _player.SetWantedLevel((uint)value); + get => (int)Resource.GetWantedLevel(); + set => Resource.SetWantedLevel((uint)value); } /// @@ -327,8 +310,8 @@ public virtual int WantedLevel /// public virtual FightStyle FightStyle { - get => (FightStyle)_player.GetFightingStyle(); - set => _player.SetFightingStyle((PlayerFightingStyle)value); + get => (FightStyle)Resource.GetFightingStyle(); + set => Resource.SetFightingStyle((PlayerFightingStyle)value); } /// @@ -336,8 +319,8 @@ public virtual FightStyle FightStyle /// public virtual Vector3 Velocity { - get => _player.GetVelocity(); - set => _player.SetVelocity(value); + get => Resource.GetVelocity(); + set => Resource.SetVelocity(value); } /// @@ -362,15 +345,15 @@ public virtual int VehicleSeat /// /// Gets the animation index of the animation this player is currently playing. /// - public virtual int AnimationIndex => _player.GetAnimationData().ID; + public virtual int AnimationIndex => Resource.GetAnimationData().ID; /// /// Gets or sets the of this player. /// public virtual SpecialAction SpecialAction { - get => (SpecialAction)_player.GetAction(); - set => _player.SetAction((PlayerSpecialAction)value); + get => (SpecialAction)Resource.GetAction(); + set => Resource.SetAction((PlayerSpecialAction)value); } /// @@ -389,31 +372,31 @@ public virtual Vector3 CameraPosition { get { - var camPos = _player.GetAimData().camPos; - return camPos != Vector3.Zero ? camPos : _player.GetCameraPosition(); + var camPos = Resource.GetAimData().camPos; + return camPos != Vector3.Zero ? camPos : Resource.GetCameraPosition(); } - set => _player.SetCameraPosition(value); + set => Resource.SetCameraPosition(value); } /// /// Gets the front of this player's camera. /// - public virtual Vector3 CameraFrontVector => _player.GetAimData().camFrontVector; + public virtual Vector3 CameraFrontVector => Resource.GetAimData().camFrontVector; /// /// Gets the of this player's camera. /// - public virtual CameraMode CameraMode => (CameraMode)_player.GetAimData().camMode; + public virtual CameraMode CameraMode => (CameraMode)Resource.GetAimData().camMode; /// /// Gets the this player is aiming at. /// - public virtual Actor? TargetActor => _entityProvider.GetComponent(_player.GetTargetActor()); + public virtual Actor? TargetActor => _entityProvider.GetComponent(Resource.GetTargetActor()); /// /// Gets the the camera of this player is pointing at. /// - public virtual GlobalObject? CameraTargetGlobalObject => _entityProvider.GetComponent(_player.GetCameraTargetObject()); + public virtual GlobalObject? CameraTargetGlobalObject => _entityProvider.GetComponent(Resource.GetCameraTargetObject()); /// /// Gets the the camera of this player is pointing at. @@ -423,17 +406,17 @@ public virtual Vector3 CameraPosition /// /// Gets the the camera of this player is pointing at. /// - public virtual Vehicle? CameraTargetVehicle => _entityProvider.GetComponent(_player.GetCameraTargetVehicle()); + public virtual Vehicle? CameraTargetVehicle => _entityProvider.GetComponent(Resource.GetCameraTargetVehicle()); /// /// Gets the the camera of this player is pointing at. /// - public virtual Player? CameraTargetPlayer => _entityProvider.GetComponent(_player.GetCameraTargetPlayer()); + public virtual Player? CameraTargetPlayer => _entityProvider.GetComponent(Resource.GetCameraTargetPlayer()); /// /// Gets the the camera of this player is pointing at. /// - public virtual Actor? CameraTargetActor => _entityProvider.GetComponent(_player.GetCameraTargetActor()); + public virtual Actor? CameraTargetActor => _entityProvider.GetComponent(Resource.GetCameraTargetActor()); /// /// Gets the entity (, , object, or ) the camera of this player is pointing at. @@ -466,7 +449,7 @@ public virtual Component? SurfingEntity { get { - var surf = _player.GetSurfingData(); + var surf = Resource.GetSurfingData(); return surf.Type switch { PlayerSurfingData.SurfType.Vehicle => _entityProvider.GetVehicle(surf.ID), @@ -498,7 +481,7 @@ public virtual Menu? Menu /// /// Gets a value indicating whether this player is a bot (NPC). /// - public virtual bool IsNpc => _player.IsBot(); + public virtual bool IsNpc => Resource.IsBot(); /// /// Gets a value indicating whether this player is logged into RCON. @@ -513,7 +496,7 @@ public virtual Menu? Menu /// /// Gets this player's global computer identifier string. /// - public virtual string Gpci => _player.GetSerial(); + public virtual string Gpci => Resource.GetSerial(); /// /// Gets a value indicating whether this player is selecting a text draw. @@ -527,7 +510,7 @@ public virtual TimeSpan ConnectedTime { get { - var stats = _player.GetNetworkData().Value.Network.GetStatistics(); + var stats = Resource.GetNetworkData().Value.Network.GetStatistics(); return TimeSpan.FromMilliseconds(stats.ConnectionElapsedTime); } } @@ -539,7 +522,7 @@ public virtual int MessagesReceived { get { - var stats = _player.GetNetworkData().Value.Network.GetStatistics(); + var stats = Resource.GetNetworkData().Value.Network.GetStatistics(); return (int)stats.MessagesReceived; } } @@ -551,7 +534,7 @@ public virtual int MessagesReceivedPerSecond { get { - var stats = _player.GetNetworkData().Value.Network.GetStatistics(); + var stats = Resource.GetNetworkData().Value.Network.GetStatistics(); return (int)stats.MessagesReceivedPerSecond; } } @@ -563,7 +546,7 @@ public virtual int MessagesSent { get { - var stats = _player.GetNetworkData().Value.Network.GetStatistics(); + var stats = Resource.GetNetworkData().Value.Network.GetStatistics(); return (int)stats.MessagesSent; } } @@ -575,7 +558,7 @@ public virtual int BytesReceived { get { - var stats = _player.GetNetworkData().Value.Network.GetStatistics(); + var stats = Resource.GetNetworkData().Value.Network.GetStatistics(); return (int)stats.BytesReceived; } } @@ -587,7 +570,7 @@ public virtual int BytesSent { get { - var stats = _player.GetNetworkData().Value.Network.GetStatistics(); + var stats = Resource.GetNetworkData().Value.Network.GetStatistics(); return (int)stats.TotalBytesSent; } } @@ -599,7 +582,7 @@ public virtual ConnectionStatus ConnectionStatus { get { - var stats = _player.GetNetworkData().Value.Network.GetStatistics(); + var stats = Resource.GetNetworkData().Value.Network.GetStatistics(); return (ConnectionStatus)stats.ConnectMode; } } @@ -607,26 +590,26 @@ public virtual ConnectionStatus ConnectionStatus /// /// Gets the aspect ratio of this player's camera. /// - public virtual float AspectCameraRatio => _player.GetAimData().aspectRatio; + public virtual float AspectCameraRatio => Resource.GetAimData().aspectRatio; /// /// Gets the game camera zoom level for this player. /// - public virtual float CameraZoom => _player.GetAimData().camZoom; + public virtual float CameraZoom => Resource.GetAimData().camZoom; /// /// Gets or sets this player's gravity. /// public virtual float Gravity { - get => _player.GetGravity(); - set => _player.SetGravity(value); + get => Resource.GetGravity(); + set => Resource.SetGravity(value); } /// /// Gets a value indicating whether this player is using the official Rockstar/SA-MP client (as opposed to open.mp, mobile/PSP, or an unofficial fork). /// - public virtual bool IsUsingOfficialClient => _player.IsUsingOfficialClient(); + public virtual bool IsUsingOfficialClient => Resource.IsUsingOfficialClient(); /// /// Gets a value indicating whether this player is using the open.mp client. @@ -636,12 +619,12 @@ public virtual float Gravity /// /// Gets this player's . /// - public virtual ClientVersion ClientVersion => _player.GetClientVersion(); + public virtual ClientVersion ClientVersion => Resource.GetClientVersion(); /// /// Gets this player's client version name. /// - public virtual string ClientVersionName => _player.GetClientVersionName(); + public virtual string ClientVersionName => Resource.GetClientVersionName(); /// /// Gets or sets a value indicating whether ghost mode is enabled for this player. @@ -649,8 +632,8 @@ public virtual float Gravity /// When enabled, other players will pass through this player as if they were not there. public virtual bool IsGhostModeEnabled { - get => _player.IsGhostModeEnabled(); - set => _player.ToggleGhostMode(value); + get => Resource.IsGhostModeEnabled(); + set => Resource.ToggleGhostMode(value); } /// @@ -658,8 +641,8 @@ public virtual bool IsGhostModeEnabled /// public virtual bool AreWeaponsAllowed { - get => _player.AreWeaponsAllowed(); - set => _player.AllowWeapons(value); + get => Resource.AreWeaponsAllowed(); + set => Resource.AllowWeapons(value); } /// @@ -667,8 +650,8 @@ public virtual bool AreWeaponsAllowed /// public virtual bool IsTeleportAllowed { - get => _player.IsTeleportAllowed(); - set => _player.AllowTeleport(value); + get => Resource.IsTeleportAllowed(); + set => Resource.AllowTeleport(value); } /// @@ -676,8 +659,8 @@ public virtual bool IsTeleportAllowed /// public virtual Vector4 WorldBounds { - get => _player.GetWorldBounds(); - set => _player.SetWorldBounds(value); + get => Resource.GetWorldBounds(); + set => Resource.SetWorldBounds(value); } /// @@ -685,8 +668,8 @@ public virtual Vector4 WorldBounds /// public virtual bool HasWidescreen { - get => _player.HasWidescreen(); - set => _player.UseWidescreen(value); + get => Resource.HasWidescreen(); + set => Resource.UseWidescreen(value); } /// @@ -694,8 +677,8 @@ public virtual bool HasWidescreen /// public virtual int Weather { - get => _player.GetWeather(); - set => _player.SetWeather(value); + get => Resource.GetWeather(); + set => Resource.SetWeather(value); } /// @@ -705,7 +688,7 @@ public virtual IEnumerable StreamedForPlayers { get { - foreach (var raw in _player.StreamedForPlayers()) + foreach (var raw in Resource.StreamedForPlayers()) { var component = _entityProvider.GetComponent(raw); if (component != null) @@ -719,15 +702,15 @@ public virtual IEnumerable StreamedForPlayers /// /// Gets the number of default world objects that have been removed for this player. /// - public virtual int DefaultObjectsRemoved => _player.GetDefaultObjectsRemoved(); + public virtual int DefaultObjectsRemoved => Resource.GetDefaultObjectsRemoved(); /// /// Gets a value indicating whether this player is in the process of being kicked. /// - public virtual bool IsBeingKicked => _player.GetKickStatus(); + public virtual bool IsBeingKicked => Resource.GetKickStatus(); private IPlayerCustomModelsData? CustomModelsData => - _player.TryQueryExtension(out var data) ? data : null; + Resource.TryQueryExtension(out var data) ? data : null; /// /// Gets or sets the active custom skin model ID for this player, or if no custom skin is set. @@ -758,7 +741,7 @@ public virtual void SetName(string name) { ArgumentNullException.ThrowIfNull(name); - var result = _player.SetName(name); + var result = Resource.SetName(name); switch (result) { case EPlayerNameStatus.Invalid: @@ -822,13 +805,13 @@ public virtual PlayerSpawnData GetSpawnInfo() /// A object containing the player's network statistics. public NetworkStats GetNetworkStats() { - return new NetworkStats(_player.GetNetworkData().Value.Network.GetStatistics()); + return new NetworkStats(Resource.GetNetworkData().Value.Network.GetStatistics()); } /// (Re)Spawns a player. public virtual void Spawn() { - _player.Spawn(); + Resource.Spawn(); } /// @@ -836,7 +819,7 @@ public virtual void Spawn() /// public virtual void PutCameraBehindPlayer() { - _player.SetCameraBehind(); + Resource.SetCameraBehind(); } /// @@ -845,7 +828,7 @@ public virtual void PutCameraBehindPlayer() /// The position to move this player to as a . public virtual void SetPositionFindZ(Vector3 position) { - _player.SetPositionFindZ(position); + Resource.SetPositionFindZ(position); } /// @@ -879,7 +862,7 @@ public virtual float GetDistanceFromPoint(Vector3 point) public virtual bool IsPlayerStreamedIn(Player player) { ArgumentNullException.ThrowIfNull(player); - return _player.IsStreamedInForPlayer(player); + return Resource.IsStreamedInForPlayer(player); } /// @@ -889,7 +872,7 @@ public virtual bool IsPlayerStreamedIn(Player player) /// The amount of ammunition to set. public virtual void SetAmmo(Weapon weapon, int ammo) { - _player.SetWeaponAmmo(new WeaponSlotData((byte)weapon, ammo)); + Resource.SetWeaponAmmo(new WeaponSlotData((byte)weapon, ammo)); } /// @@ -899,7 +882,7 @@ public virtual void SetAmmo(Weapon weapon, int ammo) /// The amount of ammunition to give with the weapon. public virtual void GiveWeapon(Weapon weapon, int ammo) { - _player.GiveWeapon(new WeaponSlotData((byte)weapon, ammo)); + Resource.GiveWeapon(new WeaponSlotData((byte)weapon, ammo)); } @@ -908,7 +891,7 @@ public virtual void GiveWeapon(Weapon weapon, int ammo) /// public virtual void ResetWeapons() { - _player.ResetWeapons(); + Resource.ResetWeapons(); } /// @@ -917,7 +900,7 @@ public virtual void ResetWeapons() /// The weapon to remove. public virtual void RemoveWeapon(Weapon weapon) { - _player.RemoveWeapon((byte)weapon); + Resource.RemoveWeapon((byte)weapon); } /// @@ -926,7 +909,7 @@ public virtual void RemoveWeapon(Weapon weapon) /// The weapon that the player should be armed with. public virtual void SetArmedWeapon(Weapon weapon) { - _player.SetArmedWeapon((int)weapon); + Resource.SetArmedWeapon((int)weapon); } /// @@ -940,7 +923,7 @@ public virtual void GetWeaponData(int slot, out Weapon weapon, out int ammo) ArgumentOutOfRangeException.ThrowIfNegative(slot, nameof(slot)); ArgumentOutOfRangeException.ThrowIfGreaterThan(slot, 12, nameof(slot)); - var data = _player.GetWeaponSlot(slot); + var data = Resource.GetWeaponSlot(slot); weapon = (Weapon)data.Id; ammo = data.Ammo; } @@ -951,7 +934,7 @@ public virtual void GetWeaponData(int slot, out Weapon weapon, out int ammo) /// The amount of money to give. Use a negative value to take money. public virtual void GiveMoney(int money) { - _player.GiveMoney(money); + Resource.GiveMoney(money); } /// @@ -959,7 +942,7 @@ public virtual void GiveMoney(int money) /// public virtual void ResetMoney() { - _player.ResetMoney(); + Resource.ResetMoney(); } /// @@ -973,7 +956,7 @@ public virtual void ResetMoney() /// The left/right direction value, passed by reference. public virtual void GetKeys(out Keys keys, out int upDown, out int leftRight) { - var data = _player.GetKeyData(); + var data = Resource.GetKeyData(); keys = (Keys)data.keys; upDown = data.upDown; leftRight = data.leftRight; @@ -991,7 +974,7 @@ public virtual void SetTime(int hour, int minutes) ArgumentOutOfRangeException.ThrowIfNegative(minutes, nameof(minutes)); ArgumentOutOfRangeException.ThrowIfGreaterThan(minutes, 59, nameof(minutes)); - _player.SetTime(TimeSpan.FromHours(hour), TimeSpan.FromMinutes(minutes)); + Resource.SetTime(TimeSpan.FromHours(hour), TimeSpan.FromMinutes(minutes)); } /// @@ -1002,7 +985,7 @@ public virtual void SetTime(int hour, int minutes) /// The current , passed by reference. public virtual void GetTime(out int hour, out int minutes) { - (hour, minutes) = _player.GetTime(); + (hour, minutes) = Resource.GetTime(); } /// @@ -1012,7 +995,7 @@ public virtual void GetTime(out int hour, out int minutes) /// to show the clock; to hide it. public virtual void ToggleClock(bool toggle) { - _player.UseClock(toggle); + Resource.UseClock(toggle); } /// @@ -1031,7 +1014,7 @@ public virtual void SetWeather(int weather) /// The player will not return to class selection until they re-spawn. This can be achieved with public virtual void ForceClassSelection() { - _player.ForceClassSelection(); + Resource.ForceClassSelection(); } /// @@ -1060,7 +1043,7 @@ public virtual void CancelSelectTextDraw() public virtual bool PlayCrimeReport(Player suspect, int crime) { ArgumentNullException.ThrowIfNull(suspect); - return _player.PlayerCrimeReport(suspect, crime); + return Resource.PlayerCrimeReport(suspect, crime); } /// @@ -1072,7 +1055,7 @@ public virtual bool PlayCrimeReport(Player suspect, int crime) public virtual void PlayAudioStream(string url, Vector3 position, float distance) { ArgumentNullException.ThrowIfNull(url); - _player.PlayAudio(url, true, position, distance); + Resource.PlayAudio(url, true, position, distance); } /// @@ -1082,7 +1065,7 @@ public virtual void PlayAudioStream(string url, Vector3 position, float distance public virtual void PlayAudioStream(string url) { ArgumentNullException.ThrowIfNull(url); - _player.PlayAudio(url); + Resource.PlayAudio(url); } /// @@ -1091,7 +1074,7 @@ public virtual void PlayAudioStream(string url) /// If , collisions are disabled; if , they are enabled. public virtual void DisableRemoteVehicleCollisions(bool disable) { - _player.SetRemoteVehicleCollisions(!disable); + Resource.SetRemoteVehicleCollisions(!disable); } /// @@ -1100,7 +1083,7 @@ public virtual void DisableRemoteVehicleCollisions(bool disable) /// If , the functionality is enabled; if , it is disabled. public virtual void EnablePlayerCameraTarget(bool enable) { - _player.UseCameraTargeting(enable); + Resource.UseCameraTargeting(enable); } /// @@ -1108,7 +1091,7 @@ public virtual void EnablePlayerCameraTarget(bool enable) /// public virtual void StopAudioStream() { - _player.StopAudio(); + Resource.StopAudio(); } /// @@ -1118,7 +1101,7 @@ public virtual void StopAudioStream() public virtual void SetShopName(string shopName) { ArgumentNullException.ThrowIfNull(shopName); - _player.SetShopName(shopName); + Resource.SetShopName(shopName); } /// @@ -1129,7 +1112,7 @@ public virtual void SetShopName(string shopName) /// The skill level (0-999). Values outside this range will be clamped. public virtual void SetSkillLevel(WeaponSkill skill, int level) { - _player.SetSkillLevel((PlayerWeaponSkill)skill, level); + Resource.SetSkillLevel((PlayerWeaponSkill)skill, level); } /// @@ -1232,7 +1215,7 @@ public virtual void SetChatBubble(string text, Color color, float drawDistance, ArgumentNullException.ThrowIfNull(text); Colour clr = color; - _player.SetChatBubble(text, ref clr, drawDistance, expireTime); + Resource.SetChatBubble(text, ref clr, drawDistance, expireTime); } /// @@ -1244,7 +1227,7 @@ public virtual void PutInVehicle(Vehicle vehicle, int seatId) { ArgumentNullException.ThrowIfNull(vehicle); - ((IVehicle)vehicle).PutPlayer(_player, seatId); + ((IVehicle)vehicle).PutPlayer(Resource, seatId); } /// @@ -1268,7 +1251,7 @@ public virtual void PutInVehicle(Vehicle vehicle) /// public virtual void RemoveFromVehicle(bool force = false) { - _player.RemoveFromVehicle(force); + Resource.RemoveFromVehicle(force); } /// @@ -1277,7 +1260,7 @@ public virtual void RemoveFromVehicle(bool force = false) /// to unfreeze the player; to freeze them. public virtual void ToggleControllable(bool toggle) { - _player.SetControllable(toggle); + Resource.SetControllable(toggle); } /// @@ -1287,7 +1270,7 @@ public virtual void ToggleControllable(bool toggle) /// Point for the sound to play at as a . public virtual void PlaySound(int soundId, Vector3 point) { - _player.PlaySound(soundId, point); + Resource.PlaySound(soundId, point); } /// @@ -1296,7 +1279,7 @@ public virtual void PlaySound(int soundId, Vector3 point) /// The sound to play. public virtual void PlaySound(int soundId) { - _player.PlaySound(soundId, new Vector3()); + Resource.PlaySound(soundId, new Vector3()); } /// @@ -1324,7 +1307,7 @@ public virtual void ApplyAnimation(string animationLibrary, string animationName var anim = new AnimationData(fDelta, loop, lockX, lockY, freeze, (uint)time.TotalMilliseconds, animationLibrary, animationName); - _player.ApplyAnimation(anim, (OpenMp.Core.Api.PlayerAnimationSyncType)syncType); + Resource.ApplyAnimation(anim, (OpenMp.Core.Api.PlayerAnimationSyncType)syncType); } /// @@ -1364,7 +1347,7 @@ public virtual void ClearAnimations(bool forceSync) /// public virtual void ClearAnimations(PlayerAnimationSyncType syncType = PlayerAnimationSyncType.NoSync) { - _player.ClearAnimations((OpenMp.Core.Api.PlayerAnimationSyncType)syncType); + Resource.ClearAnimations((OpenMp.Core.Api.PlayerAnimationSyncType)syncType); } /// @@ -1375,7 +1358,7 @@ public virtual void ClearAnimations(PlayerAnimationSyncType syncType = PlayerAni /// on success; otherwise, . public virtual bool GetAnimationName(out string? animationLibrary, out string? animationName) { - var anim = _player.GetAnimationData(); + var anim = Resource.GetAnimationData(); var id = anim.ID; (animationLibrary, animationName) = Animation.GetAnimation(id); return true; @@ -1454,7 +1437,7 @@ public virtual void SetWorldBounds(float xMax, float xMin, float yMax, float yMi public virtual void SetPlayerMarker(Player player, Color color) { ArgumentNullException.ThrowIfNull(player); - _player.SetOtherColour(player, color); + Resource.SetOtherColour(player, color); } /// @@ -1468,7 +1451,7 @@ public virtual void SetPlayerMarker(Player player, Color color) public virtual void ShowNameTagForPlayer(Player player, bool show) { ArgumentNullException.ThrowIfNull(player); - _player.ToggleOtherNameTag(player, show); + Resource.ToggleOtherNameTag(player, show); } /// @@ -1478,7 +1461,7 @@ public virtual void ShowNameTagForPlayer(Player player, bool show) /// The transition style. public virtual void SetCameraLookAt(Vector3 point, CameraCut cut) { - _player.SetCameraLookAt(point, (int)cut); + Resource.SetCameraLookAt(point, (int)cut); } /// @@ -1499,7 +1482,7 @@ public virtual void SetCameraLookAt(Vector3 point) /// The transition style. Set to for smooth movement. public virtual void InterpolateCameraPosition(Vector3 from, Vector3 to, TimeSpan time, CameraCut cut) { - _player.InterpolateCameraPosition(from, to, (int)time.TotalMilliseconds, (PlayerCameraCutType)cut); + Resource.InterpolateCameraPosition(from, to, (int)time.TotalMilliseconds, (PlayerCameraCutType)cut); } /// @@ -1516,7 +1499,7 @@ public virtual void InterpolateCameraPosition(Vector3 from, Vector3 to, int time /// The transition style. Set to for smooth interpolation. public virtual void InterpolateCameraLookAt(Vector3 from, Vector3 to, TimeSpan time, CameraCut cut) { - _player.InterpolateCameraLookAt(from, to, (int)time.TotalMilliseconds, (PlayerCameraCutType)cut); + Resource.InterpolateCameraLookAt(from, to, (int)time.TotalMilliseconds, (PlayerCameraCutType)cut); } /// @@ -1540,7 +1523,7 @@ public virtual bool IsInVehicle(Vehicle vehicle) /// to enable stunt bonuses; to disable them. public virtual void EnableStuntBonus(bool enable) { - _player.UseStuntBonuses(enable); + Resource.UseStuntBonuses(enable); } /// @@ -1550,7 +1533,7 @@ public virtual void EnableStuntBonus(bool enable) /// to enable spectating; to disable. public virtual void ToggleSpectating(bool toggle) { - _player.SetSpectating(toggle); + Resource.SetSpectating(toggle); } /// @@ -1562,7 +1545,7 @@ public virtual void ToggleSpectating(bool toggle) public virtual void SpectatePlayer(Player targetPlayer, SpectateMode mode) { ArgumentNullException.ThrowIfNull(targetPlayer); - _player.SpectatePlayer(targetPlayer, (PlayerSpectateMode)mode); + Resource.SpectatePlayer(targetPlayer, (PlayerSpectateMode)mode); } /// @@ -1585,7 +1568,7 @@ public virtual void SpectatePlayer(Player targetPlayer) public virtual void SpectateVehicle(Vehicle targetVehicle, SpectateMode mode) { ArgumentNullException.ThrowIfNull(targetVehicle); - _player.SpectateVehicle(targetVehicle, (PlayerSpectateMode)mode); + Resource.SpectateVehicle(targetVehicle, (PlayerSpectateMode)mode); } /// @@ -1627,7 +1610,7 @@ public virtual void StopRecordingPlayerData() /// The bullet hit position as a , passed by reference. public virtual void GetLastShot(out Vector3 origin, out Vector3 hitPosition) { - var data = _player.GetBulletData(); + var data = Resource.GetBulletData(); origin = data.origin; hitPosition = data.hitPos; @@ -1648,12 +1631,12 @@ public virtual void SendClientMessage(Color color, string message) Colour clr = color; if (message.Length > 144) { - _player.SendClientMessage(ref clr, message[..144]); + Resource.SendClientMessage(ref clr, message[..144]); SendClientMessage(color, message[144..]); } else { - _player.SendClientMessage(ref clr, message); + Resource.SendClientMessage(ref clr, message); } } @@ -1703,7 +1686,7 @@ public virtual void SendClientMessage(string messageFormat, params object[] args /// public virtual void Kick() { - _player.Kick(); + Resource.Kick(); } /// @@ -1721,7 +1704,7 @@ public virtual void Ban() public virtual void Ban(string reason) { ArgumentNullException.ThrowIfNull(reason); - _player.Ban(reason); + Resource.Ban(reason); } /// @@ -1736,7 +1719,7 @@ public virtual void SendPlayerMessageToPlayer(Player sender, string message) { ArgumentNullException.ThrowIfNull(sender); ArgumentNullException.ThrowIfNull(message); - _player.SendChatMessage(sender, message); + Resource.SendChatMessage(sender, message); } /// @@ -1760,7 +1743,7 @@ public virtual void GameText(string text, int time, int style) public virtual void GameText(string text, TimeSpan time, GameTextStyle style) { ArgumentNullException.ThrowIfNull(text); - _player.SendGameText(text, time, (int)style); + Resource.SendGameText(text, time, (int)style); } /// @@ -1774,7 +1757,7 @@ public virtual void GameText(string text, TimeSpan time, GameTextStyle style) /// The explosion radius. public virtual void CreateExplosion(Vector3 position, ExplosionType type, float radius) { - _player.CreateExplosion(position, (int)type, radius); + Resource.CreateExplosion(position, (int)type, radius); } /// @@ -1787,7 +1770,7 @@ public virtual void SendDeathMessage(Player killer, Player player, Weapon weapon { ArgumentNullException.ThrowIfNull(killer); ArgumentNullException.ThrowIfNull(player); - _player.SendDeathMessage(player, killer, (int)weapon); + Resource.SendDeathMessage(player, killer, (int)weapon); } /// @@ -1797,7 +1780,7 @@ public virtual void SendDeathMessage(Player killer, Player player, Weapon weapon public virtual void AttachCameraToObject(GlobalObject @object) { ArgumentNullException.ThrowIfNull(@object); - _player.AttachCameraToObject(@object); + Resource.AttachCameraToObject(@object); } /// @@ -1807,7 +1790,7 @@ public virtual void AttachCameraToObject(GlobalObject @object) public virtual void AttachCameraToObject(PlayerObject @object) { ArgumentNullException.ThrowIfNull(@object); - _player.AttachCameraToObject(@object); + Resource.AttachCameraToObject(@object); } /// @@ -1855,7 +1838,7 @@ public virtual void Select() [Obsolete("Deprecated. Use 'RemoveDefaultObjects' instead.")] public virtual void RemoveBuilding(int modelId, Vector3 position, float radius) { - _player.RemoveDefaultObjects((uint)modelId, position, radius); + Resource.RemoveDefaultObjects((uint)modelId, position, radius); } /// @@ -1866,7 +1849,7 @@ public virtual void RemoveBuilding(int modelId, Vector3 position, float radius) /// The removal radius. public virtual void RemoveDefaultObjects(int modelId, Vector3 position, float radius) { - _player.RemoveDefaultObjects((uint)modelId, position, radius); + Resource.RemoveDefaultObjects((uint)modelId, position, radius); } /// @@ -1885,7 +1868,7 @@ public virtual void SetMapIcon(int iconId, Vector3 position, MapIcon type, Color ArgumentOutOfRangeException.ThrowIfNegative(iconId, nameof(iconId)); ArgumentOutOfRangeException.ThrowIfGreaterThan(iconId, 99, nameof(iconId)); - _player.SetMapIcon(iconId, position, (int)type, color, (MapIconStyle)style); + Resource.SetMapIcon(iconId, position, (int)type, color, (MapIconStyle)style); } /// @@ -1894,7 +1877,7 @@ public virtual void SetMapIcon(int iconId, Vector3 position, MapIcon type, Color /// The icon ID to remove. public virtual void RemoveMapIcon(int iconId) { - _player.UnsetMapIcon(iconId); + Resource.UnsetMapIcon(iconId); } /// @@ -1903,7 +1886,7 @@ public virtual void RemoveMapIcon(int iconId) /// The style/slot of the game text to hide. public virtual void HideGameText(int style) { - _player.HideGameText(style); + Resource.HideGameText(style); } /// @@ -1913,7 +1896,7 @@ public virtual void HideGameText(int style) /// if game text is displayed; otherwise . public virtual bool HasGameText(int style) { - return _player.HasGameText(style); + return Resource.HasGameText(style); } /// @@ -1926,7 +1909,7 @@ public virtual bool HasGameText(int style) /// if game text is currently shown; otherwise . public virtual bool GetGameText(int style, out string? message, out TimeSpan time, out TimeSpan remaining) { - return _player.GetGameText(style, out message, out time, out remaining); + return Resource.GetGameText(style, out message, out time, out remaining); } /// @@ -1941,7 +1924,7 @@ public virtual bool GetGameText(int style, out string? message, out TimeSpan tim /// public virtual void ClearTasks(PlayerAnimationSyncType syncType) { - _player.ClearTasks((OpenMp.Core.Api.PlayerAnimationSyncType)syncType); + Resource.ClearTasks((OpenMp.Core.Api.PlayerAnimationSyncType)syncType); } /// @@ -1950,7 +1933,7 @@ public virtual void ClearTasks(PlayerAnimationSyncType syncType) /// The world time to set; only the whole-hour portion is applied. public virtual void SetWorldTime(TimeSpan time) { - _player.SetWorldTime(time); + Resource.SetWorldTime(time); } /// @@ -1960,7 +1943,7 @@ public virtual void SetWorldTime(TimeSpan time) public virtual void SendCommand(string message) { ArgumentNullException.ThrowIfNull(message); - _player.SendCommand(message); + Resource.SendCommand(message); } /// @@ -1970,7 +1953,7 @@ public virtual void SendCommand(string message) public virtual void StreamInForPlayer(Player target) { ArgumentNullException.ThrowIfNull(target); - _player.StreamInForPlayer(target); + Resource.StreamInForPlayer(target); } /// @@ -1980,7 +1963,7 @@ public virtual void StreamInForPlayer(Player target) public virtual void StreamOutForPlayer(Player target) { ArgumentNullException.ThrowIfNull(target); - _player.StreamOutForPlayer(target); + Resource.StreamOutForPlayer(target); } /// @@ -2006,7 +1989,7 @@ public virtual void SendDownloadUrl(string url) /// protected override void OnDestroyComponent() { - if (!IsOmpEntityDestroyed) + if (!Resource.GetExtension().IsOmpEntityDestroyed) { Kick(); } @@ -2015,6 +1998,10 @@ protected override void OnDestroyComponent() /// public override string ToString() { + if (!IsComponentAlive) + { + return "(Destroyed)"; + } return $"(Id: {Id}, Name: {Name})"; } @@ -2023,6 +2010,6 @@ public override string ToString() /// public static implicit operator IPlayer(Player? player) { - return player?._player ?? default; + return player?.Resource ?? default; } } diff --git a/src/SampSharp.OpenMp.Entities/SAMP/Components/PlayerGangZone.cs b/src/SampSharp.OpenMp.Entities/SAMP/Components/PlayerGangZone.cs index 3f61355f..35303daf 100644 --- a/src/SampSharp.OpenMp.Entities/SAMP/Components/PlayerGangZone.cs +++ b/src/SampSharp.OpenMp.Entities/SAMP/Components/PlayerGangZone.cs @@ -13,7 +13,6 @@ namespace SampSharp.Entities.SAMP; /// public class PlayerGangZone : BaseGangZone { - private readonly IGangZone _gangZone; private readonly Player _player; /// @@ -22,17 +21,26 @@ public class PlayerGangZone : BaseGangZone protected PlayerGangZone(IOmpEntityProvider entityProvider, IGangZonesComponent gangZones, IGangZone gangZone, Player player) : base(entityProvider, gangZones, gangZone) { - _gangZone = gangZone; + Resource = gangZone; _player = player; } + private IGangZone Resource + { + get + { + ObjectDisposedException.ThrowIf(!IsComponentAlive, typeof(PlayerGangZone)); + return field; + } + } + /// /// Shows this gang zone to the player. /// public virtual void Show() { Colour clr = Color; - _gangZone.ShowForPlayer(_player, ref clr); + Resource.ShowForPlayer(_player, ref clr); } @@ -41,7 +49,7 @@ public virtual void Show() /// public virtual void Hide() { - _gangZone.HideForPlayer(_player); + Resource.HideForPlayer(_player); } /// @@ -51,7 +59,7 @@ public virtual void Hide() public virtual void Flash(Color color) { Colour clr = color; - _gangZone.FlashForPlayer(_player, ref clr); + Resource.FlashForPlayer(_player, ref clr); } /// @@ -59,7 +67,7 @@ public virtual void Flash(Color color) /// public virtual void StopFlash() { - _gangZone.StopFlashForPlayer(_player); + Resource.StopFlashForPlayer(_player); } /// @@ -68,7 +76,7 @@ public virtual void StopFlash() /// if shown; otherwise . public virtual bool IsShown() { - return _gangZone.IsShownForPlayer(_player); + return Resource.IsShownForPlayer(_player); } /// @@ -77,7 +85,7 @@ public virtual bool IsShown() /// if flashing; otherwise . public virtual bool IsFlashing() { - return _gangZone.IsFlashingForPlayer(_player); + return Resource.IsFlashingForPlayer(_player); } /// @@ -86,7 +94,7 @@ public virtual bool IsFlashing() /// The flashing color. public virtual Color GetFlashingColor() { - return _gangZone.GetFlashingColourForPlayer(_player); + return Resource.GetFlashingColourForPlayer(_player); } /// @@ -99,7 +107,7 @@ public virtual Color GetFlashingColor() /// if the player is inside; otherwise . public virtual bool IsPlayerInside() { - return _gangZone.IsPlayerInside(_player); + return Resource.IsPlayerInside(_player); } } diff --git a/src/SampSharp.OpenMp.Entities/SAMP/Components/PlayerObject.cs b/src/SampSharp.OpenMp.Entities/SAMP/Components/PlayerObject.cs index 12cdde5c..31086b5a 100644 --- a/src/SampSharp.OpenMp.Entities/SAMP/Components/PlayerObject.cs +++ b/src/SampSharp.OpenMp.Entities/SAMP/Components/PlayerObject.cs @@ -9,7 +9,6 @@ namespace SampSharp.Entities.SAMP; public class PlayerObject : WorldEntity { private readonly IOmpEntityProvider _entityProvider; - private readonly IPlayerObject _playerObject; private readonly IPlayerObjectData _playerObjects; /// @@ -19,36 +18,40 @@ protected PlayerObject(IOmpEntityProvider entityProvider, IPlayerObjectData play { _entityProvider = entityProvider; _playerObjects = playerObjects; - _playerObject = playerObject; + Resource = playerObject; } - /// - /// Gets a value indicating whether the open.mp entity counterpart has been destroyed. - /// - protected bool IsOmpEntityDestroyed => _playerObject.TryGetExtension()?.IsOmpEntityDestroyed ?? true; + private IPlayerObject Resource + { + get + { + ObjectDisposedException.ThrowIf(!IsComponentAlive, typeof(PlayerObject)); + return field; + } + } /// /// Gets a value indicating whether this player object is moving. /// - public virtual bool IsMoving => _playerObject.IsMoving(); + public virtual bool IsMoving => Resource.IsMoving(); /// /// Gets the model ID of this player object. /// - public virtual int ModelId => _playerObject.GetModel(); + public virtual int ModelId => Resource.GetModel(); /// /// Gets the draw distance of this player object. /// - public virtual float DrawDistance => _playerObject.GetDrawDistance(); + public virtual float DrawDistance => Resource.GetDrawDistance(); /// /// Gets or sets a value indicating whether this player object collides with the player's camera. /// public virtual bool HasCameraCollision { - get => _playerObject.GetCameraCollision(); - set => _playerObject.SetCameraCollision(value); + get => Resource.GetCameraCollision(); + set => Resource.SetCameraCollision(value); } /// @@ -58,7 +61,7 @@ public virtual Player? AttachedPlayer { get { - var data = _playerObject.GetAttachmentData(); + var data = Resource.GetAttachmentData(); return data.Type == AttachmentType.Player ? _entityProvider.GetPlayer(data.Id) : null; } } @@ -70,7 +73,7 @@ public virtual Vehicle? AttachedVehicle { get { - var data = _playerObject.GetAttachmentData(); + var data = Resource.GetAttachmentData(); return data.Type == AttachmentType.Vehicle ? _entityProvider.GetVehicle(data.Id) : null; } } @@ -87,7 +90,7 @@ public virtual TimeSpan Move(Vector3 position, float speed, Vector3 rotation) var time = (position - Position).Length() / speed; var moveDat = new ObjectMoveData(position, rotation, speed); - _playerObject.Move(ref moveDat); + Resource.Move(ref moveDat); return TimeSpan.FromSeconds(time); } @@ -108,7 +111,7 @@ public virtual TimeSpan Move(Vector3 position, float speed) /// public virtual void Stop() { - _playerObject.Stop(); + Resource.Stop(); } /// @@ -124,7 +127,7 @@ public virtual void SetMaterial(int materialIndex, int modelId, string txdName, ArgumentNullException.ThrowIfNull(txdName); ArgumentNullException.ThrowIfNull(textureName); - _playerObject.SetMaterial((uint)materialIndex, modelId, txdName, textureName, materialColor); + Resource.SetMaterial((uint)materialIndex, modelId, txdName, textureName, materialColor); } /// @@ -147,7 +150,7 @@ public virtual void SetMaterialText(int materialIndex, string text, ObjectMateri ArgumentOutOfRangeException.ThrowIfGreaterThan(text.Length, 2048, nameof(text)); ArgumentOutOfRangeException.ThrowIfGreaterThan(fontSize, 255, nameof(fontSize)); - _playerObject.SetMaterialText((uint)materialIndex, text, (OpenMp.Core.Api.ObjectMaterialSize)materialSize, fontface, fontSize, bold, foreColor, backColor, + Resource.SetMaterialText((uint)materialIndex, text, (OpenMp.Core.Api.ObjectMaterialSize)materialSize, fontface, fontSize, bold, foreColor, backColor, (OpenMp.Core.Api.ObjectMaterialTextAlign)textAlignment); } @@ -156,7 +159,7 @@ public virtual void SetMaterialText(int materialIndex, string text, ObjectMateri /// public virtual void DisableCameraCollisions() { - _playerObject.SetCameraCollision(false); + Resource.SetCameraCollision(false); } /// @@ -165,7 +168,7 @@ public virtual void DisableCameraCollisions() /// The describing the current move target. public virtual ObjectMoveData GetMovingData() { - return _playerObject.GetMovingData(); + return Resource.GetMovingData(); } /// @@ -173,7 +176,7 @@ public virtual ObjectMoveData GetMovingData() /// public virtual void ResetAttachment() { - _playerObject.ResetAttachment(); + Resource.ResetAttachment(); } /// @@ -183,7 +186,7 @@ public virtual void ResetAttachment() /// The material data, or if no material has been set in that slot. public virtual ObjectMaterialData? GetMaterialData(int materialIndex) { - return _playerObject.GetMaterialData((uint)materialIndex, out var data) ? data : null; + return Resource.GetMaterialData((uint)materialIndex, out var data) ? data : null; } /// @@ -196,7 +199,7 @@ public virtual void AttachTo(Player target, Vector3 offset, Vector3 rotation) { ArgumentNullException.ThrowIfNull(target); - _playerObject.AttachToPlayer(target, offset, rotation); + Resource.AttachToPlayer(target, offset, rotation); } /// @@ -209,7 +212,7 @@ public virtual void AttachTo(Vehicle target, Vector3 offset, Vector3 rotation) { ArgumentNullException.ThrowIfNull(target); - _playerObject.AttachToVehicle(target, offset, rotation); + Resource.AttachToVehicle(target, offset, rotation); } /// @@ -222,13 +225,13 @@ public virtual void AttachTo(PlayerObject target, Vector3 offset, Vector3 rotati { ArgumentNullException.ThrowIfNull(target); - _playerObject.AttachToObject(target, offset, rotation); + Resource.AttachToObject(target, offset, rotation); } /// protected override void OnDestroyComponent() { - if (!IsOmpEntityDestroyed) + if (!Resource.GetExtension().IsOmpEntityDestroyed) { _playerObjects.Release(Id); } @@ -237,6 +240,10 @@ protected override void OnDestroyComponent() /// public override string ToString() { + if (!IsComponentAlive) + { + return "(Destroyed)"; + } return $"(Id: {Id}, Model: {ModelId})"; } @@ -245,6 +252,6 @@ public override string ToString() /// public static implicit operator IPlayerObject(PlayerObject? playerObject) { - return playerObject?._playerObject ?? default; + return playerObject?.Resource ?? default; } } \ No newline at end of file diff --git a/src/SampSharp.OpenMp.Entities/SAMP/Components/PlayerPickup.cs b/src/SampSharp.OpenMp.Entities/SAMP/Components/PlayerPickup.cs index 2c2b8b97..02010ab3 100644 --- a/src/SampSharp.OpenMp.Entities/SAMP/Components/PlayerPickup.cs +++ b/src/SampSharp.OpenMp.Entities/SAMP/Components/PlayerPickup.cs @@ -13,7 +13,6 @@ namespace SampSharp.Entities.SAMP; /// public class PlayerPickup : BasePickup { - private readonly IPickup _pickup; private readonly Player _player; /// @@ -21,26 +20,36 @@ public class PlayerPickup : BasePickup /// protected PlayerPickup(IPickupsComponent pickups, IPickup pickup, Player player) : base(pickups, pickup) { - _pickup = pickup; + Resource = pickup; _player = player; } + private IPickup Resource + { + get + { + ObjectDisposedException.ThrowIf(!IsComponentAlive, typeof(PlayerPickup)); + return field; + } + } + + /// Checks whether this pickup is streamed in for the player. /// if streamed in; otherwise . public virtual bool IsStreamedIn() { - return _pickup.IsStreamedInForPlayer(_player); + return Resource.IsStreamedInForPlayer(_player); } /// Streams this pickup in for the player. public virtual void StreamIn() { - _pickup.StreamInForPlayer(_player); + Resource.StreamInForPlayer(_player); } /// Streams this pickup out for the player. public virtual void StreamOut() { - _pickup.StreamOutForPlayer(_player); + Resource.StreamOutForPlayer(_player); } } diff --git a/src/SampSharp.OpenMp.Entities/SAMP/Components/PlayerTextDraw.cs b/src/SampSharp.OpenMp.Entities/SAMP/Components/PlayerTextDraw.cs index 6e33dae9..b801f6c1 100644 --- a/src/SampSharp.OpenMp.Entities/SAMP/Components/PlayerTextDraw.cs +++ b/src/SampSharp.OpenMp.Entities/SAMP/Components/PlayerTextDraw.cs @@ -8,7 +8,6 @@ namespace SampSharp.Entities.SAMP; /// public class PlayerTextDraw : IdProvider { - private readonly IPlayerTextDraw _playerTextDraw; private readonly IPlayerTextDrawData _playerTextDraws; /// @@ -17,21 +16,25 @@ public class PlayerTextDraw : IdProvider protected PlayerTextDraw(IPlayerTextDrawData playerTextDraws, IPlayerTextDraw playerTextDraw) : base((IIDProvider)playerTextDraw) { _playerTextDraws = playerTextDraws; - _playerTextDraw = playerTextDraw; + Resource = playerTextDraw; } - /// - /// Gets a value indicating whether the open.mp entity counterpart has been destroyed. - /// - protected bool IsOmpEntityDestroyed => _playerTextDraw.TryGetExtension()?.IsOmpEntityDestroyed ?? true; + private IPlayerTextDraw Resource + { + get + { + ObjectDisposedException.ThrowIf(!IsComponentAlive, typeof(PlayerTextDraw)); + return field; + } + } /// /// Gets or sets the size of the letters in this text draw. /// public virtual Vector2 LetterSize { - get => _playerTextDraw.GetLetterSize(); - set => _playerTextDraw.SetLetterSize(value); + get => Resource.GetLetterSize(); + set => Resource.SetLetterSize(value); } /// @@ -39,8 +42,8 @@ public virtual Vector2 LetterSize /// public virtual Vector2 TextSize { - get => _playerTextDraw.GetTextSize(); - set => _playerTextDraw.SetTextSize(value); + get => Resource.GetTextSize(); + set => Resource.SetTextSize(value); } /// @@ -48,8 +51,8 @@ public virtual Vector2 TextSize /// public virtual TextDrawAlignment Alignment { - get => (TextDrawAlignment)_playerTextDraw.GetAlignment(); - set => _playerTextDraw.SetAlignment((TextDrawAlignmentTypes)value); + get => (TextDrawAlignment)Resource.GetAlignment(); + set => Resource.SetAlignment((TextDrawAlignmentTypes)value); } /// @@ -57,8 +60,8 @@ public virtual TextDrawAlignment Alignment /// public virtual Color ForeColor { - get => _playerTextDraw.GetLetterColour(); - set => _playerTextDraw.SetColour(value); + get => Resource.GetLetterColour(); + set => Resource.SetColour(value); } /// @@ -66,8 +69,8 @@ public virtual Color ForeColor /// public virtual bool UseBox { - get => _playerTextDraw.HasBox(); - set => _playerTextDraw.UseBox(value); + get => Resource.HasBox(); + set => Resource.UseBox(value); } /// @@ -77,10 +80,10 @@ public virtual Color BoxColor { get { - _playerTextDraw.GetBoxColour(out var colour); + Resource.GetBoxColour(out var colour); return colour; } - set => _playerTextDraw.SetBoxColour(value); + set => Resource.SetBoxColour(value); } /// @@ -88,8 +91,8 @@ public virtual Color BoxColor /// public virtual int Shadow { - get => _playerTextDraw.GetShadow(); - set => _playerTextDraw.SetShadow(value); + get => Resource.GetShadow(); + set => Resource.SetShadow(value); } /// @@ -97,8 +100,8 @@ public virtual int Shadow /// public virtual int Outline { - get => _playerTextDraw.GetOutline(); - set => _playerTextDraw.SetOutline(value); + get => Resource.GetOutline(); + set => Resource.SetOutline(value); } /// @@ -106,8 +109,8 @@ public virtual int Outline /// public virtual Color BackColor { - get => _playerTextDraw.GetBackgroundColour(); - set => _playerTextDraw.SetBackgroundColour(value); + get => Resource.GetBackgroundColour(); + set => Resource.SetBackgroundColour(value); } /// @@ -115,8 +118,8 @@ public virtual Color BackColor /// public virtual TextDrawFont Font { - get => (TextDrawFont)_playerTextDraw.GetStyle(); - set => _playerTextDraw.SetStyle((TextDrawStyle)value); + get => (TextDrawFont)Resource.GetStyle(); + set => Resource.SetStyle((TextDrawStyle)value); } /// @@ -124,8 +127,8 @@ public virtual TextDrawFont Font /// public virtual bool Proportional { - get => _playerTextDraw.IsProportional(); - set => _playerTextDraw.SetProportional(value); + get => Resource.IsProportional(); + set => Resource.SetProportional(value); } /// @@ -133,8 +136,8 @@ public virtual bool Proportional /// public virtual bool Selectable { - get => _playerTextDraw.IsSelectable(); - set => _playerTextDraw.SetSelectable(value); + get => Resource.IsSelectable(); + set => Resource.SetSelectable(value); } /// @@ -142,8 +145,8 @@ public virtual bool Selectable /// public virtual string Text { - get => _playerTextDraw.GetText(); - set => _playerTextDraw.SetText(string.IsNullOrEmpty(value) ? "_" : value); + get => Resource.GetText(); + set => Resource.SetText(string.IsNullOrEmpty(value) ? "_" : value); } /// @@ -151,8 +154,8 @@ public virtual string Text /// public virtual int PreviewModel { - get => _playerTextDraw.GetPreviewModel(); - set => _playerTextDraw.SetPreviewModel(value); + get => Resource.GetPreviewModel(); + set => Resource.SetPreviewModel(value); } /// @@ -160,8 +163,8 @@ public virtual int PreviewModel /// public virtual Vector2 Position { - get => _playerTextDraw.GetPosition(); - set => _playerTextDraw.SetPosition(value); + get => Resource.GetPosition(); + set => Resource.SetPosition(value); } /// @@ -169,21 +172,21 @@ public virtual Vector2 Position /// public virtual Vector3 PreviewRotation { - get => _playerTextDraw.GetPreviewRotation(); - set => _playerTextDraw.SetPreviewRotation(value); + get => Resource.GetPreviewRotation(); + set => Resource.SetPreviewRotation(value); } /// /// Gets the preview model zoom of this text draw. /// - public virtual float PreviewZoom => _playerTextDraw.GetPreviewZoom(); + public virtual float PreviewZoom => Resource.GetPreviewZoom(); /// /// Forces this text draw to be re-sent to the player. /// public virtual void Restream() { - _playerTextDraw.Restream(); + Resource.Restream(); } /// @@ -193,8 +196,8 @@ public virtual void Restream() /// The zoom level of the preview model. public virtual void SetPreviewRotation(Vector3 rotation, float zoom = 1.0f) { - _playerTextDraw.SetPreviewRotation(rotation); - _playerTextDraw.SetPreviewZoom(zoom); + Resource.SetPreviewRotation(rotation); + Resource.SetPreviewZoom(zoom); } /// @@ -204,7 +207,7 @@ public virtual void SetPreviewRotation(Vector3 rotation, float zoom = 1.0f) /// The secondary color of the preview vehicle. public virtual void SetPreviewVehicleColor(int color1, int color2) { - _playerTextDraw.SetPreviewVehicleColour(color1, color2); + Resource.SetPreviewVehicleColour(color1, color2); } /// @@ -212,7 +215,7 @@ public virtual void SetPreviewVehicleColor(int color1, int color2) /// public virtual void Show() { - _playerTextDraw.Show(); + Resource.Show(); } /// @@ -220,13 +223,13 @@ public virtual void Show() /// public virtual void Hide() { - _playerTextDraw.Hide(); + Resource.Hide(); } /// protected override void OnDestroyComponent() { - if (!IsOmpEntityDestroyed) + if (!Resource.GetExtension().IsOmpEntityDestroyed) { _playerTextDraws.AsPool().Release(Id); } @@ -235,6 +238,10 @@ protected override void OnDestroyComponent() /// public override string ToString() { + if (!IsComponentAlive) + { + return "(Destroyed)"; + } return $"(Id: {Id}, Text: {Text})"; } @@ -243,6 +250,6 @@ public override string ToString() /// public static implicit operator IPlayerTextDraw(PlayerTextDraw? playerTextDraw) { - return playerTextDraw?._playerTextDraw ?? default; + return playerTextDraw?.Resource ?? default; } } \ No newline at end of file diff --git a/src/SampSharp.OpenMp.Entities/SAMP/Components/PlayerTextLabel.cs b/src/SampSharp.OpenMp.Entities/SAMP/Components/PlayerTextLabel.cs index 5ab575d9..434e97dc 100644 --- a/src/SampSharp.OpenMp.Entities/SAMP/Components/PlayerTextLabel.cs +++ b/src/SampSharp.OpenMp.Entities/SAMP/Components/PlayerTextLabel.cs @@ -9,7 +9,6 @@ namespace SampSharp.Entities.SAMP; public class PlayerTextLabel : WorldEntity { private readonly IOmpEntityProvider _entityProvider; - private readonly IPlayerTextLabel _playerTextLabel; private readonly IPlayerTextLabelData _playerTextLabels; /// @@ -19,13 +18,17 @@ protected PlayerTextLabel(IOmpEntityProvider entityProvider, IPlayerTextLabelDat { _entityProvider = entityProvider; _playerTextLabels = playerTextLabels; - _playerTextLabel = playerTextLabel; + Resource = playerTextLabel; } - /// - /// Gets a value indicating whether the open.mp entity counterpart has been destroyed. - /// - protected bool IsOmpEntityDestroyed => _playerTextLabel.TryGetExtension()?.IsOmpEntityDestroyed ?? true; + private IPlayerTextLabel Resource + { + get + { + ObjectDisposedException.ThrowIf(!IsComponentAlive, typeof(PlayerTextLabel)); + return field; + } + } /// /// Gets the of this player text label. @@ -34,7 +37,7 @@ public virtual Color Color { get { - _playerTextLabel.GetColour(out var colour); + Resource.GetColour(out var colour); return colour; } } @@ -42,17 +45,17 @@ public virtual Color Color /// /// Gets the text displayed in this player text label. /// - public virtual string Text => _playerTextLabel.GetText(); + public virtual string Text => Resource.GetText(); /// /// Gets the draw distance of this player text label. /// - public virtual float DrawDistance => _playerTextLabel.GetDrawDistance(); + public virtual float DrawDistance => Resource.GetDrawDistance(); /// /// Gets a value indicating whether line-of-sight testing is enabled for this player text label. /// - public virtual bool TestLos => _playerTextLabel.GetTestLOS(); + public virtual bool TestLos => Resource.GetTestLOS(); /// /// Gets the entity this player text label is attached to, if any. @@ -61,7 +64,7 @@ public virtual Component? AttachedEntity { get { - var attachmentData = _playerTextLabel.GetAttachmentData(); + var attachmentData = Resource.GetAttachmentData(); if (attachmentData.PlayerId != OpenMpConstants.INVALID_PLAYER_ID) { @@ -80,12 +83,12 @@ public virtual Component? AttachedEntity /// /// Gets the this text label is attached to, or if it is not attached to a player. /// - public virtual Player? AttachedPlayer => _entityProvider.GetPlayer(_playerTextLabel.GetAttachmentData().PlayerId); + public virtual Player? AttachedPlayer => _entityProvider.GetPlayer(Resource.GetAttachmentData().PlayerId); /// /// Gets the this text label is attached to, or if it is not attached to a vehicle. /// - public virtual Vehicle? AttachedVehicle => _entityProvider.GetVehicle(_playerTextLabel.GetAttachmentData().VehicleId); + public virtual Vehicle? AttachedVehicle => _entityProvider.GetVehicle(Resource.GetAttachmentData().VehicleId); /// /// Attaches this player text label to the specified . @@ -96,7 +99,7 @@ public virtual void Attach(Player player, Vector3 offset = default) { ArgumentNullException.ThrowIfNull(player); - _playerTextLabel.AttachToPlayer(player, offset); + Resource.AttachToPlayer(player, offset); } /// @@ -108,7 +111,7 @@ public virtual void Attach(Vehicle vehicle, Vector3 offset = default) { ArgumentNullException.ThrowIfNull(vehicle); - _playerTextLabel.AttachToVehicle(vehicle, offset); + Resource.AttachToVehicle(vehicle, offset); } /// @@ -117,7 +120,7 @@ public virtual void Attach(Vehicle vehicle, Vector3 offset = default) /// The new world position. public virtual void DetachFromPlayer(Vector3 position) { - _playerTextLabel.DetachFromPlayer(position); + Resource.DetachFromPlayer(position); } /// @@ -126,7 +129,7 @@ public virtual void DetachFromPlayer(Vector3 position) /// The new world position. public virtual void DetachFromVehicle(Vector3 position) { - _playerTextLabel.DetachFromVehicle(position); + Resource.DetachFromVehicle(position); } /// @@ -137,13 +140,13 @@ public virtual void DetachFromVehicle(Vector3 position) public virtual void SetColorAndText(Color color, string text) { ArgumentNullException.ThrowIfNull(text); - _playerTextLabel.SetColourAndText(color, text); + Resource.SetColourAndText(color, text); } /// protected override void OnDestroyComponent() { - if (!IsOmpEntityDestroyed) + if (!Resource.GetExtension().IsOmpEntityDestroyed) { _playerTextLabels.Release(Id); } @@ -152,6 +155,10 @@ protected override void OnDestroyComponent() /// public override string ToString() { + if (!IsComponentAlive) + { + return "(Destroyed)"; + } return $"(Id: {Id}, Text: {Text})"; } @@ -160,6 +167,6 @@ public override string ToString() /// public static implicit operator IPlayerTextLabel(PlayerTextLabel? playerTextLabel) { - return playerTextLabel?._playerTextLabel ?? default; + return playerTextLabel?.Resource ?? default; } } \ No newline at end of file diff --git a/src/SampSharp.OpenMp.Entities/SAMP/Components/TextDraw.cs b/src/SampSharp.OpenMp.Entities/SAMP/Components/TextDraw.cs index b54d2df2..c7fc4e47 100644 --- a/src/SampSharp.OpenMp.Entities/SAMP/Components/TextDraw.cs +++ b/src/SampSharp.OpenMp.Entities/SAMP/Components/TextDraw.cs @@ -8,7 +8,6 @@ namespace SampSharp.Entities.SAMP; /// public class TextDraw : IdProvider { - private readonly ITextDraw _textDraw; private readonly ITextDrawsComponent _textDraws; /// @@ -17,21 +16,25 @@ public class TextDraw : IdProvider protected TextDraw(ITextDrawsComponent textDraws, ITextDraw textDraw) : base((IIDProvider)textDraw) { _textDraws = textDraws; - _textDraw = textDraw; + Resource = textDraw; } - /// - /// Gets a value indicating whether the open.mp entity counterpart has been destroyed. - /// - protected bool IsOmpEntityDestroyed => _textDraw.TryGetExtension()?.IsOmpEntityDestroyed ?? true; + private ITextDraw Resource + { + get + { + ObjectDisposedException.ThrowIf(!IsComponentAlive, typeof(TextDraw)); + return field; + } + } /// /// Gets or sets the size of the letters in this text draw. /// public virtual Vector2 LetterSize { - get => _textDraw.GetLetterSize(); - set => _textDraw.SetLetterSize(value); + get => Resource.GetLetterSize(); + set => Resource.SetLetterSize(value); } /// @@ -39,8 +42,8 @@ public virtual Vector2 LetterSize /// public virtual Vector2 TextSize { - get => _textDraw.GetTextSize(); - set => _textDraw.SetTextSize(value); + get => Resource.GetTextSize(); + set => Resource.SetTextSize(value); } /// @@ -48,8 +51,8 @@ public virtual Vector2 TextSize /// public virtual TextDrawAlignment Alignment { - get => (TextDrawAlignment)_textDraw.GetAlignment(); - set => _textDraw.SetAlignment((TextDrawAlignmentTypes)value); + get => (TextDrawAlignment)Resource.GetAlignment(); + set => Resource.SetAlignment((TextDrawAlignmentTypes)value); } /// @@ -57,8 +60,8 @@ public virtual TextDrawAlignment Alignment /// public virtual Color ForeColor { - get => _textDraw.GetLetterColour(); - set => _textDraw.SetColour(value); + get => Resource.GetLetterColour(); + set => Resource.SetColour(value); } /// @@ -66,8 +69,8 @@ public virtual Color ForeColor /// public virtual bool UseBox { - get => _textDraw.HasBox(); - set => _textDraw.UseBox(value); + get => Resource.HasBox(); + set => Resource.UseBox(value); } /// @@ -77,10 +80,10 @@ public virtual Color BoxColor { get { - _textDraw.GetBoxColour(out var colour); + Resource.GetBoxColour(out var colour); return colour; } - set => _textDraw.SetBoxColour(value); + set => Resource.SetBoxColour(value); } /// @@ -88,8 +91,8 @@ public virtual Color BoxColor /// public virtual int Shadow { - get => _textDraw.GetShadow(); - set => _textDraw.SetShadow(value); + get => Resource.GetShadow(); + set => Resource.SetShadow(value); } /// @@ -97,8 +100,8 @@ public virtual int Shadow /// public virtual int Outline { - get => _textDraw.GetOutline(); - set => _textDraw.SetOutline(value); + get => Resource.GetOutline(); + set => Resource.SetOutline(value); } /// @@ -106,8 +109,8 @@ public virtual int Outline /// public virtual Color BackColor { - get => _textDraw.GetBackgroundColour(); - set => _textDraw.SetBackgroundColour(value); + get => Resource.GetBackgroundColour(); + set => Resource.SetBackgroundColour(value); } /// @@ -115,8 +118,8 @@ public virtual Color BackColor /// public virtual TextDrawFont Font { - get => (TextDrawFont)_textDraw.GetStyle(); - set => _textDraw.SetStyle((TextDrawStyle)value); + get => (TextDrawFont)Resource.GetStyle(); + set => Resource.SetStyle((TextDrawStyle)value); } /// @@ -124,8 +127,8 @@ public virtual TextDrawFont Font /// public virtual bool Proportional { - get => _textDraw.IsProportional(); - set => _textDraw.SetProportional(value); + get => Resource.IsProportional(); + set => Resource.SetProportional(value); } /// @@ -133,8 +136,8 @@ public virtual bool Proportional /// public virtual bool Selectable { - get => _textDraw.IsSelectable(); - set => _textDraw.SetSelectable(value); + get => Resource.IsSelectable(); + set => Resource.SetSelectable(value); } /// @@ -142,8 +145,8 @@ public virtual bool Selectable /// public virtual string Text { - get => _textDraw.GetText(); - set => _textDraw.SetText(string.IsNullOrEmpty(value) ? "_" : value); + get => Resource.GetText(); + set => Resource.SetText(string.IsNullOrEmpty(value) ? "_" : value); } /// @@ -151,8 +154,8 @@ public virtual string Text /// public virtual int PreviewModel { - get => _textDraw.GetPreviewModel(); - set => _textDraw.SetPreviewModel(value); + get => Resource.GetPreviewModel(); + set => Resource.SetPreviewModel(value); } /// @@ -160,8 +163,8 @@ public virtual int PreviewModel /// public virtual Vector2 Position { - get => _textDraw.GetPosition(); - set => _textDraw.SetPosition(value); + get => Resource.GetPosition(); + set => Resource.SetPosition(value); } /// @@ -169,21 +172,21 @@ public virtual Vector2 Position /// public virtual Vector3 PreviewRotation { - get => _textDraw.GetPreviewRotation(); - set => _textDraw.SetPreviewRotation(value); + get => Resource.GetPreviewRotation(); + set => Resource.SetPreviewRotation(value); } /// /// Gets the preview model zoom of this text draw. /// - public virtual float PreviewZoom => _textDraw.GetPreviewZoom(); + public virtual float PreviewZoom => Resource.GetPreviewZoom(); /// /// Forces this text draw to be re-sent to all players who currently have it visible. /// public virtual void Restream() { - _textDraw.Restream(); + Resource.Restream(); } /// @@ -195,7 +198,7 @@ public virtual void SetTextForPlayer(Player player, string text) { ArgumentNullException.ThrowIfNull(player); ArgumentNullException.ThrowIfNull(text); - _textDraw.SetTextForPlayer(player, string.IsNullOrEmpty(text) ? "_" : text); + Resource.SetTextForPlayer(player, string.IsNullOrEmpty(text) ? "_" : text); } /// @@ -205,8 +208,8 @@ public virtual void SetTextForPlayer(Player player, string text) /// The zoom level of the preview model. public virtual void SetPreviewRotation(Vector3 rotation, float zoom = 1.0f) { - _textDraw.SetPreviewRotation(rotation); - _textDraw.SetPreviewZoom(zoom); + Resource.SetPreviewRotation(rotation); + Resource.SetPreviewZoom(zoom); } /// @@ -216,7 +219,7 @@ public virtual void SetPreviewRotation(Vector3 rotation, float zoom = 1.0f) /// The secondary color of the preview vehicle. public virtual void SetPreviewVehicleColor(int color1, int color2) { - _textDraw.SetPreviewVehicleColour(color1, color2); + Resource.SetPreviewVehicleColour(color1, color2); } /// @@ -238,7 +241,7 @@ public virtual void Show(Player player) { ArgumentNullException.ThrowIfNull(player); - _textDraw.ShowForPlayer(player); + Resource.ShowForPlayer(player); } /// @@ -260,13 +263,13 @@ public virtual void Hide(Player player) { ArgumentNullException.ThrowIfNull(player); - _textDraw.HideForPlayer(player); + Resource.HideForPlayer(player); } /// protected override void OnDestroyComponent() { - if (!IsOmpEntityDestroyed) + if (!Resource.GetExtension().IsOmpEntityDestroyed) { _textDraws.AsPool().Release(Id); } @@ -275,6 +278,10 @@ protected override void OnDestroyComponent() /// public override string ToString() { + if (!IsComponentAlive) + { + return "(Destroyed)"; + } return $"(Id: {Id}, Text: {Text})"; } @@ -283,6 +290,6 @@ public override string ToString() /// public static implicit operator ITextDraw(TextDraw? textDraw) { - return textDraw?._textDraw ?? default; + return textDraw?.Resource ?? default; } } \ No newline at end of file diff --git a/src/SampSharp.OpenMp.Entities/SAMP/Components/TextLabel.cs b/src/SampSharp.OpenMp.Entities/SAMP/Components/TextLabel.cs index 78e86bb2..6b7d368f 100644 --- a/src/SampSharp.OpenMp.Entities/SAMP/Components/TextLabel.cs +++ b/src/SampSharp.OpenMp.Entities/SAMP/Components/TextLabel.cs @@ -9,7 +9,6 @@ namespace SampSharp.Entities.SAMP; public class TextLabel : WorldEntity { private readonly IOmpEntityProvider _entityProvider; - private readonly ITextLabel _textLabel; private readonly ITextLabelsComponent _textLabels; /// @@ -19,13 +18,17 @@ protected TextLabel(IOmpEntityProvider entityProvider, ITextLabelsComponent text { _entityProvider = entityProvider; _textLabels = textLabels; - _textLabel = textLabel; + Resource = textLabel; } - /// - /// Gets a value indicating whether the open.mp entity counterpart has been destroyed. - /// - protected bool IsOmpEntityDestroyed => _textLabel.TryGetExtension()?.IsOmpEntityDestroyed ?? true; + private ITextLabel Resource + { + get + { + ObjectDisposedException.ThrowIf(!IsComponentAlive, typeof(TextLabel)); + return field; + } + } /// /// Gets or sets the of this text label. @@ -34,10 +37,10 @@ public virtual Color Color { get { - _textLabel.GetColour(out var colour); + Resource.GetColour(out var colour); return colour; } - set => _textLabel.SetColour(value); + set => Resource.SetColour(value); } /// @@ -45,19 +48,19 @@ public virtual Color Color /// public virtual string Text { - get => _textLabel.GetText(); - set => _textLabel.SetText(value); + get => Resource.GetText(); + set => Resource.SetText(value); } /// /// Gets the draw distance of this text label. /// - public virtual float DrawDistance => _textLabel.GetDrawDistance(); + public virtual float DrawDistance => Resource.GetDrawDistance(); /// /// Gets a value indicating whether line-of-sight testing is enabled for this text label. /// - public virtual bool TestLos => _textLabel.GetTestLOS(); + public virtual bool TestLos => Resource.GetTestLOS(); /// /// Gets the entity this text label is attached to, if any. @@ -66,7 +69,7 @@ public virtual Component? AttachedEntity { get { - var attachmentData = _textLabel.GetAttachmentData(); + var attachmentData = Resource.GetAttachmentData(); if (attachmentData.PlayerId != OpenMpConstants.INVALID_PLAYER_ID) { @@ -85,12 +88,12 @@ public virtual Component? AttachedEntity /// /// Gets the this text label is attached to, or if it is not attached to a player. /// - public virtual Player? AttachedPlayer => _entityProvider.GetPlayer(_textLabel.GetAttachmentData().PlayerId); + public virtual Player? AttachedPlayer => _entityProvider.GetPlayer(Resource.GetAttachmentData().PlayerId); /// /// Gets the this text label is attached to, or if it is not attached to a vehicle. /// - public virtual Vehicle? AttachedVehicle => _entityProvider.GetVehicle(_textLabel.GetAttachmentData().VehicleId); + public virtual Vehicle? AttachedVehicle => _entityProvider.GetVehicle(Resource.GetAttachmentData().VehicleId); /// /// Attaches this text label to the specified . @@ -101,7 +104,7 @@ public virtual void Attach(Player player, Vector3 offset = default) { ArgumentNullException.ThrowIfNull(player); - _textLabel.AttachToPlayer(player, offset); + Resource.AttachToPlayer(player, offset); } /// @@ -113,7 +116,7 @@ public virtual void Attach(Vehicle vehicle, Vector3 offset = default) { ArgumentNullException.ThrowIfNull(vehicle); - _textLabel.AttachToVehicle(vehicle, offset); + Resource.AttachToVehicle(vehicle, offset); } /// @@ -122,7 +125,7 @@ public virtual void Attach(Vehicle vehicle, Vector3 offset = default) /// The new world position. public virtual void DetachFromPlayer(Vector3 position) { - _textLabel.DetachFromPlayer(position); + Resource.DetachFromPlayer(position); } /// @@ -131,7 +134,7 @@ public virtual void DetachFromPlayer(Vector3 position) /// The new world position. public virtual void DetachFromVehicle(Vector3 position) { - _textLabel.DetachFromVehicle(position); + Resource.DetachFromVehicle(position); } /// @@ -142,7 +145,7 @@ public virtual void DetachFromVehicle(Vector3 position) public virtual void SetColorAndText(Color color, string text) { ArgumentNullException.ThrowIfNull(text); - _textLabel.SetColourAndText(color, text); + Resource.SetColourAndText(color, text); } /// @@ -153,7 +156,7 @@ public virtual void SetColorAndText(Color color, string text) public virtual bool IsStreamedInForPlayer(Player player) { ArgumentNullException.ThrowIfNull(player); - return _textLabel.IsStreamedInForPlayer(player); + return Resource.IsStreamedInForPlayer(player); } /// @@ -163,7 +166,7 @@ public virtual bool IsStreamedInForPlayer(Player player) public virtual void StreamInForPlayer(Player player) { ArgumentNullException.ThrowIfNull(player); - _textLabel.StreamInForPlayer(player); + Resource.StreamInForPlayer(player); } /// @@ -173,13 +176,13 @@ public virtual void StreamInForPlayer(Player player) public virtual void StreamOutForPlayer(Player player) { ArgumentNullException.ThrowIfNull(player); - _textLabel.StreamOutForPlayer(player); + Resource.StreamOutForPlayer(player); } /// protected override void OnDestroyComponent() { - if (!IsOmpEntityDestroyed) + if (!Resource.GetExtension().IsOmpEntityDestroyed) { _textLabels.AsPool().Release(Id); } @@ -188,6 +191,10 @@ protected override void OnDestroyComponent() /// public override string ToString() { + if (!IsComponentAlive) + { + return "(Destroyed)"; + } return $"(Id: {Id}, Text: {Text})"; } @@ -196,6 +203,6 @@ public override string ToString() /// public static implicit operator ITextLabel(TextLabel? textLabel) { - return textLabel?._textLabel ?? default; + return textLabel?.Resource ?? default; } } \ No newline at end of file diff --git a/src/SampSharp.OpenMp.Entities/SAMP/Components/Vehicle.cs b/src/SampSharp.OpenMp.Entities/SAMP/Components/Vehicle.cs index 5ca89327..273ba726 100644 --- a/src/SampSharp.OpenMp.Entities/SAMP/Components/Vehicle.cs +++ b/src/SampSharp.OpenMp.Entities/SAMP/Components/Vehicle.cs @@ -9,7 +9,6 @@ namespace SampSharp.Entities.SAMP; public class Vehicle : WorldEntity { private readonly IOmpEntityProvider _entityProvider; - private readonly IVehicle _vehicle; private readonly IVehiclesComponent _vehicles; /// @@ -19,49 +18,53 @@ protected Vehicle(IOmpEntityProvider entityProvider, IVehiclesComponent vehicles { _entityProvider = entityProvider; _vehicles = vehicles; - _vehicle = vehicle; + Resource = vehicle; } - /// - /// Gets a value indicating whether the open.mp entity counterpart has been destroyed. - /// - protected bool IsOmpEntityDestroyed => _vehicle.TryGetExtension()?.IsOmpEntityDestroyed ?? true; + private IVehicle Resource + { + get + { + ObjectDisposedException.ThrowIf(!IsComponentAlive, typeof(Vehicle)); + return field; + } + } /// /// Gets or sets the Z angle of this vehicle. /// public virtual float Angle { - get => _vehicle.GetZAngle(); - set => _vehicle.SetZAngle(value); + get => Resource.GetZAngle(); + set => Resource.SetZAngle(value); } /// /// Gets the model ID of this vehicle. /// - public virtual VehicleModelType Model => (VehicleModelType)_vehicle + public virtual VehicleModelType Model => (VehicleModelType)Resource .GetModel(); /// /// Gets a value indicating whether this vehicle has a trailer attached. /// - public virtual bool HasTrailer => _vehicle.GetTrailer() != null; + public virtual bool HasTrailer => Resource.GetTrailer() != null; /// /// Gets or sets the trailer attached to this vehicle. /// public virtual Vehicle? Trailer { - get => _vehicle.GetTrailer().TryGetExtension()?.Component as Vehicle; + get => Resource.GetTrailer().TryGetExtension()?.Component as Vehicle; set { if (value) { - _vehicle.AttachTrailer(value!); + Resource.AttachTrailer(value!); } else { - _vehicle.DetachTrailer(); + Resource.DetachTrailer(); } } } @@ -71,8 +74,8 @@ public virtual Vehicle? Trailer /// public virtual Vector3 Velocity { - get => _vehicle.GetVelocity(); - set => _vehicle.SetVelocity(value); + get => Resource.GetVelocity(); + set => Resource.SetVelocity(value); } /// @@ -82,13 +85,13 @@ public virtual VehicleParameters Parameters { get { - var parameters = _vehicle.GetParams(); + var parameters = Resource.GetParams(); return VehicleParameters.FromParams(ref parameters); } set { var p = value.ToParams(); - _vehicle.SetParams(ref p); + Resource.SetParams(ref p); } } @@ -99,7 +102,7 @@ public virtual bool Engine { get { - var parameters = _vehicle.GetParams(); + var parameters = Resource.GetParams(); return (VehicleParameterValue)parameters.engine == VehicleParameterValue.On; } set => @@ -116,7 +119,7 @@ public virtual bool Lights { get { - var parameters = _vehicle.GetParams(); + var parameters = Resource.GetParams(); return (VehicleParameterValue)parameters.lights == VehicleParameterValue.On; } set => @@ -133,7 +136,7 @@ public virtual bool Alarm { get { - var parameters = _vehicle.GetParams(); + var parameters = Resource.GetParams(); return (VehicleParameterValue)parameters.alarm == VehicleParameterValue.On; } set => @@ -150,7 +153,7 @@ public virtual bool Doors { get { - var parameters = _vehicle.GetParams(); + var parameters = Resource.GetParams(); return (VehicleParameterValue)parameters.doors == VehicleParameterValue.On; } set => @@ -167,7 +170,7 @@ public virtual bool Bonnet { get { - var parameters = _vehicle.GetParams(); + var parameters = Resource.GetParams(); return (VehicleParameterValue)parameters.bonnet == VehicleParameterValue.On; } set => @@ -184,7 +187,7 @@ public virtual bool Boot { get { - var parameters = _vehicle.GetParams(); + var parameters = Resource.GetParams(); return (VehicleParameterValue)parameters.boot == VehicleParameterValue.On; } set => @@ -201,7 +204,7 @@ public virtual bool Objective { get { - var parameters = _vehicle.GetParams(); + var parameters = Resource.GetParams(); return (VehicleParameterValue)parameters.objective == VehicleParameterValue.On; } set => @@ -218,7 +221,7 @@ public virtual bool IsDriverDoorOpen { get { - var parameters = _vehicle.GetParams(); + var parameters = Resource.GetParams(); return (VehicleParameterValue)parameters.doorDriver == VehicleParameterValue.On; } set => @@ -235,7 +238,7 @@ public virtual bool IsPassengerDoorOpen { get { - var parameters = _vehicle.GetParams(); + var parameters = Resource.GetParams(); return (VehicleParameterValue)parameters.doorPassenger == VehicleParameterValue.On; } set => @@ -252,7 +255,7 @@ public virtual bool IsBackLeftDoorOpen { get { - var parameters = _vehicle.GetParams(); + var parameters = Resource.GetParams(); return (VehicleParameterValue)parameters.doorBackLeft == VehicleParameterValue.On; } set => @@ -269,7 +272,7 @@ public virtual bool IsBackRightDoorOpen { get { - var parameters = _vehicle.GetParams(); + var parameters = Resource.GetParams(); return (VehicleParameterValue)parameters.doorBackRight == VehicleParameterValue.On; } set => @@ -286,7 +289,7 @@ public virtual bool IsDriverWindowClosed { get { - var parameters = _vehicle.GetParams(); + var parameters = Resource.GetParams(); return (VehicleParameterValue)parameters.windowDriver == VehicleParameterValue.On; } set => @@ -303,7 +306,7 @@ public virtual bool IsPassengerWindowClosed { get { - var parameters = _vehicle.GetParams(); + var parameters = Resource.GetParams(); return (VehicleParameterValue)parameters.windowPassenger == VehicleParameterValue.On; } set => @@ -320,7 +323,7 @@ public virtual bool IsBackLeftWindowClosed { get { - var parameters = _vehicle.GetParams(); + var parameters = Resource.GetParams(); return (VehicleParameterValue)parameters.windowBackLeft == VehicleParameterValue.On; } set => @@ -337,7 +340,7 @@ public virtual bool IsBackRightWindowClosed { get { - var parameters = _vehicle.GetParams(); + var parameters = Resource.GetParams(); return (VehicleParameterValue)parameters.windowBackRight == VehicleParameterValue.On; } set => @@ -350,15 +353,15 @@ public virtual bool IsBackRightWindowClosed /// /// Gets a value indicating whether the siren of this vehicle is on. /// - public virtual bool IsSirenOn => _vehicle.GetSirenState() == 1; + public virtual bool IsSirenOn => Resource.GetSirenState() == 1; /// /// Gets or sets the health of this vehicle. /// public virtual float Health { - get => _vehicle.GetHealth(); - set => _vehicle.SetHealth(value); + get => Resource.GetHealth(); + set => Resource.SetHealth(value); } /// @@ -383,8 +386,8 @@ public virtual float Health /// Use 3 to remove the paintjob. public virtual int Paintjob { - get => _vehicle.GetPaintJob(); - set => _vehicle.SetPaintJob(value); + get => Resource.GetPaintJob(); + set => Resource.SetPaintJob(value); } /// @@ -392,8 +395,8 @@ public virtual int Paintjob /// public virtual int Interior { - get => _vehicle.GetInterior(); - set => _vehicle.SetInterior(value); + get => Resource.GetInterior(); + set => Resource.SetInterior(value); } /// @@ -403,7 +406,7 @@ public virtual VehicleSpawnInfo SpawnData { get { - var raw = _vehicle.GetSpawnData(); + var raw = Resource.GetSpawnData(); return new VehicleSpawnInfo( ModelId: raw.modelID, Position: raw.position, @@ -425,7 +428,7 @@ public virtual VehicleSpawnInfo SpawnData colour2: value.SecondaryColor, siren: value.HasSiren, interior: value.Interior); - _vehicle.SetSpawnData(ref raw); + Resource.SetSpawnData(ref raw); } } @@ -435,88 +438,88 @@ public virtual VehicleSpawnInfo SpawnData /// public virtual (int Primary, int Secondary) Colors { - get => _vehicle.GetColour(); - set => _vehicle.SetColour(value.Primary, value.Secondary); + get => Resource.GetColour(); + set => Resource.SetColour(value.Primary, value.Secondary); } /// /// Gets the current numberplate text of this vehicle. /// - public virtual string NumberPlate => _vehicle.GetPlate(); + public virtual string NumberPlate => Resource.GetPlate(); /// /// Gets a value indicating whether this vehicle is dead (destroyed). /// - public virtual bool IsDead => _vehicle.IsDead(); + public virtual bool IsDead => Resource.IsDead(); /// /// Gets a value indicating whether this vehicle is currently in the process of respawning. /// - public virtual bool IsRespawning => _vehicle.IsRespawning(); + public virtual bool IsRespawning => Resource.IsRespawning(); /// /// Gets or sets the respawn delay for this vehicle. /// public virtual TimeSpan RespawnDelay { - get => _vehicle.GetRespawnDelay(); - set => _vehicle.SetRespawnDelay(value); + get => Resource.GetRespawnDelay(); + set => Resource.SetRespawnDelay(value); } /// /// Gets a value indicating whether this vehicle has ever been occupied. /// - public virtual bool HasBeenOccupied => _vehicle.HasBeenOccupied(); + public virtual bool HasBeenOccupied => Resource.HasBeenOccupied(); /// /// Gets a value indicating whether this vehicle is currently occupied. /// - public virtual bool IsOccupied => _vehicle.IsOccupied(); + public virtual bool IsOccupied => Resource.IsOccupied(); /// /// Gets the timestamp at which this vehicle was last occupied. /// - public virtual DateTimeOffset LastOccupiedTime => _vehicle.GetLastOccupiedTime(); + public virtual DateTimeOffset LastOccupiedTime => Resource.GetLastOccupiedTime(); /// /// Gets the timestamp at which this vehicle was last spawned. /// - public virtual DateTimeOffset LastSpawnTime => _vehicle.GetLastSpawnTime(); + public virtual DateTimeOffset LastSpawnTime => Resource.GetLastSpawnTime(); /// /// Gets the player pool ID of the last driver of this vehicle. /// - public virtual int LastDriverPoolID => _vehicle.GetLastDriverPoolID(); + public virtual int LastDriverPoolID => Resource.GetLastDriverPoolID(); /// /// Gets a value indicating whether this vehicle is a trailer (i.e. is being towed by another vehicle). /// - public virtual bool IsTrailer => _vehicle.IsTrailer(); + public virtual bool IsTrailer => Resource.IsTrailer(); /// /// Gets the cab (towing vehicle) currently towing this vehicle, or if there is none. /// - public virtual Vehicle? Cab => _entityProvider.GetComponent(_vehicle.GetCab()); + public virtual Vehicle? Cab => _entityProvider.GetComponent(Resource.GetCab()); /// /// Gets the current driver of this vehicle, or if there is none. /// - public virtual Player? Driver => _entityProvider.GetComponent(_vehicle.GetDriver()); + public virtual Player? Driver => _entityProvider.GetComponent(Resource.GetDriver()); /// /// Gets the current Hydra (jet) thrust angle of this vehicle. /// - public virtual uint HydraThrustAngle => _vehicle.GetHydraThrustAngle(); + public virtual uint HydraThrustAngle => Resource.GetHydraThrustAngle(); /// /// Gets the current train speed of this vehicle. /// - public virtual float TrainSpeed => _vehicle.GetTrainSpeed(); + public virtual float TrainSpeed => Resource.GetTrainSpeed(); /// /// Gets the current state of this vehicle's landing gear. /// - public virtual byte LandingGearState => _vehicle.GetLandingGearState(); + public virtual byte LandingGearState => Resource.GetLandingGearState(); /// /// Calculates the distance between this vehicle and the specified . @@ -537,7 +540,7 @@ public virtual float GetDistanceFromPoint(Vector3 point) public virtual bool IsStreamedIn(Player player) { ArgumentNullException.ThrowIfNull(player); - return _vehicle.IsStreamedInForPlayer(player); + return Resource.IsStreamedInForPlayer(player); } /// @@ -549,7 +552,7 @@ public virtual void SetParametersForPlayer(Player player, in VehicleParameters p { ArgumentNullException.ThrowIfNull(player); var p = parameters.ToParams(); - _vehicle.SetParamsForPlayer(player, ref p); + Resource.SetParamsForPlayer(player, ref p); } /// @@ -557,7 +560,7 @@ public virtual void SetParametersForPlayer(Player player, in VehicleParameters p /// public virtual void Respawn() { - _vehicle.Respawn(); + Resource.Respawn(); } /// @@ -567,7 +570,7 @@ public virtual void Respawn() [Obsolete("Use the Interior property instead.")] public virtual void LinkToInterior(int interiorId) { - _vehicle.SetInterior(interiorId); + Resource.SetInterior(interiorId); } /// @@ -576,7 +579,7 @@ public virtual void LinkToInterior(int interiorId) /// The ID of the component to add. public virtual void AddComponent(int componentId) { - _vehicle.AddComponent(componentId); + Resource.AddComponent(componentId); } /// @@ -585,7 +588,7 @@ public virtual void AddComponent(int componentId) /// The ID of the component to remove. public virtual void RemoveComponent(int componentId) { - _vehicle.RemoveComponent(componentId); + Resource.RemoveComponent(componentId); } /// @@ -615,7 +618,7 @@ public virtual void ChangePaintjob(int paintjobId) /// The license plate text to display. Color embedding is supported. public virtual void SetNumberPlate(string numberplate) { - _vehicle.SetPlate(numberplate); + Resource.SetPlate(numberplate); } /// @@ -625,7 +628,7 @@ public virtual void SetNumberPlate(string numberplate) /// The ID of the component installed in the specified . public virtual int GetComponentInSlot(CarModType slot) { - return _vehicle.GetComponentInSlot((int)slot); + return Resource.GetComponentInSlot((int)slot); } /// @@ -633,7 +636,7 @@ public virtual int GetComponentInSlot(CarModType slot) /// public virtual void Repair() { - _vehicle.Repair(); + Resource.Repair(); } /// @@ -642,7 +645,7 @@ public virtual void Repair() /// The angular velocity to set. public virtual void SetAngularVelocity(Vector3 velocity) { - _vehicle.SetAngularVelocity(velocity); + Resource.SetAngularVelocity(velocity); } /// @@ -654,7 +657,7 @@ public virtual void SetAngularVelocity(Vector3 velocity) /// The tire damage status. public virtual void GetDamageStatus(out int panels, out int doors, out int lights, out int tires) { - _vehicle.GetDamageStatus(out panels, out doors, out lights, out tires); + Resource.GetDamageStatus(out panels, out doors, out lights, out tires); } /// @@ -667,7 +670,7 @@ public virtual void GetDamageStatus(out int panels, out int doors, out int light /// The player updating the vehicle damage, or to update for all players. public virtual void UpdateDamageStatus(int panels, int doors, int lights, int tires, Player? updater = null) { - _vehicle.SetDamageStatus(panels, doors, (byte)lights, (byte)tires, updater ?? default(IPlayer)); + Resource.SetDamageStatus(panels, doors, (byte)lights, (byte)tires, updater ?? default(IPlayer)); } /// @@ -676,7 +679,7 @@ public virtual void UpdateDamageStatus(int panels, int doors, int lights, int ti /// A lazy sequence of components. public virtual IEnumerable GetPassengers() { - foreach (var raw in _vehicle.GetPassengers()) + foreach (var raw in Resource.GetPassengers()) { var component = _entityProvider.GetComponent(raw); if (component != null) @@ -692,7 +695,7 @@ public virtual IEnumerable GetPassengers() /// A lazy sequence of components. public virtual IEnumerable StreamedForPlayers() { - foreach (var raw in _vehicle.StreamedForPlayers()) + foreach (var raw in Resource.StreamedForPlayers()) { var component = _entityProvider.GetComponent(raw); if (component != null) @@ -708,7 +711,7 @@ public virtual IEnumerable StreamedForPlayers() /// to turn the siren on; to turn it off. public virtual void SetSiren(bool enable) { - _vehicle.SetSiren(enable); + Resource.SetSiren(enable); } /// @@ -719,7 +722,7 @@ public virtual void SetSiren(bool enable) public virtual void AddCarriage(Vehicle carriage, int pos) { ArgumentNullException.ThrowIfNull(carriage); - _vehicle.AddCarriage(carriage, pos); + Resource.AddCarriage(carriage, pos); } /// @@ -729,7 +732,7 @@ public virtual void AddCarriage(Vehicle carriage, int pos) /// The new carriage velocity. public virtual void UpdateCarriage(Vector3 position, Vector3 velocity) { - _vehicle.UpdateCarriage(position, velocity); + Resource.UpdateCarriage(position, velocity); } /// @@ -738,7 +741,7 @@ public virtual void UpdateCarriage(Vector3 position, Vector3 velocity) /// A sequence of components representing the carriages. public virtual IEnumerable GetCarriages() { - var array = _vehicle.GetCarriages(); + var array = Resource.GetCarriages(); foreach (var raw in array.Values) { var component = _entityProvider.GetComponent(raw); @@ -752,7 +755,7 @@ public virtual IEnumerable GetCarriages() /// protected override void OnDestroyComponent() { - if (!IsOmpEntityDestroyed) + if (!Resource.GetExtension().IsOmpEntityDestroyed) { _vehicles.AsPool().Release(Id); } @@ -763,7 +766,6 @@ public override string ToString() { if (IsDestroying) { - // TODO: do this check for other components as well return "(Destroyed)"; } @@ -775,6 +777,6 @@ public override string ToString() /// public static implicit operator IVehicle(Vehicle? vehicle) { - return vehicle?._vehicle ?? default; + return vehicle?.Resource ?? default; } } \ No newline at end of file diff --git a/src/SampSharp.OpenMp.Entities/SAMP/Components/WorldEntity.cs b/src/SampSharp.OpenMp.Entities/SAMP/Components/WorldEntity.cs index 64ad1265..2b8a601f 100644 --- a/src/SampSharp.OpenMp.Entities/SAMP/Components/WorldEntity.cs +++ b/src/SampSharp.OpenMp.Entities/SAMP/Components/WorldEntity.cs @@ -8,15 +8,22 @@ namespace SampSharp.Entities.SAMP; /// public abstract class WorldEntity : IdProvider { - private readonly IEntity _entity; - /// /// Initializes a new instance of the class. /// /// The open.mp entity this component represents. protected WorldEntity(IEntity entity) : base((IIDProvider)entity) { - _entity = entity; + Resource = entity; + } + + private IEntity Resource + { + get + { + ObjectDisposedException.ThrowIf(!IsComponentAlive, typeof(WorldEntity)); + return field; + } } /// @@ -24,8 +31,8 @@ protected WorldEntity(IEntity entity) : base((IIDProvider)entity) /// public virtual Vector3 Position { - get => _entity.GetPosition(); - set => _entity.SetPosition(value); + get => Resource.GetPosition(); + set => Resource.SetPosition(value); } /// @@ -33,8 +40,8 @@ public virtual Vector3 Position /// public virtual Quaternion Rotation { - get => _entity.GetRotation(); - set => _entity.SetRotation(value); + get => Resource.GetRotation(); + set => Resource.SetRotation(value); } /// @@ -52,7 +59,7 @@ public virtual Vector3 RotationEuler /// public virtual int VirtualWorld { - get => _entity.GetVirtualWorld(); - set => _entity.SetVirtualWorld(value); + get => Resource.GetVirtualWorld(); + set => Resource.SetVirtualWorld(value); } } \ No newline at end of file diff --git a/test/TestMode.Entities.ApiTests/Infrastructure/Startup.cs b/test/TestMode.Entities.ApiTests/Infrastructure/Startup.cs index 3e10c515..a8665129 100644 --- a/test/TestMode.Entities.ApiTests/Infrastructure/Startup.cs +++ b/test/TestMode.Entities.ApiTests/Infrastructure/Startup.cs @@ -1,4 +1,5 @@ -using SampSharp.Entities; +using Microsoft.Extensions.DependencyInjection; +using SampSharp.Entities; using SampSharp.OpenMp.Core; using Shouldly; @@ -9,6 +10,12 @@ public class Startup : IStartup public void Initialize(IStartupContext context) { ShouldlyConfiguration.DefaultFloatingPointTolerance = 0.0005f; - context.UseEntities(); + context.UseEntities() + .ConfigureServices(services => + { + services.AddSingleton(new TestContext(Directory.GetCurrentDirectory())); + }); } -} \ No newline at end of file +} + +public record TestContext(string ServerDirectory); \ No newline at end of file diff --git a/test/TestMode.Entities.ApiTests/Infrastructure/XunitSystem.cs b/test/TestMode.Entities.ApiTests/Infrastructure/XunitSystem.cs index fb0977f7..c363bbf8 100644 --- a/test/TestMode.Entities.ApiTests/Infrastructure/XunitSystem.cs +++ b/test/TestMode.Entities.ApiTests/Infrastructure/XunitSystem.cs @@ -23,6 +23,7 @@ public void OnGameModeInit(IServerService serverService) { serverService.AddPlayerClass(1, new Vector3(0, 0, 10), 0); + serverService.ConnectNpc("tester", "npcidle"); } diff --git a/test/TestMode.Entities.ApiTests/ServerServiceTests.cs b/test/TestMode.Entities.ApiTests/ServerServiceTests.cs index f25d7de2..6f354b53 100644 --- a/test/TestMode.Entities.ApiTests/ServerServiceTests.cs +++ b/test/TestMode.Entities.ApiTests/ServerServiceTests.cs @@ -41,7 +41,10 @@ public void AddPlayerClass_without_team_should_succeed() [Fact] public void ConnectNpc_should_succeed() { - Sut.ConnectNpc("TestNpc", "npc_script"); + // xunit sets current dir to the assembly directory. reset to server directory, allowing NPC to connect. + Directory.SetCurrentDirectory(Services.GetRequiredService().ServerDirectory); + + Sut.ConnectNpc("TestNpc", "npcidle"); } [Fact]